ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/core/m_nick.c
Revision: 981
Committed: Sun Aug 9 19:09:03 2009 UTC (14 years, 7 months ago) by michael
Content type: text/x-csrc
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

# Content
1 /*
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 * $Id$
23 */
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 #include "watch.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 uid_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, struct Client *server_p);
60 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 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 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 const char *_version = "$Revision$";
96 #endif
97
98
99 /*! \brief NICK command handler (called by unregistered,
100 * locally connected clients)
101 *
102 * \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 */
113 static void
114 mr_nick(struct Client *client_p, struct Client *source_p,
115 int parc, char *parv[])
116 {
117 struct Client *target_p = NULL;
118 char nick[NICKLEN];
119 char *s = NULL;
120
121 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 set_initial_nick(client_p, source_p, nick);
154 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
161 /*! \brief NICK command handler (called by already registered,
162 * locally connected clients)
163 *
164 * \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 */
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 struct Client *target_p = NULL;
181
182 if (parc < 2 || EmptyString(parv[1]))
183 {
184 sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
185 me.name, source_p->name);
186 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 me.name, source_p->name, nick);
201 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 me.name, source_p->name, nick);
210 return;
211 }
212
213 if ((target_p = find_client(nick)) == NULL)
214 change_local_nick(client_p, source_p, nick);
215 else if (target_p == source_p)
216 {
217 /*
218 * If (target_p == source_p) the client is changing nicks between
219 * equivalent nicknames ie: [nick] -> {nick}
220 */
221
222 /* check the nick isnt exactly the same */
223 if (strcmp(target_p->name, nick))
224 change_local_nick(client_p, source_p, nick);
225 }
226 else if (IsUnknown(target_p))
227 {
228 /*
229 * if the client that has the nick isn't registered yet (nick but no
230 * user) then drop the unregged client
231 */
232 exit_client(target_p, &me, "Overridden");
233 change_local_nick(client_p, source_p, nick);
234 }
235 else
236 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
237 source_p->name, nick);
238 }
239
240
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 * server -> server nick change
254 * - parv[0] = sender prefix
255 * - parv[1] = nickname
256 * - parv[2] = TS when nick change
257 *
258 * server introducing new nick
259 * - 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 */
269 static void
270 ms_nick(struct Client *client_p, struct Client *source_p,
271 int parc, char *parv[])
272 {
273 struct Client *target_p = NULL;
274 time_t newts = 0;
275
276 if (parc < 2 || EmptyString(parv[1]))
277 return;
278
279 if (parc == 9)
280 {
281 struct Client *server_p = find_server(parv[7]);
282
283 if (server_p == NULL)
284 {
285 sendto_realops_flags(UMODE_ALL, L_ALL,
286 "Invalid server %s from %s for NICK %s",
287 parv[7], source_p->name, parv[1]);
288 sendto_one(client_p, ":%s KILL %s :%s (Server doesn't exist!)",
289 me.name, parv[1], me.name);
290 return;
291 }
292
293 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 return;
297
298 if (IsServer(source_p))
299 newts = atol(parv[3]);
300 }
301 else if (parc == 3)
302 {
303 if (IsServer(source_p))
304 /* Servers can't change nicks.. */
305 return;
306
307 if (check_clean_nick(client_p, source_p, parv[1],
308 source_p->servptr))
309 return;
310
311 newts = atol(parv[2]);
312 }
313
314 /* if the nick doesnt exist, allow it and process like normal */
315 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 {
319 /* we're not living in the past anymore, an unknown client is local only. */
320 exit_client(target_p, &me, "Overridden");
321 nick_from_server(client_p, source_p, parc, parv, newts, parv[1], parv[8]);
322 }
323 else if (target_p == source_p)
324 {
325 if (strcmp(target_p->name, parv[1]))
326 nick_from_server(client_p, source_p, parc, parv, newts, parv[1], parv[8]);
327 }
328 else
329 perform_nick_collides(source_p, client_p, target_p, parc, parv,
330 newts, parv[1], parv[8], NULL);
331 }
332
333
334 /*! \brief UID command handler (called by servers)
335 *
336 * \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 */
356 static void
357 ms_uid(struct Client *client_p, struct Client *source_p,
358 int parc, char *parv[])
359 {
360 struct Client *target_p = NULL;
361 time_t newts = 0;
362
363 if (parc != 10 || EmptyString(parv[9]))
364 return;
365
366 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 return;
370
371 newts = atol(parv[3]);
372
373 /*
374 * if there is an ID collision, kill our client, and kill theirs.
375 * 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 if ((target_p = hash_find_id(parv[8])) != NULL)
379 {
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 ++ServerStats.is_kill;
388 SetKilled(target_p);
389 exit_client(target_p, &me, "ID Collision");
390 return;
391 }
392
393 if ((target_p = find_client(parv[1])) == NULL)
394 uid_from_server(client_p, source_p, parc, parv, newts, parv[1], parv[9]);
395 else if (IsUnknown(target_p))
396 {
397 exit_client(target_p, &me, "Overridden");
398 uid_from_server(client_p, source_p, parc, parv, newts, parv[1], parv[9]);
399 }
400 else
401 perform_nick_collides(source_p, client_p, target_p,
402 parc, parv, newts, parv[1], parv[9], parv[8]);
403 }
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 char *nick, struct Client *server_p)
420 {
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 if (!clean_nick_name(nick, 0))
425 {
426 ++ServerStats.is_kill;
427 sendto_realops_flags(UMODE_DEBUG, L_ALL,
428 "Bad/long Nick: %s From: %s(via %s)",
429 nick, server_p->name, client_p->name);
430
431 sendto_one(client_p, ":%s KILL %s :%s (Bad Nickname)",
432 me.name, nick, me.name);
433
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 return 1;
445 }
446
447 return 0;
448 }
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 if (!clean_user_name(user))
464 {
465 ++ServerStats.is_kill;
466 sendto_realops_flags(UMODE_DEBUG, L_ALL,
467 "Bad/Long Username: %s Nickname: %s From: %s(via %s)",
468 user, nick, server_p->name, client_p->name);
469 sendto_one(client_p, ":%s KILL %s :%s (Bad Username)",
470 me.name, nick, me.name);
471 return 1;
472 }
473
474 return 0;
475 }
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 if (!clean_host_name(host))
491 {
492 ++ServerStats.is_kill;
493 sendto_realops_flags(UMODE_DEBUG, L_ALL,
494 "Bad/Long Hostname: %s Nickname: %s From: %s(via %s)",
495 host, nick, server_p->name, client_p->name);
496 sendto_one(client_p, ":%s KILL %s :%s (Bad Hostname)",
497 me.name, nick, me.name);
498 return 1;
499 }
500
501 return 0;
502 }
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 clean_nick_name(const char *nick, const int local)
513 {
514 const char *p = nick;
515 assert(nick &&);
516
517 /* nicks can't start with a digit or - or be 0 length */
518 /* This closer duplicates behaviour of hybrid-6 */
519 if (*p == '-' || (IsDigit(*p) && local) || *p == '\0')
520 return 0;
521
522 for (; *p; ++p)
523 if (!IsNickChar(*p))
524 return 0;
525
526 return p - nick <= (NICKLEN - 1);
527 }
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 clean_user_name(const char *user)
537 {
538 const char *p = user;
539
540 assert(user && *user);
541
542 for (; *p; ++p)
543 if (!IsUserChar(*p))
544 return 0;
545
546 return p - user <= USERLEN;
547 }
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 clean_host_name(const char *host)
556 {
557 const char *p = host;
558
559 assert(host && *host);
560
561 for (; *p; ++p)
562 if (!IsHostChar(*p))
563 return 0;
564
565 return p - host <= HOSTLEN;
566 }
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 int samenick = 0;
576
577 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 strlcpy(source_p->info, parv[8], sizeof(source_p->info));
594 /* copy the nick in place */
595 strcpy(source_p->name, nick);
596 hash_add_client(source_p);
597
598 if (parc > 8)
599 {
600 const char *m;
601
602 /* parse usermodes */
603 for (m = &parv[4][1]; *m; ++m)
604 {
605 unsigned int flag = user_modes[(unsigned char)*m];
606
607 if (flag & UMODE_INVISIBLE)
608 ++Count.invisi;
609 if (flag & UMODE_OPER)
610 ++Count.oper;
611
612 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 return;
618 }
619 }
620 else if (source_p->name[0])
621 {
622 samenick = !irccmp(source_p->name, nick);
623
624 /* client changing their nick */
625 if (!samenick)
626 {
627 watch_check_hash(source_p, RPL_LOGOFF);
628 source_p->tsinfo = newts ? newts : CurrentTime;
629 }
630
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 add_history(source_p, 1);
636 sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
637 ":%s NICK %s :%lu",
638 ID(source_p), nick, (unsigned long)source_p->tsinfo);
639 sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
640 ":%s NICK %s :%lu",
641 source_p->name, nick, (unsigned long)source_p->tsinfo);
642 }
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
651 if (!samenick)
652 watch_check_hash(source_p, RPL_LOGON);
653 }
654
655 /*
656 * client_from_server()
657 */
658 static void
659 uid_from_server(struct Client *client_p, struct Client *source_p, int parc,
660 char *parv[], time_t newts, char *nick, char *ugecos)
661 {
662 const char *m = NULL;
663 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 strlcpy(source_p->info, parv[9], sizeof(source_p->info));
676
677 hash_add_client(source_p);
678 hash_add_id(source_p);
679
680 /* parse usermodes */
681 for (m = &parv[4][1]; *m; ++m)
682 {
683 unsigned int flag = user_modes[(unsigned char)*m];
684
685 if (flag & UMODE_INVISIBLE)
686 ++Count.invisi;
687 if (flag & UMODE_OPER)
688 ++Count.oper;
689
690 source_p->umodes |= flag & SEND_UMODES;
691 }
692
693 register_remote_user(client_p, source_p, parv[5], parv[6],
694 servername, parv[9]);
695 }
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 ++ServerStats.is_kill;
724 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 ++ServerStats.is_kill;
763 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 uid_from_server(client_p, source_p, parc, parv, newts, nick, gecos);
780
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 {
789 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 sendto_one(target_p, form_str(ERR_NICKCOLLISION), me.name,
795 target_p->name, target_p->name);
796
797 ++ServerStats.is_kill;
798 kill_client_ll_serv_butone(NULL, source_p, "%s (Nick change collision)",
799 me.name);
800
801 ++ServerStats.is_kill;
802 kill_client_ll_serv_butone(NULL, target_p, "%s (Nick change collision)",
803 me.name);
804
805 SetKilled(target_p);
806 exit_client(target_p, &me, "Nick collision (new)");
807
808 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 ++ServerStats.is_kill;
832 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 ++ServerStats.is_kill;
862 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