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

Properties

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