ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1155
Committed: Tue Aug 9 20:27:45 2011 UTC (12 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/core/m_nick.c
File size: 26643 byte(s)
Log Message:
- recreate "trunk"

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

Properties

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