ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.1.x/modules/core/m_nick.c
Revision: 896
Committed: Sat Nov 3 08:54:09 2007 UTC (16 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_nick.c
File size: 25259 byte(s)
Log Message:
- Killed s_stats.c

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

Properties

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