ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_nick.c
Revision: 221
Committed: Thu Nov 3 15:36:27 2005 UTC (20 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 27326 byte(s)
Log Message:
- Finished WATCH implementation
- Added missing 'return' after register_remote_user() call in
  nick_from_server() which would cause an extra hash_del/strcpy/hash_add
  combination.

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

Properties

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