ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_nick.c
Revision: 457
Committed: Sun Feb 12 20:30:27 2006 UTC (19 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 25169 byte(s)
Log Message:
- Use set_initial_nick() if an unregistered client is changing between
  equivalent nicks which only differ in cAsE.  That way we properly keep
  the fd note about the client updated.

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_nick.c: Sets a users nick.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #include "handlers.h"
27     #include "client.h"
28     #include "hash.h"
29     #include "ircd.h"
30     #include "numeric.h"
31     #include "s_conf.h"
32     #include "s_stats.h"
33     #include "s_user.h"
34     #include "whowas.h"
35     #include "s_serv.h"
36     #include "send.h"
37     #include "channel.h"
38     #include "resv.h"
39     #include "msg.h"
40     #include "parse.h"
41     #include "modules.h"
42     #include "common.h"
43     #include "packet.h"
44 michael 221 #include "watch.h"
45 adx 30
46     static void m_nick(struct Client *, struct Client *, int, char **);
47     static void mr_nick(struct Client *, struct Client *, int, char **);
48     static void ms_nick(struct Client *, struct Client *, int, char **);
49     static void ms_uid(struct Client *, struct Client *, int, char **);
50    
51     static void nick_from_server(struct Client *, struct Client *, int, char **,
52     time_t, char *, char *);
53     static void client_from_server(struct Client *, struct Client *, int, char **,
54     time_t, char *, char *);
55     static int check_clean_nick(struct Client *client_p, struct Client *source_p,
56     char *nick, char *newnick,
57     struct Client *server_p);
58     static int check_clean_user(struct Client *client_p, char *nick, char *user,
59     struct Client *server_p);
60     static int check_clean_host(struct Client *client_p, char *nick, char *host,
61     struct Client *server_p);
62    
63     static int clean_nick_name(char *, int);
64     static int clean_user_name(char *);
65     static int clean_host_name(char *);
66     static void perform_nick_collides(struct Client *, struct Client *, struct Client *,
67     int, char **, time_t, char *, char *, char *);
68     struct Message nick_msgtab = {
69     "NICK", 0, 0, 1, 0, MFLG_SLOW, 0,
70     {mr_nick, m_nick, ms_nick, m_ignore, m_nick, m_ignore}
71     };
72    
73     struct Message uid_msgtab = {
74     "UID", 0, 0, 10, 0, MFLG_SLOW, 0,
75     {m_ignore, m_ignore, ms_uid, m_ignore, m_ignore, m_ignore}
76     };
77    
78 adx 442 INIT_MODULE(m_nick, "$Revision$")
79 adx 30 {
80     mod_add_cmd(&nick_msgtab);
81     mod_add_cmd(&uid_msgtab);
82     }
83    
84 adx 442 CLEANUP_MODULE
85 adx 30 {
86     mod_del_cmd(&nick_msgtab);
87     mod_del_cmd(&uid_msgtab);
88     }
89    
90     /* mr_nick()
91     *
92     * parv[0] = sender prefix
93     * parv[1] = nickname
94     */
95     static void
96     mr_nick(struct Client *client_p, struct Client *source_p,
97     int parc, char *parv[])
98     {
99 michael 398 struct Client *target_p = NULL;
100 adx 30 char nick[NICKLEN];
101     char *s;
102 michael 398
103 michael 457 if (EmptyString(parv[1]))
104 adx 30 {
105     sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
106     me.name, EmptyString(parv[0]) ? "*" : parv[0]);
107     return;
108     }
109    
110     /* Terminate the nick at the first ~ */
111     /* XXX - Is this still needed?? */
112     if ((s = strchr(parv[1], '~')) != NULL)
113     *s = '\0';
114    
115     /* copy the nick and terminate it */
116     strlcpy(nick, parv[1], sizeof(nick));
117    
118     /* check the nickname is ok */
119     if (!clean_nick_name(nick, 1))
120     {
121     sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
122     me.name, EmptyString(parv[0]) ? "*" : parv[0], parv[1]);
123     return;
124     }
125    
126     /* check if the nick is resv'd */
127     if (find_matching_name_conf(NRESV_TYPE, nick, NULL, NULL, 0) &&
128     !IsExemptResv(source_p))
129     {
130     sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
131     me.name, EmptyString(parv[0]) ? "*" : parv[0], nick);
132     return;
133     }
134    
135 michael 457 if ((target_p = find_client(nick)) == NULL || source_p == target_p)
136 adx 30 {
137 michael 398 set_initial_nick(client_p, source_p, nick);
138     return;
139     }
140 adx 30
141 michael 398 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE),
142     me.name, "*", nick);
143 adx 30 }
144    
145     /* m_nick()
146     *
147     * parv[0] = sender prefix
148     * parv[1] = nickname
149     */
150     static void
151     m_nick(struct Client *client_p, struct Client *source_p,
152     int parc, char *parv[])
153     {
154     char nick[NICKLEN];
155     struct Client *target_p;
156    
157     if (parc < 2 || EmptyString(parv[1]))
158     {
159     sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
160     me.name, parv[0]);
161     return;
162     }
163    
164     /* mark end of grace period, to prevent nickflooding */
165     if (!IsFloodDone(source_p))
166     flood_endgrace(source_p);
167    
168     /* terminate nick to NICKLEN */
169     strlcpy(nick, parv[1], sizeof(nick));
170    
171     /* check the nickname is ok */
172     if (!clean_nick_name(nick, 1))
173     {
174     sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
175     me.name, parv[0], nick);
176     return;
177     }
178    
179     if (find_matching_name_conf(NRESV_TYPE, nick,
180     NULL, NULL, 0) && !IsExemptResv(source_p) &&
181     !(IsOper(source_p) && ConfigFileEntry.oper_pass_resv))
182     {
183     sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
184     me.name, parv[0], nick);
185     return;
186     }
187    
188     if ((target_p = find_client(nick)))
189     {
190     /* If(target_p == source_p) the client is changing nicks between
191     * equivalent nicknames ie: [nick] -> {nick}
192     */
193    
194     if (target_p == source_p)
195     {
196     /* check the nick isnt exactly the same */
197     if (!strcmp(target_p->name, nick))
198     return; /* client is doing :old NICK old ignore it. */
199    
200     change_local_nick(client_p, source_p, nick);
201     return;
202     }
203    
204     /* if the client that has the nick isn't registered yet (nick but no
205     * user) then drop the unregged client
206     */
207     if (IsUnknown(target_p))
208     {
209     /* the old code had an if(MyConnect(target_p)) here.. but I cant see
210     * how that can happen, m_nick() is local only --fl_
211     */
212     exit_client(target_p, &me, "Overridden");
213     change_local_nick(client_p, source_p, nick);
214     return;
215     }
216     else
217     {
218     sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
219     parv[0], nick);
220     return;
221     }
222     }
223     else
224     {
225 michael 398 change_local_nick(client_p,source_p,nick);
226     return;
227 adx 30 }
228     }
229    
230     /*
231     * ms_nick()
232     *
233     * server -> server nick change
234     * parv[0] = sender prefix
235     * parv[1] = nickname
236     * parv[2] = TS when nick change
237     *
238     * server introducing new nick
239     * parv[0] = sender prefix
240     * parv[1] = nickname
241     * parv[2] = hop count
242     * parv[3] = TS
243     * parv[4] = umode
244     * parv[5] = username
245     * parv[6] = hostname
246     * parv[7] = server
247     * parv[8] = ircname
248     */
249     static void
250     ms_nick(struct Client *client_p, struct Client *source_p,
251     int parc, char *parv[])
252     {
253     struct Client* target_p;
254     char nick[NICKLEN];
255     char ngecos[REALLEN + 1];
256     time_t newts = 0;
257     char *nnick = parv[1];
258     char *nhop = parv[2];
259     char *nts = parv[3];
260     char *nusername = parv[5];
261     char *nhost = parv[6];
262     char *nserver = parv[7];
263    
264     if (parc < 2 || EmptyString(nnick))
265     return;
266    
267     /* fix the lengths */
268     strlcpy(nick, nnick, sizeof(nick));
269    
270     if (parc == 9)
271     {
272     struct Client *server_p = find_server(nserver);
273    
274     strlcpy(ngecos, parv[8], sizeof(ngecos));
275    
276     if (server_p == NULL)
277     {
278     sendto_realops_flags(UMODE_ALL, L_ALL,
279     "Invalid server %s from %s for NICK %s",
280     nserver, source_p->name, nick);
281     sendto_one(client_p, ":%s KILL %s :%s (Server doesn't exist!)",
282     me.name, nick, me.name);
283     return;
284     }
285    
286     if (check_clean_nick(client_p, source_p, nick, nnick, server_p) ||
287     check_clean_user(client_p, nick, nusername, server_p) ||
288     check_clean_host(client_p, nick, nhost, server_p))
289     return;
290    
291     /* check the length of the clients gecos */
292     if (strlen(parv[8]) > REALLEN)
293     sendto_realops_flags(UMODE_ALL, L_ALL,
294     "Long realname from server %s for %s",
295     nserver, nnick);
296    
297     if (IsServer(source_p))
298     newts = atol(nts);
299     }
300     else if (parc == 3)
301     {
302     if (IsServer(source_p))
303     /* Server's cant change nicks.. */
304     return;
305    
306     if (check_clean_nick(client_p, source_p, nick, nnick,
307     source_p->servptr))
308     return;
309    
310     /*
311     * Yes, this is right. HOP field is the TS field for parc = 3
312     */
313     newts = atol(nhop);
314     }
315    
316     /* if the nick doesnt exist, allow it and process like normal */
317     if (!(target_p = find_client(nick)))
318     {
319     nick_from_server(client_p, source_p, parc, parv, newts, nick, ngecos);
320     return;
321     }
322    
323     /* we're not living in the past anymore, an unknown client is local only. */
324     if (IsUnknown(target_p))
325     {
326     exit_client(target_p, &me, "Overridden");
327     nick_from_server(client_p, source_p, parc, parv, newts, nick, ngecos);
328     return;
329     }
330    
331     if (target_p == source_p)
332     {
333     if (strcmp(target_p->name, nick))
334     {
335     /* client changing case of nick */
336     nick_from_server(client_p, source_p, parc, parv, newts, nick, ngecos);
337     return;
338     }
339     else
340     /* client not changing nicks at all */
341     return;
342     }
343    
344     perform_nick_collides(source_p, client_p, target_p,
345     parc, parv, newts, nick, ngecos, NULL);
346     }
347    
348     /* ms_uid()
349     *
350     * parv[0] = sender prefix
351     * parv[1] = nickname
352     * parv[2] = hop count
353     * parv[3] = TS
354     * parv[4] = umode
355     * parv[5] = username
356     * parv[6] = hostname
357     * parv[7] = ip
358     * parv[8] = uid
359     * parv[9] = ircname (gecos)
360     */
361     static void
362     ms_uid(struct Client *client_p, struct Client *source_p,
363     int parc, char *parv[])
364     {
365     struct Client *target_p;
366     char nick[NICKLEN];
367     char ugecos[REALLEN + 1];
368     time_t newts = 0;
369     char *unick = parv[1];
370     char *uts = parv[3];
371     char *uname = parv[5];
372     char *uhost = parv[6];
373     char *uid = parv[8];
374    
375     if (EmptyString(unick))
376     return;
377    
378     /* Fix the lengths */
379     strlcpy(nick, parv[1], sizeof(nick));
380     strlcpy(ugecos, parv[9], sizeof(ugecos));
381    
382     if (check_clean_nick(client_p, source_p, nick, unick, source_p) ||
383     check_clean_user(client_p, nick, uname, source_p) ||
384     check_clean_host(client_p, nick, uhost, source_p))
385     return;
386    
387     if (strlen(parv[9]) > REALLEN)
388     sendto_realops_flags(UMODE_ALL, L_ALL, "Long realname from server %s for %s",
389     parv[0], parv[1]);
390    
391     newts = atol(uts);
392    
393     /* if there is an ID collision, kill our client, and kill theirs.
394     * this may generate 401's, but it ensures that both clients always
395     * go, even if the other server refuses to do the right thing.
396     */
397     if ((target_p = hash_find_id(uid)) != NULL)
398     {
399     sendto_realops_flags(UMODE_ALL, L_ALL,
400     "ID collision on %s(%s <- %s)(both killed)",
401     target_p->name, target_p->from->name,
402     client_p->name);
403    
404     kill_client_ll_serv_butone(NULL, target_p, "%s (ID collision)",
405     me.name);
406    
407     ServerStats->is_kill++;
408    
409     SetKilled(target_p);
410     exit_client(target_p, &me, "ID Collision");
411     return;
412     }
413    
414     if ((target_p = find_client(unick)) == NULL)
415     client_from_server(client_p, source_p, parc, parv, newts, nick, ugecos);
416     else if (IsUnknown(target_p))
417     {
418     exit_client(target_p, &me, "Overridden");
419     client_from_server(client_p, source_p, parc, parv, newts, nick, ugecos);
420     }
421     else
422     perform_nick_collides(source_p, client_p, target_p,
423     parc, parv, newts, nick, ugecos, uid);
424     }
425    
426     /* check_clean_nick()
427     *
428     * input - pointer to source
429     * -
430     * - nickname
431     * - truncated nickname
432     * - origin of client
433     * - pointer to server nick is coming from
434     * output - none
435     * side effects - if nickname is erroneous, or a different length to
436     * truncated nickname, return 1
437     */
438     static int
439     check_clean_nick(struct Client *client_p, struct Client *source_p,
440     char *nick, char *newnick, struct Client *server_p)
441     {
442     /* the old code did some wacky stuff here, if the nick is invalid, kill it
443     * and dont bother messing at all
444     */
445     if (!clean_nick_name(nick, 0) || strcmp(nick, newnick))
446     {
447     ServerStats->is_kill++;
448     sendto_realops_flags(UMODE_DEBUG, L_ALL,
449     "Bad Nick: %s From: %s(via %s)",
450     nick, server_p->name, client_p->name);
451    
452     sendto_one(client_p, ":%s KILL %s :%s (Bad Nickname)",
453     me.name, newnick, me.name);
454    
455     /* bad nick change */
456     if (source_p != client_p)
457     {
458     kill_client_ll_serv_butone(client_p, source_p,
459     "%s (Bad Nickname)",
460     me.name);
461     SetKilled(source_p);
462     exit_client(source_p, &me, "Bad Nickname");
463     }
464    
465     return (1);
466     }
467    
468     return (0);
469     }
470    
471     /* check_clean_user()
472     *
473     * input - pointer to client sending data
474     * - nickname
475     * - username to check
476     * - origin of NICK
477     * output - none
478     * side effects - if username is erroneous, return 1
479     */
480     static int
481     check_clean_user(struct Client *client_p, char *nick,
482     char *user, struct Client *server_p)
483     {
484     if (strlen(user) > USERLEN)
485     {
486     ServerStats->is_kill++;
487     sendto_realops_flags(UMODE_DEBUG, L_ALL,
488     "Long Username: %s Nickname: %s From: %s(via %s)",
489     user, nick, server_p->name, client_p->name);
490    
491     sendto_one(client_p, ":%s KILL %s :%s (Bad Username)",
492     me.name, nick, me.name);
493    
494 michael 398 return 1;
495 adx 30 }
496    
497     if (!clean_user_name(user))
498     sendto_realops_flags(UMODE_DEBUG, L_ALL,
499     "Bad Username: %s Nickname: %s From: %s(via %s)",
500     user, nick, server_p->name, client_p->name);
501    
502 michael 398 return 0;
503 adx 30 }
504    
505     /* check_clean_host()
506     *
507     * input - pointer to client sending us data
508     * - nickname
509     * - hostname to check
510     * - source name
511     * output - none
512     * side effects - if hostname is erroneous, return 1
513     */
514     static int
515     check_clean_host(struct Client *client_p, char *nick,
516     char *host, struct Client *server_p)
517     {
518     if (strlen(host) > HOSTLEN)
519     {
520     ServerStats->is_kill++;
521     sendto_realops_flags(UMODE_DEBUG, L_ALL,
522     "Long Hostname: %s Nickname: %s From: %s(via %s)",
523     host, nick, server_p->name, client_p->name);
524    
525     sendto_one(client_p, ":%s KILL %s :%s (Bad Hostname)",
526     me.name, nick, me.name);
527    
528 michael 398 return 1;
529 adx 30 }
530    
531     if (!clean_host_name(host))
532     sendto_realops_flags(UMODE_DEBUG, L_ALL,
533     "Bad Hostname: %s Nickname: %s From: %s(via %s)",
534     host, nick, server_p->name, client_p->name);
535    
536 michael 398 return 0;
537 adx 30 }
538    
539     /* clean_nick_name()
540     *
541     * input - nickname
542     * - whether it's a local nick (1) or remote (0)
543     * output - none
544     * side effects - walks through the nickname, returning 0 if erroneous
545     */
546     static int
547     clean_nick_name(char *nick, int local)
548     {
549     assert(nick);
550    
551     /* nicks cant start with a digit or - or be 0 length */
552     /* This closer duplicates behaviour of hybrid-6 */
553     if (*nick == '-' || (IsDigit(*nick) && local) || *nick == '\0')
554 michael 398 return 0;
555 adx 30
556 michael 398 for (; *nick; ++nick)
557 adx 30 if (!IsNickChar(*nick))
558 michael 398 return 0;
559 adx 30
560 michael 398 return 1;
561 adx 30 }
562    
563     /* clean_user_name()
564     *
565     * input - username
566     * output - none
567     * side effects - walks through the username, returning 0 if erroneous
568     */
569     static int
570     clean_user_name(char *user)
571     {
572     assert(user);
573 michael 398
574     for (; *user; ++user)
575 adx 30 if (!IsUserChar(*user))
576     return 0;
577    
578     return 1;
579     }
580    
581     /* clean_host_name()
582     * input - hostname
583     * output - none
584     * side effects - walks through the hostname, returning 0 if erroneous
585     */
586     static int
587     clean_host_name(char *host)
588     {
589     assert(host);
590 michael 398
591     for (; *host; ++host)
592 adx 30 if (!IsHostChar(*host))
593     return 0;
594    
595     return 1;
596     }
597    
598     /*
599     * nick_from_server()
600     */
601     static void
602     nick_from_server(struct Client *client_p, struct Client *source_p, int parc,
603     char *parv[], time_t newts, char *nick, char *ngecos)
604     {
605 michael 221 int samenick = 0;
606    
607 adx 30 if (IsServer(source_p))
608     {
609     /* A server introducing a new client, change source */
610     source_p = make_client(client_p);
611     dlinkAdd(source_p, &source_p->node, &global_client_list);
612    
613     if (parc > 2)
614     source_p->hopcount = atoi(parv[2]);
615     if (newts)
616     source_p->tsinfo = newts;
617     else
618     {
619     newts = source_p->tsinfo = CurrentTime;
620     ts_warn("Remote nick %s (%s) introduced without a TS", nick, parv[0]);
621     }
622    
623     /* copy the nick in place */
624 michael 398 strlcpy(source_p->name, nick, sizeof(source_p->name));
625 adx 30 hash_add_client(source_p);
626    
627     if (parc > 8)
628     {
629     unsigned int flag;
630     char *m;
631    
632     /* parse usermodes */
633     m = &parv[4][1];
634    
635     while (*m)
636     {
637     flag = user_modes[(unsigned char)*m];
638     if (!(source_p->umodes & UMODE_INVISIBLE) && (flag & UMODE_INVISIBLE))
639     Count.invisi++;
640     if (!(source_p->umodes & UMODE_OPER) && (flag & UMODE_OPER))
641     Count.oper++;
642    
643     source_p->umodes |= flag & SEND_UMODES;
644     m++;
645     }
646    
647     register_remote_user(client_p, source_p, parv[5], parv[6],
648     parv[7], ngecos);
649 michael 221 return;
650 adx 30 }
651     }
652     else if (source_p->name[0])
653     {
654 michael 221 samenick = !irccmp(parv[0], nick);
655 adx 30 /* client changing their nick */
656 michael 221 if (!samenick)
657     {
658 adx 30 source_p->tsinfo = newts ? newts : CurrentTime;
659 michael 221 hash_check_watch(source_p, RPL_LOGOFF);
660     }
661 adx 30
662     sendto_common_channels_local(source_p, 1, ":%s!%s@%s NICK :%s",
663 michael 221 source_p->name, source_p->username,
664 adx 30 source_p->host, nick);
665    
666 michael 221 add_history(source_p, 1);
667 michael 405 sendto_server(client_p, source_p, NULL, CAP_TS6, NOCAPS,
668 adx 30 ":%s NICK %s :%lu",
669     ID(source_p), nick, (unsigned long)source_p->tsinfo);
670 michael 405 sendto_server(client_p, source_p, NULL, NOCAPS, CAP_TS6,
671 adx 30 ":%s NICK %s :%lu",
672     parv[0], nick, (unsigned long)source_p->tsinfo);
673     }
674    
675     /* set the new nick name */
676 michael 221 assert(source_p->name[0]);
677 adx 30
678 michael 221 hash_del_client(source_p);
679 adx 30 strcpy(source_p->name, nick);
680     hash_add_client(source_p);
681 michael 221
682     if (!samenick)
683     hash_check_watch(source_p, RPL_LOGON);
684 adx 30 }
685    
686     /*
687     * client_from_server()
688     */
689     static void
690     client_from_server(struct Client *client_p, struct Client *source_p, int parc,
691     char *parv[], time_t newts, char *nick, char *ugecos)
692     {
693     char *m;
694     unsigned int flag;
695     const char *servername = source_p->name;
696    
697     source_p = make_client(client_p);
698     dlinkAdd(source_p, &source_p->node, &global_client_list);
699    
700     source_p->hopcount = atoi(parv[2]);
701     source_p->tsinfo = newts;
702    
703     /* copy the nick in place */
704     strcpy(source_p->name, nick);
705     strlcpy(source_p->id, parv[8], sizeof(source_p->id));
706     strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
707    
708     hash_add_client(source_p);
709     hash_add_id(source_p);
710    
711     /* parse usermodes */
712     m = &parv[4][1];
713     while (*m)
714     {
715     flag = user_modes[(unsigned char)*m];
716     if (flag & UMODE_INVISIBLE)
717     Count.invisi++;
718     if (flag & UMODE_OPER)
719     Count.oper++;
720    
721     source_p->umodes |= flag & SEND_UMODES;
722     m++;
723     }
724    
725     register_remote_user(client_p, source_p, parv[5], parv[6],
726     servername, ugecos);
727     }
728    
729     static void
730     perform_nick_collides(struct Client *source_p, struct Client *client_p,
731     struct Client *target_p, int parc, char *parv[],
732     time_t newts, char *nick, char *gecos, char *uid)
733     {
734     int sameuser;
735    
736     /* server introducing new nick */
737     if (IsServer(source_p))
738     {
739     /* if we dont have a ts, or their TS's are the same, kill both */
740     if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
741     {
742     sendto_realops_flags(UMODE_ALL, L_ALL,
743     "Nick collision on %s(%s <- %s)(both killed)",
744     target_p->name, target_p->from->name,
745     client_p->name);
746    
747     /* if we have a UID, issue a kill for it */
748     if (uid)
749     sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
750     me.id, uid, me.name);
751    
752     kill_client_ll_serv_butone(NULL, target_p,
753     "%s (Nick collision (new))",
754     me.name);
755     ServerStats->is_kill++;
756     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
757     me.name, target_p->name, target_p->name);
758    
759     SetKilled(target_p);
760     exit_client(target_p, &me, "Nick collision (new)");
761     return;
762     }
763     /* the timestamps are different */
764     else
765     {
766     sameuser = !irccmp(target_p->username, parv[5]) &&
767     !irccmp(target_p->host, parv[6]);
768    
769     /* if the users are the same (loaded a client on a different server)
770     * and the new users ts is older, or the users are different and the
771     * new users ts is newer, ignore the new client and let it do the kill
772     */
773     if ((sameuser && newts < target_p->tsinfo) ||
774     (!sameuser && newts > target_p->tsinfo))
775     {
776     if (uid)
777     sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
778     me.id, uid, me.name);
779     return;
780     }
781     else
782     {
783     if (sameuser)
784     sendto_realops_flags(UMODE_ALL, L_ALL,
785     "Nick collision on %s(%s <- %s)(older killed)",
786     target_p->name, target_p->from->name,
787     client_p->name);
788     else
789     sendto_realops_flags(UMODE_ALL, L_ALL,
790     "Nick collision on %s(%s <- %s)(newer killed)",
791     target_p->name, target_p->from->name,
792     client_p->name);
793    
794     ServerStats->is_kill++;
795     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
796     me.name, target_p->name, target_p->name);
797    
798     /* if it came from a LL server, itd have been source_p,
799     * so we dont need to mark target_p as known
800     */
801     kill_client_ll_serv_butone(source_p, target_p,
802     "%s (Nick collision (new))",
803     me.name);
804    
805     SetKilled(target_p);
806     exit_client(target_p, &me, "Nick collision");
807    
808     if (parc == 9)
809     nick_from_server(client_p, source_p, parc, parv, newts, nick, gecos);
810     else if (parc == 10)
811     client_from_server(client_p, source_p, parc, parv, newts, nick, gecos);
812    
813     return;
814     }
815     }
816     }
817    
818     /* its a client changing nick and causing a collide */
819     if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
820 michael 398 {
821 adx 30 sendto_realops_flags(UMODE_ALL, L_ALL,
822     "Nick change collision from %s to %s(%s <- %s)(both killed)",
823     source_p->name, target_p->name, target_p->from->name,
824     client_p->name);
825    
826     ServerStats->is_kill++;
827     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
828     me.name, target_p->name, target_p->name);
829    
830     /* if we got the message from a LL, it knows about source_p */
831     kill_client_ll_serv_butone(NULL, source_p,
832     "%s (Nick change collision)",
833     me.name);
834    
835     ServerStats->is_kill++;
836    
837     kill_client_ll_serv_butone(NULL, target_p,
838     "%s (Nick change collision)",
839     me.name);
840    
841     SetKilled(target_p);
842     exit_client(target_p, &me, "Nick collision (new)");
843     SetKilled(source_p);
844     exit_client(source_p, &me, "Nick collision (old)");
845     return;
846     }
847     else
848     {
849     sameuser = !irccmp(target_p->username, source_p->username) &&
850     !irccmp(target_p->host, source_p->host);
851    
852     if ((sameuser && newts < target_p->tsinfo) ||
853     (!sameuser && newts > target_p->tsinfo))
854     {
855     if (sameuser)
856     sendto_realops_flags(UMODE_ALL, L_ALL,
857     "Nick change collision from %s to %s(%s <- %s)(older killed)",
858     source_p->name, target_p->name, target_p->from->name,
859     client_p->name);
860     else
861     sendto_realops_flags(UMODE_ALL, L_ALL,
862     "Nick change collision from %s to %s(%s <- %s)(newer killed)",
863     source_p->name, target_p->name, target_p->from->name,
864     client_p->name);
865    
866     ServerStats->is_kill++;
867    
868     /* this won't go back to the incoming link, so LL doesnt matter */
869     kill_client_ll_serv_butone(client_p, source_p,
870     "%s (Nick change collision)",
871     me.name);
872    
873     SetKilled(source_p);
874    
875     if (sameuser)
876     exit_client(source_p, &me, "Nick collision (old)");
877     else
878     exit_client(source_p, &me, "Nick collision (new)");
879     return;
880     }
881     else
882     {
883     if (sameuser)
884     sendto_realops_flags(UMODE_ALL, L_ALL,
885     "Nick collision on %s(%s <- %s)(older killed)",
886     target_p->name, target_p->from->name,
887     client_p->name);
888     else
889     sendto_realops_flags(UMODE_ALL, L_ALL,
890     "Nick collision on %s(%s <- %s)(newer killed)",
891     target_p->name, target_p->from->name,
892     client_p->name);
893    
894     kill_client_ll_serv_butone(source_p, target_p,
895     "%s (Nick collision)",
896     me.name);
897    
898     ServerStats->is_kill++;
899     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
900     me.name, target_p->name, target_p->name);
901    
902     SetKilled(target_p);
903     exit_client(target_p, &me, "Nick collision");
904     }
905     }
906    
907 michael 405 /*
908     * we should only ever call nick_from_server() here, as
909 adx 30 * this is a client changing nick, not a new client
910     */
911     nick_from_server(client_p, source_p, parc, parv, newts, nick, gecos);
912     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision