ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_nick.c
Revision: 876
Committed: Wed Oct 24 21:51:21 2007 UTC (16 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_nick.c
File size: 27413 byte(s)
Log Message:
Backported WATCH

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

Properties

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