ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/core/m_nick.c
Revision: 887
Committed: Thu Nov 1 11:54:48 2007 UTC (16 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 25407 byte(s)
Log Message:
- Backported new ACCEPT code which adds support for n!u@h masks

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

Properties

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