ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 981
Committed: Sun Aug 9 19:09:03 2009 UTC (16 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_nick.c
File size: 25944 byte(s)
Log Message:
- speed up processing of incoming NICK/UID bursts
- fixed archaic bug where bursting servers with missconfigured NICKLEN were able
  to desync the network's nickname database


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

Properties

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