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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1017 - (show annotations)
Tue Oct 27 22:22:38 2009 UTC (10 years, 11 months ago) by michael
File MIME type: text/x-chdr
File size: 26837 byte(s)
- fixed build with --enable-assert
- fixed STATS z reporting correct memory consumption of channel bans/excepts/invites and watchlist entries

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

Properties

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

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