ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/core/m_nick.c
Revision: 885
Committed: Wed Oct 31 18:09:24 2007 UTC (18 years, 8 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_nick.c
File size: 25440 byte(s)
Log Message:
- Removed LazyLinks in 7.2 to stop people from asking why we keep
  broken code for half a decade. LL will be implemented in a smarter
  fashion in due time

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     del_all_accepts(source_p);
680 michael 876 watch_check_hash(source_p, RPL_LOGOFF);
681 adx 30 source_p->tsinfo = newts ? newts : CurrentTime;
682 michael 706 }
683 adx 30
684     sendto_common_channels_local(source_p, 1, ":%s!%s@%s NICK :%s",
685     source_p->name,source_p->username,
686     source_p->host, nick);
687    
688 michael 706 add_history(source_p, 1);
689 michael 885 sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
690 adx 30 ":%s NICK %s :%lu",
691     ID(source_p), nick, (unsigned long)source_p->tsinfo);
692 michael 885 sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
693 adx 30 ":%s NICK %s :%lu",
694     parv[0], nick, (unsigned long)source_p->tsinfo);
695     }
696    
697     /* set the new nick name */
698     if (source_p->name[0])
699     hash_del_client(source_p);
700    
701     strcpy(source_p->name, nick);
702     hash_add_client(source_p);
703 michael 876
704     if (!samenick)
705     watch_check_hash(source_p, RPL_LOGON);
706 adx 30 }
707    
708     /*
709     * client_from_server()
710     */
711     static void
712     client_from_server(struct Client *client_p, struct Client *source_p, int parc,
713     char *parv[], time_t newts, char *nick, char *ugecos)
714     {
715     char *m;
716     unsigned int flag;
717     const char *servername = source_p->name;
718    
719     source_p = make_client(client_p);
720     dlinkAdd(source_p, &source_p->node, &global_client_list);
721    
722     source_p->hopcount = atoi(parv[2]);
723     source_p->tsinfo = newts;
724    
725     /* copy the nick in place */
726     strcpy(source_p->name, nick);
727     strlcpy(source_p->id, parv[8], sizeof(source_p->id));
728     strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
729    
730     hash_add_client(source_p);
731     hash_add_id(source_p);
732    
733     /* parse usermodes */
734     m = &parv[4][1];
735     while (*m)
736     {
737     flag = user_modes[(unsigned char)*m];
738     if (flag & UMODE_INVISIBLE)
739     Count.invisi++;
740     if (flag & UMODE_OPER)
741     Count.oper++;
742    
743     source_p->umodes |= flag & SEND_UMODES;
744     m++;
745     }
746    
747     register_remote_user(client_p, source_p, parv[5], parv[6],
748     servername, ugecos);
749     }
750    
751     static void
752     perform_nick_collides(struct Client *source_p, struct Client *client_p,
753     struct Client *target_p, int parc, char *parv[],
754     time_t newts, char *nick, char *gecos, char *uid)
755     {
756     int sameuser;
757    
758     /* server introducing new nick */
759     if (IsServer(source_p))
760     {
761     /* if we dont have a ts, or their TS's are the same, kill both */
762     if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
763     {
764     sendto_realops_flags(UMODE_ALL, L_ALL,
765     "Nick collision on %s(%s <- %s)(both killed)",
766     target_p->name, target_p->from->name,
767     client_p->name);
768    
769     /* if we have a UID, issue a kill for it */
770     if (uid)
771     sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
772     me.id, uid, me.name);
773    
774     kill_client_ll_serv_butone(NULL, target_p,
775     "%s (Nick collision (new))",
776     me.name);
777     ServerStats->is_kill++;
778     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
779     me.name, target_p->name, target_p->name);
780    
781     SetKilled(target_p);
782     exit_client(target_p, &me, "Nick collision (new)");
783     return;
784     }
785     /* the timestamps are different */
786     else
787     {
788     sameuser = !irccmp(target_p->username, parv[5]) &&
789     !irccmp(target_p->host, parv[6]);
790    
791     /* if the users are the same (loaded a client on a different server)
792     * and the new users ts is older, or the users are different and the
793     * new users ts is newer, ignore the new client and let it do the kill
794     */
795     if ((sameuser && newts < target_p->tsinfo) ||
796     (!sameuser && newts > target_p->tsinfo))
797     {
798     if (uid)
799     sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
800     me.id, uid, me.name);
801     return;
802     }
803     else
804     {
805     if (sameuser)
806     sendto_realops_flags(UMODE_ALL, L_ALL,
807     "Nick collision on %s(%s <- %s)(older killed)",
808     target_p->name, target_p->from->name,
809     client_p->name);
810     else
811     sendto_realops_flags(UMODE_ALL, L_ALL,
812     "Nick collision on %s(%s <- %s)(newer killed)",
813     target_p->name, target_p->from->name,
814     client_p->name);
815    
816     ServerStats->is_kill++;
817     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
818     me.name, target_p->name, target_p->name);
819    
820     /* if it came from a LL server, itd have been source_p,
821     * so we dont need to mark target_p as known
822     */
823     kill_client_ll_serv_butone(source_p, target_p,
824     "%s (Nick collision (new))",
825     me.name);
826    
827     SetKilled(target_p);
828     exit_client(target_p, &me, "Nick collision");
829    
830     if (parc == 9)
831     nick_from_server(client_p, source_p, parc, parv, newts, nick, gecos);
832     else if (parc == 10)
833     client_from_server(client_p, source_p, parc, parv, newts, nick, gecos);
834    
835     return;
836     }
837     }
838     }
839    
840     /* its a client changing nick and causing a collide */
841     if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
842     {
843     sendto_realops_flags(UMODE_ALL, L_ALL,
844     "Nick change collision from %s to %s(%s <- %s)(both killed)",
845     source_p->name, target_p->name, target_p->from->name,
846     client_p->name);
847    
848     ServerStats->is_kill++;
849     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
850     me.name, target_p->name, target_p->name);
851    
852     /* if we got the message from a LL, it knows about source_p */
853     kill_client_ll_serv_butone(NULL, source_p,
854     "%s (Nick change collision)",
855     me.name);
856    
857     ServerStats->is_kill++;
858    
859     kill_client_ll_serv_butone(NULL, target_p,
860     "%s (Nick change collision)",
861     me.name);
862    
863     SetKilled(target_p);
864     exit_client(target_p, &me, "Nick collision (new)");
865     SetKilled(source_p);
866     exit_client(source_p, &me, "Nick collision (old)");
867     return;
868     }
869     else
870     {
871     sameuser = !irccmp(target_p->username, source_p->username) &&
872     !irccmp(target_p->host, source_p->host);
873    
874     if ((sameuser && newts < target_p->tsinfo) ||
875     (!sameuser && newts > target_p->tsinfo))
876     {
877     if (sameuser)
878     sendto_realops_flags(UMODE_ALL, L_ALL,
879     "Nick change collision from %s to %s(%s <- %s)(older killed)",
880     source_p->name, target_p->name, target_p->from->name,
881     client_p->name);
882     else
883     sendto_realops_flags(UMODE_ALL, L_ALL,
884     "Nick change collision from %s to %s(%s <- %s)(newer killed)",
885     source_p->name, target_p->name, target_p->from->name,
886     client_p->name);
887    
888     ServerStats->is_kill++;
889    
890     /* this won't go back to the incoming link, so LL doesnt matter */
891     kill_client_ll_serv_butone(client_p, source_p,
892     "%s (Nick change collision)",
893     me.name);
894    
895     SetKilled(source_p);
896    
897     if (sameuser)
898     exit_client(source_p, &me, "Nick collision (old)");
899     else
900     exit_client(source_p, &me, "Nick collision (new)");
901     return;
902     }
903     else
904     {
905     if (sameuser)
906     sendto_realops_flags(UMODE_ALL, L_ALL,
907     "Nick collision on %s(%s <- %s)(older killed)",
908     target_p->name, target_p->from->name,
909     client_p->name);
910     else
911     sendto_realops_flags(UMODE_ALL, L_ALL,
912     "Nick collision on %s(%s <- %s)(newer killed)",
913     target_p->name, target_p->from->name,
914     client_p->name);
915    
916     kill_client_ll_serv_butone(source_p, target_p,
917     "%s (Nick collision)",
918     me.name);
919    
920     ServerStats->is_kill++;
921     sendto_one(target_p, form_str(ERR_NICKCOLLISION),
922     me.name, target_p->name, target_p->name);
923    
924     SetKilled(target_p);
925     exit_client(target_p, &me, "Nick collision");
926     }
927     }
928    
929     /* we should only ever call nick_from_server() here, as
930     * this is a client changing nick, not a new client
931     */
932     nick_from_server(client_p, source_p, parc, parv, newts, nick, gecos);
933     }

Properties

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