/[svn]/ircd-hybrid/modules/core/m_nick.c
ViewVC logotype

Contents of /ircd-hybrid/modules/core/m_nick.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 460 - (show annotations)
Sun Feb 12 22:22:50 2006 UTC (15 years, 5 months ago) by db
File MIME type: text/x-chdr
File size: 25159 byte(s)
- fixed typo
- fixed argument number
- removed reference to no longer used argument


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

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28