ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.0.x/modules/core/m_nick.c
Revision: 31
Committed: Sun Oct 2 20:34:05 2005 UTC (18 years, 5 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/core/m_nick.c
File size: 27182 byte(s)
Log Message:
- Fix svn:keywords

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

Properties

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