ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_nick.c
Revision: 887
Committed: Thu Nov 1 11:54:48 2007 UTC (16 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_nick.c
File size: 25407 byte(s)
Log Message:
- Backported new ACCEPT code which adds support for n!u@h masks

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

Properties

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