]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/core/m_nick.c
irc_string.h -> match.h, irc_string.h; includes changed
[irc/rqf/shadowircd.git] / modules / core / m_nick.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_nick.c: Sets a users nick.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
66b4a7ae 24 * $Id: m_nick.c 3518 2007-06-22 21:59:09Z jilles $
212380e3 25 */
26
27#include "stdinc.h"
28#include "client.h"
29#include "hash.h"
13ae2f4b 30#include "match.h"
212380e3 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 "hash.h"
37#include "whowas.h"
38#include "s_serv.h"
39#include "send.h"
40#include "channel.h"
d3455e2c 41#include "logger.h"
212380e3 42#include "msg.h"
43#include "parse.h"
44#include "modules.h"
45#include "common.h"
46#include "packet.h"
47#include "scache.h"
48#include "s_newconf.h"
49#include "monitor.h"
50
3f7e0642 51/* Give all UID nicks the same TS. This ensures nick TS is always the same on
52 * all servers for each nick-user pair, also if a user with a UID nick changes
53 * their nick but is collided again (the server detecting the collision will
54 * not propagate the nick change further). -- jilles
55 */
56#define SAVE_NICKTS 100
57
212380e3 58static int mr_nick(struct Client *, struct Client *, int, const char **);
59static int m_nick(struct Client *, struct Client *, int, const char **);
60static int mc_nick(struct Client *, struct Client *, int, const char **);
61static int ms_nick(struct Client *, struct Client *, int, const char **);
62static int ms_uid(struct Client *, struct Client *, int, const char **);
63static int ms_euid(struct Client *, struct Client *, int, const char **);
64static int ms_save(struct Client *, struct Client *, int, const char **);
65static int can_save(struct Client *);
66static void save_user(struct Client *, struct Client *, struct Client *);
0624f969 67static void bad_nickname(struct Client *, const char *);
212380e3 68
69struct Message nick_msgtab = {
70 "NICK", 0, 0, 0, MFLG_SLOW,
71 {{mr_nick, 0}, {m_nick, 0}, {mc_nick, 3}, {ms_nick, 8}, mg_ignore, {m_nick, 0}}
72};
73struct Message uid_msgtab = {
74 "UID", 0, 0, 0, MFLG_SLOW,
75 {mg_ignore, mg_ignore, mg_ignore, {ms_uid, 9}, mg_ignore, mg_ignore}
76};
77struct Message euid_msgtab = {
78 "EUID", 0, 0, 0, MFLG_SLOW,
79 {mg_ignore, mg_ignore, mg_ignore, {ms_euid, 12}, mg_ignore, mg_ignore}
80};
81struct Message save_msgtab = {
82 "SAVE", 0, 0, 0, MFLG_SLOW,
83 {mg_ignore, mg_ignore, mg_ignore, {ms_save, 3}, mg_ignore, mg_ignore}
84};
85
86mapi_clist_av1 nick_clist[] = { &nick_msgtab, &uid_msgtab, &euid_msgtab,
87 &save_msgtab, NULL };
88
66b4a7ae 89DECLARE_MODULE_AV1(nick, NULL, NULL, nick_clist, NULL, NULL, "$Revision: 3518 $");
212380e3 90
91static int change_remote_nick(struct Client *, struct Client *, time_t,
92 const char *, int);
93
94static int clean_nick(const char *, int loc_client);
95static int clean_username(const char *);
96static int clean_host(const char *);
97static int clean_uid(const char *uid);
98
99static void set_initial_nick(struct Client *client_p, struct Client *source_p, char *nick);
100static void change_local_nick(struct Client *client_p, struct Client *source_p, char *nick, int);
101static int register_client(struct Client *client_p, struct Client *server,
102 const char *nick, time_t newts, int parc, const char *parv[]);
103
104static int perform_nick_collides(struct Client *, struct Client *,
105 struct Client *, int, const char **,
106 time_t, const char *, const char *);
107static int perform_nickchange_collides(struct Client *, struct Client *,
108 struct Client *, int, const char **, time_t, const char *);
109
110/* mr_nick()
111 * parv[0] = sender prefix
112 * parv[1] = nickname
113 */
114static int
115mr_nick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
116{
117 struct Client *target_p;
118 char nick[NICKLEN];
119 char *s;
120
121 if (strlen(client_p->id) == 3)
122 {
123 exit_client(client_p, client_p, client_p, "Mixing client and server protocol");
124 return 0;
125 }
126
127 if(parc < 2 || EmptyString(parv[1]) || (parv[1][0] == '~'))
128 {
129 sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
130 me.name, EmptyString(source_p->name) ? "*" : source_p->name);
131 return 0;
132 }
133
134 /* due to the scandinavian origins, (~ being uppercase of ^) and ~
135 * being disallowed as a nick char, we need to chop the first ~
136 * instead of just erroring.
137 */
138 if((s = strchr(parv[1], '~')))
139 *s = '\0';
140
141 /* copy the nick and terminate it */
907468c4 142 rb_strlcpy(nick, parv[1], sizeof(nick));
212380e3 143
144 /* check the nickname is ok */
145 if(!clean_nick(nick, 1))
146 {
147 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
148 me.name, EmptyString(parv[0]) ? "*" : parv[0], parv[1]);
149 return 0;
150 }
151
152 /* check if the nick is resv'd */
153 if(find_nick_resv(nick))
154 {
155 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
156 me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick);
157 return 0;
158 }
159
b37021a4 160 if(irc_dictionary_find(nd_dict, nick))
212380e3 161 {
162 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
163 me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick);
164 return 0;
165 }
166
167 if((target_p = find_named_client(nick)) == NULL)
168 set_initial_nick(client_p, source_p, nick);
169 else if(source_p == target_p)
170 strcpy(source_p->name, nick);
171 else
172 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, "*", nick);
173
174 return 0;
175}
176
177/* m_nick()
178 * parv[0] = sender prefix
179 * parv[1] = nickname
180 */
181static int
182m_nick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
183{
184 struct Client *target_p;
185 char nick[NICKLEN];
186 char *s;
187
188 if(parc < 2 || EmptyString(parv[1]) || (parv[1][0] == '~'))
189 {
190 sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, source_p->name);
191 return 0;
192 }
193
194 /* due to the scandinavian origins, (~ being uppercase of ^) and ~
195 * being disallowed as a nick char, we need to chop the first ~
196 * instead of just erroring.
197 */
198 if((s = strchr(parv[1], '~')))
199 *s = '\0';
200
201 /* mark end of grace period, to prevent nickflooding */
202 if(!IsFloodDone(source_p))
203 flood_endgrace(source_p);
204
205 /* terminate nick to NICKLEN, we dont want clean_nick() to error! */
907468c4 206 rb_strlcpy(nick, parv[1], sizeof(nick));
212380e3 207
208 /* check the nickname is ok */
209 if(!clean_nick(nick, 1))
210 {
211 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], nick);
212 return 0;
213 }
214
215 if(!IsExemptResv(source_p) && find_nick_resv(nick))
216 {
217 sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, source_p->name, nick);
218 return 0;
219 }
220
b37021a4 221 if(irc_dictionary_find(nd_dict, nick))
212380e3 222 {
223 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
224 me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick);
225 return 0;
226 }
227
228 if((target_p = find_named_client(nick)))
229 {
230 /* If(target_p == source_p) the client is changing nicks between
231 * equivalent nicknames ie: [nick] -> {nick}
232 */
233 if(target_p == source_p)
234 {
235 /* check the nick isnt exactly the same */
236 if(strcmp(target_p->name, nick))
237 change_local_nick(client_p, source_p, nick, 1);
238
239 }
240
241 /* drop unregged client */
242 else if(IsUnknown(target_p))
243 {
244 exit_client(NULL, target_p, &me, "Overridden");
245 change_local_nick(client_p, source_p, nick, 1);
246 }
247 else
248 sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, parv[0], nick);
249
250 return 0;
251 }
252 else
253 change_local_nick(client_p, source_p, nick, 1);
254
255 return 0;
256}
257
258/* ms_nick()
259 *
260 * server -> server nick change
261 * parv[0] = sender prefix
262 * parv[1] = nickname
263 * parv[2] = TS when nick change
264 *
265 * server introducing new nick
266 * parv[0] = sender prefix
267 * parv[1] = nickname
268 * parv[2] = hop count
269 * parv[3] = TS
270 * parv[4] = umode
271 * parv[5] = username
272 * parv[6] = hostname
273 * parv[7] = server
274 * parv[8] = ircname
275 */
276static int
277mc_nick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
278{
279 struct Client *target_p;
280 time_t newts = 0;
281
282 /* if nicks erroneous, or too long, kill */
283 if(!clean_nick(parv[1], 0))
284 {
0624f969 285 bad_nickname(client_p, parv[1]);
212380e3 286 return 0;
287 }
288
289 newts = atol(parv[2]);
290 target_p = find_named_client(parv[1]);
291
292 /* if the nick doesnt exist, allow it and process like normal */
293 if(target_p == NULL)
294 {
295 change_remote_nick(client_p, source_p, newts, parv[1], 1);
296 }
297 else if(IsUnknown(target_p))
298 {
299 exit_client(NULL, target_p, &me, "Overridden");
300 change_remote_nick(client_p, source_p, newts, parv[1], 1);
301 }
302 else if(target_p == source_p)
303 {
304 /* client changing case of nick */
305 if(strcmp(target_p->name, parv[1]))
306 change_remote_nick(client_p, source_p, newts, parv[1], 1);
307 }
308 /* we've got a collision! */
309 else
310 perform_nickchange_collides(source_p, client_p, target_p,
311 parc, parv, newts, parv[1]);
312
313 return 0;
314}
315
316static int
317ms_nick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
318{
319 struct Client *target_p;
320 time_t newts = 0;
321
322 if(parc != 9)
323 {
324 sendto_realops_snomask(SNO_GENERAL, L_ALL,
325 "Dropping server %s due to (invalid) command 'NICK' "
326 "with %d arguments (expecting 9)", client_p->name, parc);
327 ilog(L_SERVER, "Excess parameters (%d) for command 'NICK' from %s.",
328 parc, client_p->name);
329 exit_client(client_p, client_p, client_p, "Excess parameters to NICK command");
330 return 0;
331 }
332
333 /* if nicks empty, erroneous, or too long, kill */
334 if(!clean_nick(parv[1], 0))
335 {
0624f969 336 bad_nickname(client_p, parv[1]);
212380e3 337 return 0;
338 }
339
340 /* invalid username or host? */
341 if(!clean_username(parv[5]) || !clean_host(parv[6]))
342 {
83251205 343 ServerStats.is_kill++;
212380e3 344 sendto_realops_snomask(SNO_DEBUG, L_ALL,
345 "Bad user@host: %s@%s From: %s(via %s)",
346 parv[5], parv[6], parv[7], client_p->name);
347 sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.name, parv[1], me.name);
348 return 0;
349 }
350
351 /* check the length of the clients gecos */
352 if(strlen(parv[8]) > REALLEN)
353 {
354 char *s = LOCAL_COPY(parv[8]);
355 /* why exactly do we care? --fl */
356 sendto_realops_snomask(SNO_GENERAL, L_ALL,
357 "Long realname from server %s for %s", parv[7], parv[1]);
358
359 s[REALLEN] = '\0';
360 parv[8] = s;
361 }
362
363 newts = atol(parv[3]);
364
365 target_p = find_named_client(parv[1]);
366
367 /* if the nick doesnt exist, allow it and process like normal */
368 if(target_p == NULL)
369 {
370 register_client(client_p, NULL, parv[1], newts, parc, parv);
371 }
372 else if(IsUnknown(target_p))
373 {
374 exit_client(NULL, target_p, &me, "Overridden");
375 register_client(client_p, NULL, parv[1], newts, parc, parv);
376 }
377 else if(target_p == source_p)
378 {
379 /* client changing case of nick */
380 if(strcmp(target_p->name, parv[1]))
381 register_client(client_p, NULL, parv[1], newts, parc, parv);
382 }
383 /* we've got a collision! */
384 else
385 perform_nick_collides(source_p, client_p, target_p, parc, parv,
386 newts, parv[1], NULL);
387
388 return 0;
389}
390
391/* ms_uid()
392 * parv[1] - nickname
393 * parv[2] - hops
394 * parv[3] - TS
395 * parv[4] - umodes
396 * parv[5] - username
397 * parv[6] - hostname
398 * parv[7] - IP
399 * parv[8] - UID
400 * parv[9] - gecos
401 */
402static int
403ms_uid(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
404{
405 struct Client *target_p;
406 time_t newts = 0;
407
408 newts = atol(parv[3]);
409
410 if(parc != 10)
411 {
412 sendto_realops_snomask(SNO_GENERAL, L_ALL,
413 "Dropping server %s due to (invalid) command 'UID' "
414 "with %d arguments (expecting 10)", client_p->name, parc);
415 ilog(L_SERVER, "Excess parameters (%d) for command 'UID' from %s.",
416 parc, client_p->name);
417 exit_client(client_p, client_p, client_p, "Excess parameters to UID command");
418 return 0;
419 }
420
421 /* if nicks erroneous, or too long, kill */
422 if(!clean_nick(parv[1], 0))
423 {
0624f969 424 bad_nickname(client_p, parv[1]);
212380e3 425 return 0;
426 }
427
428 if(!clean_username(parv[5]) || !clean_host(parv[6]))
429 {
83251205 430 ServerStats.is_kill++;
212380e3 431 sendto_realops_snomask(SNO_DEBUG, L_ALL,
432 "Bad user@host: %s@%s From: %s(via %s)",
433 parv[5], parv[6], source_p->name, client_p->name);
434 sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name);
435 return 0;
436 }
437
438 if(!clean_uid(parv[8]))
439 {
83251205 440 ServerStats.is_kill++;
212380e3 441 sendto_realops_snomask(SNO_DEBUG, L_ALL,
442 "Bad UID: %s From: %s(via %s)",
443 parv[8], source_p->name, client_p->name);
444 sendto_one(client_p, ":%s KILL %s :%s (Bad UID)", me.id, parv[8], me.name);
445 return 0;
446 }
447
448 /* check length of clients gecos */
449 if(strlen(parv[9]) > REALLEN)
450 {
451 char *s = LOCAL_COPY(parv[9]);
452 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Long realname from server %s for %s",
453 parv[0], parv[1]);
454 s[REALLEN] = '\0';
455 parv[9] = s;
456 }
457
458 target_p = find_named_client(parv[1]);
459
460 if(target_p == NULL)
461 {
462 register_client(client_p, source_p, parv[1], newts, parc, parv);
463 }
464 else if(IsUnknown(target_p))
465 {
466 exit_client(NULL, target_p, &me, "Overridden");
467 register_client(client_p, source_p, parv[1], newts, parc, parv);
468 }
469 /* we've got a collision! */
470 else
471 perform_nick_collides(source_p, client_p, target_p, parc, parv,
472 newts, parv[1], parv[8]);
473
474 return 0;
475}
476
477/* ms_euid()
478 * parv[1] - nickname
479 * parv[2] - hops
480 * parv[3] - TS
481 * parv[4] - umodes
482 * parv[5] - username
483 * parv[6] - hostname
484 * parv[7] - IP
485 * parv[8] - UID
486 * parv[9] - realhost
487 * parv[10] - account
488 * parv[11] - gecos
489 */
490static int
491ms_euid(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
492{
493 struct Client *target_p;
494 time_t newts = 0;
495
496 newts = atol(parv[3]);
497
498 if(parc != 12)
499 {
500 sendto_realops_snomask(SNO_GENERAL, L_ALL,
501 "Dropping server %s due to (invalid) command 'EUID' "
502 "with %d arguments (expecting 12)", client_p->name, parc);
503 ilog(L_SERVER, "Excess parameters (%d) for command 'EUID' from %s.",
504 parc, client_p->name);
505 exit_client(client_p, client_p, client_p, "Excess parameters to EUID command");
506 return 0;
507 }
508
509 /* if nicks erroneous, or too long, kill */
510 if(!clean_nick(parv[1], 0))
511 {
0624f969 512 bad_nickname(client_p, parv[1]);
212380e3 513 return 0;
514 }
515
516 if(!clean_username(parv[5]) || !clean_host(parv[6]))
517 {
83251205 518 ServerStats.is_kill++;
212380e3 519 sendto_realops_snomask(SNO_DEBUG, L_ALL,
520 "Bad user@host: %s@%s From: %s(via %s)",
521 parv[5], parv[6], source_p->name, client_p->name);
522 sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name);
523 return 0;
524 }
525
526 if(!clean_uid(parv[8]))
527 {
83251205 528 ServerStats.is_kill++;
212380e3 529 sendto_realops_snomask(SNO_DEBUG, L_ALL,
530 "Bad UID: %s From: %s(via %s)",
531 parv[8], source_p->name, client_p->name);
532 sendto_one(client_p, ":%s KILL %s :%s (Bad UID)", me.id, parv[8], me.name);
533 return 0;
534 }
535
536 if(strcmp(parv[9], "*") && !clean_host(parv[9]))
537 {
83251205 538 ServerStats.is_kill++;
212380e3 539 sendto_realops_snomask(SNO_DEBUG, L_ALL,
540 "Bad realhost: %s From: %s(via %s)",
541 parv[9], source_p->name, client_p->name);
542 sendto_one(client_p, ":%s KILL %s :%s (Bad user@host)", me.id, parv[8], me.name);
543 return 0;
544 }
545
546 /* check length of clients gecos */
547 if(strlen(parv[11]) > REALLEN)
548 {
549 char *s = LOCAL_COPY(parv[11]);
550 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Long realname from server %s for %s",
551 parv[0], parv[1]);
552 s[REALLEN] = '\0';
553 parv[11] = s;
554 }
555
556 target_p = find_named_client(parv[1]);
557
558 if(target_p == NULL)
559 {
560 register_client(client_p, source_p, parv[1], newts, parc, parv);
561 }
562 else if(IsUnknown(target_p))
563 {
564 exit_client(NULL, target_p, &me, "Overridden");
565 register_client(client_p, source_p, parv[1], newts, parc, parv);
566 }
567 /* we've got a collision! */
568 else
569 perform_nick_collides(source_p, client_p, target_p, parc, parv,
570 newts, parv[1], parv[8]);
571
572 return 0;
573}
574
575/* ms_save()
576 * parv[1] - UID
577 * parv[2] - TS
578 */
579static int
580ms_save(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
581{
582 struct Client *target_p;
583
584 target_p = find_id(parv[1]);
585 if (target_p == NULL)
586 return 0;
587 if (!IsPerson(target_p))
588 sendto_realops_snomask(SNO_GENERAL, L_ALL,
589 "Ignored SAVE message for non-person %s from %s",
590 target_p->name, source_p->name);
591 else if (IsDigit(target_p->name[0]))
592 sendto_realops_snomask(SNO_DEBUG, L_ALL,
593 "Ignored noop SAVE message for %s from %s",
594 target_p->name, source_p->name);
595 else if (target_p->tsinfo == atol(parv[2]))
596 save_user(client_p, source_p, target_p);
597 else
598 sendto_realops_snomask(SNO_SKILL, L_ALL,
599 "Ignored SAVE message for %s from %s",
600 target_p->name, source_p->name);
601 return 0;
602}
603
604/* clean_nick()
605 *
606 * input - nickname to check
607 * output - 0 if erroneous, else 1
608 * side effects -
609 */
610static int
611clean_nick(const char *nick, int loc_client)
612{
613 int len = 0;
614
615 /* nicks cant start with a digit or -, and must have a length */
616 if(*nick == '-' || *nick == '\0')
617 return 0;
618
619 if(loc_client && IsDigit(*nick))
620 return 0;
621
622 for(; *nick; nick++)
623 {
624 len++;
625 if(!IsNickChar(*nick))
626 return 0;
627 }
628
629 /* nicklen is +1 */
630 if(len >= NICKLEN)
631 return 0;
632
633 return 1;
634}
635
636/* clean_username()
637 *
638 * input - username to check
639 * output - 0 if erroneous, else 0
640 * side effects -
641 */
642static int
643clean_username(const char *username)
644{
645 int len = 0;
646
647 for(; *username; username++)
648 {
649 len++;
650
651 if(!IsUserChar(*username))
652 return 0;
653 }
654
655 if(len > USERLEN)
656 return 0;
657
658 return 1;
659}
660
661/* clean_host()
662 *
663 * input - host to check
664 * output - 0 if erroneous, else 0
665 * side effects -
666 */
667static int
668clean_host(const char *host)
669{
670 int len = 0;
671
672 for(; *host; host++)
673 {
674 len++;
675
676 if(!IsHostChar(*host))
677 return 0;
678 }
679
680 if(len > HOSTLEN)
681 return 0;
682
683 return 1;
684}
685
686static int
687clean_uid(const char *uid)
688{
689 int len = 1;
690
691 if(!IsDigit(*uid++))
692 return 0;
693
694 for(; *uid; uid++)
695 {
696 len++;
697
698 if(!IsIdChar(*uid))
699 return 0;
700 }
701
702 if(len != IDLEN - 1)
703 return 0;
704
705 return 1;
706}
707
708static void
709set_initial_nick(struct Client *client_p, struct Client *source_p, char *nick)
710{
711 char buf[USERLEN + 1];
bfccb2c0 712 char note[NICKLEN + 10];
212380e3 713
714 /* This had to be copied here to avoid problems.. */
9f6bbe3c 715 source_p->tsinfo = rb_current_time();
212380e3 716 if(source_p->name[0])
717 del_from_client_hash(source_p->name, source_p);
718
719 strcpy(source_p->name, nick);
720 add_to_client_hash(nick, source_p);
721
bfccb2c0
JT
722 rb_snprintf(note, sizeof(note), "Nick: %s", nick);
723 rb_note(client_p->localClient->F, note);
212380e3 724
725 if(source_p->flags & FLAGS_SENTUSER)
726 {
907468c4 727 rb_strlcpy(buf, source_p->username, sizeof(buf));
212380e3 728
729 /* got user, heres nick. */
730 register_local_user(client_p, source_p, buf);
731
732 }
733}
734
735static void
736change_local_nick(struct Client *client_p, struct Client *source_p,
737 char *nick, int dosend)
738{
739 struct Client *target_p;
90a3c35b 740 rb_dlink_node *ptr, *next_ptr;
212380e3 741 struct Channel *chptr;
bfccb2c0 742 char note[NICKLEN + 10];
212380e3 743 int samenick;
744
745 if (dosend)
746 {
747 chptr = find_bannickchange_channel(source_p);
748 if (chptr != NULL)
749 {
750 sendto_one_numeric(source_p, ERR_BANNICKCHANGE,
751 form_str(ERR_BANNICKCHANGE),
752 nick, chptr->chname);
753 return;
754 }
9f6bbe3c 755 if((source_p->localClient->last_nick_change + ConfigFileEntry.max_nick_time) < rb_current_time())
212380e3 756 source_p->localClient->number_of_nick_changes = 0;
757
9f6bbe3c 758 source_p->localClient->last_nick_change = rb_current_time();
212380e3 759 source_p->localClient->number_of_nick_changes++;
760
761 if(ConfigFileEntry.anti_nick_flood && !IsOper(source_p) &&
762 source_p->localClient->number_of_nick_changes > ConfigFileEntry.max_nick_changes)
763 {
764 sendto_one(source_p, form_str(ERR_NICKTOOFAST),
765 me.name, source_p->name, source_p->name,
766 nick, ConfigFileEntry.max_nick_time);
767 return;
768 }
769 }
770
771 samenick = irccmp(source_p->name, nick) ? 0 : 1;
772
773 /* dont reset TS if theyre just changing case of nick */
774 if(!samenick)
775 {
95ffa685 776 /* force the TS to increase -- jilles */
9f6bbe3c 777 if (source_p->tsinfo >= rb_current_time())
95ffa685 778 source_p->tsinfo++;
779 else
9f6bbe3c 780 source_p->tsinfo = rb_current_time();
212380e3 781 monitor_signoff(source_p);
782 /* we only do bancache for local users -- jilles */
783 if(source_p->user)
784 invalidate_bancache_user(source_p);
785 }
786
787 sendto_realops_snomask(SNO_NCHANGE, L_ALL,
788 "Nick change: From %s to %s [%s@%s]",
789 source_p->name, nick, source_p->username, source_p->host);
790
791 /* send the nick change to the users channels */
792 sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s",
793 source_p->name, source_p->username, source_p->host, nick);
794
795 /* send the nick change to servers.. */
796 if(source_p->user)
797 {
798 add_history(source_p, 1);
799
800 if (dosend)
801 {
802 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
803 use_id(source_p), nick, (long) source_p->tsinfo);
804 sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s NICK %s :%ld",
805 source_p->name, nick, (long) source_p->tsinfo);
806 }
807 }
808
809 /* Finally, add to hash */
810 del_from_client_hash(source_p->name, source_p);
811 strcpy(source_p->name, nick);
812 add_to_client_hash(nick, source_p);
813
814 if(!samenick)
815 monitor_signon(source_p);
816
817 /* Make sure everyone that has this client on its accept list
818 * loses that reference.
819 */
820 /* we used to call del_all_accepts() here, but theres no real reason
821 * to clear a clients own list of accepted clients. So just remove
822 * them from everyone elses list --anfl
823 */
90a3c35b 824 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, source_p->on_allow_list.head)
212380e3 825 {
826 target_p = ptr->data;
827
9f6c3353
JT
828 rb_dlinkFindDestroy(source_p, &target_p->localClient->allow_list);
829 rb_dlinkDestroy(ptr, &source_p->on_allow_list);
212380e3 830 }
831
bfccb2c0
JT
832 rb_snprintf(note, sizeof(note), "Nick: %s", nick);
833 rb_note(client_p->localClient->F, note);
212380e3 834
835 return;
836}
837
838/*
839 * change_remote_nick()
840 */
841static int
842change_remote_nick(struct Client *client_p, struct Client *source_p,
843 time_t newts, const char *nick, int dosend)
844{
845 struct nd_entry *nd;
846 int samenick = irccmp(source_p->name, nick) ? 0 : 1;
847
848 /* client changing their nick - dont reset ts if its same */
849 if(!samenick)
850 {
9f6bbe3c 851 source_p->tsinfo = newts ? newts : rb_current_time();
212380e3 852 monitor_signoff(source_p);
853 }
854
855 sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s",
856 source_p->name, source_p->username, source_p->host, nick);
857
858 if(source_p->user)
859 {
860 add_history(source_p, 1);
861 if (dosend)
862 {
863 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
864 use_id(source_p), nick, (long) source_p->tsinfo);
865 sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s NICK %s :%ld",
866 source_p->name, nick, (long) source_p->tsinfo);
867 }
868 }
869
870 del_from_client_hash(source_p->name, source_p);
871
872 /* invalidate nick delay when a remote client uses the nick.. */
b37021a4 873 if((nd = irc_dictionary_retrieve(nd_dict, nick)))
212380e3 874 free_nd_entry(nd);
875
876 strcpy(source_p->name, nick);
877 add_to_client_hash(nick, source_p);
878
879 if(!samenick)
880 monitor_signon(source_p);
881
882 /* remove all accepts pointing to the client */
883 del_all_accepts(source_p);
884
885 return 0;
886}
887
888static int
889perform_nick_collides(struct Client *source_p, struct Client *client_p,
890 struct Client *target_p, int parc, const char *parv[],
891 time_t newts, const char *nick, const char *uid)
892{
893 int sameuser;
894 int use_save;
895 const char *action;
896
897 use_save = ConfigFileEntry.collision_fnc && can_save(target_p) &&
898 uid != NULL && can_save(source_p);
899 action = use_save ? "saved" : "killed";
900
901 /* if we dont have a ts, or their TS's are the same, kill both */
902 if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
903 {
904 sendto_realops_snomask(SNO_GENERAL, L_ALL,
905 "Nick collision on %s(%s <- %s)(both %s)",
906 target_p->name, target_p->from->name, client_p->name, action);
907
908 if (use_save)
909 {
910 save_user(&me, &me, target_p);
83251205 911 ServerStats.is_save++;
212380e3 912 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
913 uid, (long)newts);
914 register_client(client_p, source_p,
3f7e0642 915 uid, SAVE_NICKTS, parc, parv);
212380e3 916 }
917 else
918 {
919 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
920 form_str(ERR_NICKCOLLISION), target_p->name);
921
922 /* if the new client being introduced has a UID, we need to
923 * issue a KILL for it..
924 */
925 if(uid)
926 sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
927 me.id, uid, me.name);
928
929 /* we then need to KILL the old client everywhere */
930 kill_client_serv_butone(NULL, target_p, "%s (Nick collision (new))", me.name);
83251205 931 ServerStats.is_kill++;
212380e3 932
933 target_p->flags |= FLAGS_KILLED;
934 exit_client(client_p, target_p, &me, "Nick collision (new)");
935 }
936 return 0;
937 }
938 /* the timestamps are different */
939 else
940 {
941 sameuser = (target_p->user) && !irccmp(target_p->username, parv[5])
942 && !irccmp(target_p->host, parv[6]);
943
944 if((sameuser && newts < target_p->tsinfo) ||
945 (!sameuser && newts > target_p->tsinfo))
946 {
947 /* if we have a UID, then we need to issue a KILL,
948 * otherwise we do nothing and hope that the other
949 * client will collide it..
950 */
951 if (use_save)
952 {
953 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
954 uid, (long)newts);
955 register_client(client_p, source_p,
3f7e0642 956 uid, SAVE_NICKTS, parc, parv);
212380e3 957 }
958 else if(uid)
959 sendto_one(client_p,
960 ":%s KILL %s :%s (Nick collision (new))",
961 me.id, uid, me.name);
962 return 0;
963 }
964 else
965 {
966 if(sameuser)
967 sendto_realops_snomask(SNO_GENERAL, L_ALL,
968 "Nick collision on %s(%s <- %s)(older %s)",
969 target_p->name, target_p->from->name,
970 client_p->name, action);
971 else
972 sendto_realops_snomask(SNO_GENERAL, L_ALL,
973 "Nick collision on %s(%s <- %s)(newer %s)",
974 target_p->name, target_p->from->name,
975 client_p->name, action);
976
977 if (use_save)
978 {
83251205 979 ServerStats.is_save++;
212380e3 980 save_user(&me, &me, target_p);
981 }
982 else
983 {
83251205 984 ServerStats.is_kill++;
212380e3 985 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
986 form_str(ERR_NICKCOLLISION), target_p->name);
987
988 /* now we just need to kill the existing client */
989 kill_client_serv_butone(client_p, target_p,
990 "%s (Nick collision (new))", me.name);
991
992 target_p->flags |= FLAGS_KILLED;
993 (void) exit_client(client_p, target_p, &me, "Nick collision");
994 }
995
996 register_client(client_p, parc >= 10 ? source_p : NULL,
997 nick, newts, parc, parv);
998
999 return 0;
1000 }
1001 }
1002}
1003
1004
1005static int
1006perform_nickchange_collides(struct Client *source_p, struct Client *client_p,
1007 struct Client *target_p, int parc,
1008 const char *parv[], time_t newts, const char *nick)
1009{
1010 int sameuser;
1011 int use_save;
1012 const char *action;
1013
1014 use_save = ConfigFileEntry.collision_fnc && can_save(target_p) &&
1015 can_save(source_p);
1016 action = use_save ? "saved" : "killed";
1017
1018 /* its a client changing nick and causing a collide */
1019 if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user)
1020 {
1021 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1022 "Nick change collision from %s to %s(%s <- %s)(both %s)",
1023 source_p->name, target_p->name, target_p->from->name,
1024 client_p->name, action);
1025
1026 if (use_save)
1027 {
83251205 1028 ServerStats.is_save += 2;
212380e3 1029 save_user(&me, &me, target_p);
1030 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
1031 source_p->id, (long)newts);
1032 /* don't send a redundant nick change */
1033 if (!IsDigit(source_p->name[0]))
3f7e0642 1034 change_remote_nick(client_p, source_p, SAVE_NICKTS, source_p->id, 1);
212380e3 1035 }
1036 else
1037 {
83251205 1038 ServerStats.is_kill++;
212380e3 1039 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
1040 form_str(ERR_NICKCOLLISION), target_p->name);
1041
1042 kill_client_serv_butone(NULL, source_p, "%s (Nick change collision)", me.name);
1043
83251205 1044 ServerStats.is_kill++;
212380e3 1045
1046 kill_client_serv_butone(NULL, target_p, "%s (Nick change collision)", me.name);
1047
1048 target_p->flags |= FLAGS_KILLED;
1049 exit_client(NULL, target_p, &me, "Nick collision(new)");
1050 source_p->flags |= FLAGS_KILLED;
1051 exit_client(client_p, source_p, &me, "Nick collision(old)");
1052 }
1053 return 0;
1054 }
1055 else
1056 {
1057 sameuser = !irccmp(target_p->username, source_p->username) &&
1058 !irccmp(target_p->host, source_p->host);
1059
1060 if((sameuser && newts < target_p->tsinfo) ||
1061 (!sameuser && newts > target_p->tsinfo))
1062 {
1063 if(sameuser)
1064 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1065 "Nick change collision from %s to %s(%s <- %s)(older %s)",
1066 source_p->name, target_p->name,
1067 target_p->from->name, client_p->name, action);
1068 else
1069 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1070 "Nick change collision from %s to %s(%s <- %s)(newer %s)",
1071 source_p->name, target_p->name,
1072 target_p->from->name, client_p->name, action);
1073
1074 if (use_save)
1075 {
83251205 1076 ServerStats.is_save++;
212380e3 1077 /* can't broadcast a SAVE because the
1078 * nickchange has happened at client_p
1079 * but not in other directions -- jilles */
1080 sendto_one(client_p, ":%s SAVE %s %ld", me.id,
1081 source_p->id, (long)newts);
212380e3 1082 /* send a :<id> NICK <id> <ts> (!) */
1083 if (!IsDigit(source_p->name[0]))
3f7e0642 1084 change_remote_nick(client_p, source_p, SAVE_NICKTS, source_p->id, 1);
212380e3 1085 }
1086 else
1087 {
83251205 1088 ServerStats.is_kill++;
212380e3 1089
1090 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
1091 form_str(ERR_NICKCOLLISION), target_p->name);
1092
1093 /* kill the client issuing the nickchange */
1094 kill_client_serv_butone(client_p, source_p,
1095 "%s (Nick change collision)", me.name);
1096
1097 source_p->flags |= FLAGS_KILLED;
1098
1099 if(sameuser)
1100 exit_client(client_p, source_p, &me, "Nick collision(old)");
1101 else
1102 exit_client(client_p, source_p, &me, "Nick collision(new)");
1103 }
1104 return 0;
1105 }
1106 else
1107 {
1108 if(sameuser)
1109 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1110 "Nick collision on %s(%s <- %s)(older %s)",
1111 target_p->name, target_p->from->name,
1112 client_p->name, action);
1113 else
1114 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1115 "Nick collision on %s(%s <- %s)(newer %s)",
1116 target_p->name, target_p->from->name,
1117 client_p->name, action);
1118
1119 if (use_save)
1120 {
83251205 1121 ServerStats.is_save++;
212380e3 1122 save_user(&me, &me, target_p);
1123 }
1124 else
1125 {
1126 sendto_one_numeric(target_p, ERR_NICKCOLLISION,
1127 form_str(ERR_NICKCOLLISION), target_p->name);
1128
1129 /* kill the client who existed before hand */
1130 kill_client_serv_butone(client_p, target_p, "%s (Nick collision)", me.name);
1131
83251205 1132 ServerStats.is_kill++;
212380e3 1133
1134 target_p->flags |= FLAGS_KILLED;
1135 (void) exit_client(client_p, target_p, &me, "Nick collision");
1136 }
1137 }
1138 }
1139
1140 change_remote_nick(client_p, source_p, newts, nick, 1);
1141
1142 return 0;
1143}
1144
1145static int
1146register_client(struct Client *client_p, struct Client *server,
1147 const char *nick, time_t newts, int parc, const char *parv[])
1148{
1149 struct Client *source_p;
1150 struct User *user;
1151 struct nd_entry *nd;
1152 const char *m;
1153 int flag;
1154
64449595
JT
1155 if(server == NULL)
1156 {
1157 if((server = find_server(NULL, parv[7])) == NULL)
1158 {
1159 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1160 "Ghost killed: %s on invalid server %s",
1161 nick, parv[7]);
1162 sendto_one(client_p, ":%s KILL %s :%s (Server doesn't exist)",
1163 get_id(&me, client_p), nick, me.name);
1164 return 0;
1165 }
1166 }
1167
212380e3 1168 source_p = make_client(client_p);
1169 user = make_user(source_p);
bfccb2c0 1170 rb_dlinkAddTail(source_p, &source_p->node, &global_client_list);
212380e3 1171
1172 source_p->hopcount = atoi(parv[2]);
1173 source_p->tsinfo = newts;
1174
1175 strcpy(source_p->name, nick);
907468c4
VY
1176 rb_strlcpy(source_p->username, parv[5], sizeof(source_p->username));
1177 rb_strlcpy(source_p->host, parv[6], sizeof(source_p->host));
1178 rb_strlcpy(source_p->orighost, source_p->host, sizeof(source_p->orighost));
212380e3 1179
1180 if(parc == 12)
1181 {
907468c4
VY
1182 rb_strlcpy(source_p->info, parv[11], sizeof(source_p->info));
1183 rb_strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
1184 rb_strlcpy(source_p->id, parv[8], sizeof(source_p->id));
212380e3 1185 add_to_id_hash(source_p->id, source_p);
1186 if (strcmp(parv[9], "*"))
1187 {
907468c4 1188 rb_strlcpy(source_p->orighost, parv[9], sizeof(source_p->orighost));
212380e3 1189 if (irccmp(source_p->host, source_p->orighost))
1190 SetDynSpoof(source_p);
1191 }
1192 if (strcmp(parv[10], "*"))
907468c4 1193 rb_strlcpy(source_p->user->suser, parv[10], sizeof(source_p->user->suser));
212380e3 1194 }
1195 else if(parc == 10)
1196 {
907468c4
VY
1197 rb_strlcpy(source_p->info, parv[9], sizeof(source_p->info));
1198 rb_strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
1199 rb_strlcpy(source_p->id, parv[8], sizeof(source_p->id));
212380e3 1200 add_to_id_hash(source_p->id, source_p);
1201 }
1202 else
1203 {
907468c4 1204 rb_strlcpy(source_p->info, parv[8], sizeof(source_p->info));
212380e3 1205 }
1206
1207 /* remove any nd entries for this nick */
b37021a4 1208 if((nd = irc_dictionary_retrieve(nd_dict, nick)))
212380e3 1209 free_nd_entry(nd);
1210
1211 add_to_client_hash(nick, source_p);
66b4a7ae 1212 add_to_hostname_hash(source_p->orighost, source_p);
212380e3 1213 monitor_signon(source_p);
1214
1215 m = &parv[4][1];
1216 while(*m)
1217 {
1218 flag = user_modes[(unsigned char) *m];
1219
1220 if(flag & UMODE_SERVICE)
1221 {
1222 int hit = 0;
08d11e34 1223 rb_dlink_node *ptr;
212380e3 1224
08d11e34 1225 RB_DLINK_FOREACH(ptr, service_list.head)
212380e3 1226 {
c88cdb00 1227 if(!irccmp((const char *) ptr->data, server->name))
212380e3 1228 {
1229 hit++;
1230 break;
1231 }
1232 }
1233
1234 if(!hit)
1235 {
1236 m++;
1237 continue;
1238 }
1239 }
1240
1241 /* increment +i count if theyre invis */
1242 if(!(source_p->umodes & UMODE_INVISIBLE) && (flag & UMODE_INVISIBLE))
1243 Count.invisi++;
1244
1245 /* increment opered count if theyre opered */
1246 if(!(source_p->umodes & UMODE_OPER) && (flag & UMODE_OPER))
1247 Count.oper++;
1248
1249 source_p->umodes |= flag;
1250 m++;
1251 }
1252
1253 if(IsOper(source_p) && !IsService(source_p))
bfccb2c0 1254 rb_dlinkAddAlloc(source_p, &oper_list);
212380e3 1255
1256 SetRemoteClient(source_p);
1257
1258 if(++Count.total > Count.max_tot)
1259 Count.max_tot = Count.total;
1260
64449595 1261 source_p->servptr = server;
212380e3 1262
bfccb2c0 1263 rb_dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->users);
212380e3 1264
1265 /* fake direction */
1266 if(source_p->servptr->from != source_p->from)
1267 {
1268 struct Client *target_p = source_p->servptr->from;
1269
1270 sendto_realops_snomask(SNO_DEBUG, L_ALL,
1271 "Bad User [%s] :%s USER %s@%s %s, != %s[%s]",
1272 client_p->name, source_p->name,
1273 source_p->username, source_p->host,
c88cdb00 1274 server->name, target_p->name, target_p->from->name);
212380e3 1275 kill_client(client_p, source_p,
1276 "%s (NICK from wrong direction (%s != %s))",
c88cdb00 1277 me.name, server->name, target_p->from->name);
212380e3 1278 source_p->flags |= FLAGS_KILLED;
1279 return exit_client(source_p, source_p, &me, "USER server wrong direction");
1280 }
1281
1282 call_hook(h_new_remote_user, source_p);
1283
1284 return (introduce_client(client_p, source_p, user, nick, parc == 12));
1285}
1286
1287/* Check if we can do SAVE. target_p can be a client to save or a
1288 * server introducing a client -- jilles */
1289static int
1290can_save(struct Client *target_p)
1291{
1292 struct Client *serv_p;
1293
1294 if (MyClient(target_p))
1295 return 1;
1296 if (!has_id(target_p))
1297 return 0;
1298 serv_p = IsServer(target_p) ? target_p : target_p->servptr;
1299 while (serv_p != NULL && serv_p != &me)
1300 {
1301 if (!(serv_p->serv->caps & CAP_SAVE))
1302 return 0;
1303 serv_p = serv_p->servptr;
1304 }
1305 return serv_p == &me;
1306}
1307
1308static void
1309save_user(struct Client *client_p, struct Client *source_p,
1310 struct Client *target_p)
1311{
1312 if (!MyConnect(target_p) && (!has_id(target_p) || !IsCapable(target_p->from, CAP_SAVE)))
1313 {
1314 /* This shouldn't happen */
1315 /* Note we only need SAVE support in this direction */
1316 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1317 "Killed %s!%s@%s for nick collision detected by %s (%s does not support SAVE)",
1318 target_p->name, target_p->username, target_p->host, source_p->name, target_p->from->name);
1319 kill_client_serv_butone(NULL, target_p, "%s (Nick collision (no SAVE support))", me.name);
83251205 1320 ServerStats.is_kill++;
212380e3 1321
1322 target_p->flags |= FLAGS_KILLED;
1323 (void) exit_client(NULL, target_p, &me, "Nick collision (no SAVE support)");
1324 return;
1325 }
1326 sendto_server(client_p, NULL, CAP_SAVE|CAP_TS6, NOCAPS, ":%s SAVE %s %ld",
1327 source_p->id, target_p->id, (long)target_p->tsinfo);
1328 sendto_server(client_p, NULL, CAP_TS6, CAP_SAVE, ":%s NICK %s :%ld",
3f7e0642 1329 target_p->id, target_p->id, (long)SAVE_NICKTS);
212380e3 1330 sendto_server(client_p, NULL, NOCAPS, CAP_TS6, ":%s NICK %s :%ld",
3f7e0642 1331 target_p->name, target_p->id, (long)SAVE_NICKTS);
212380e3 1332 if (!IsMe(client_p))
1333 sendto_realops_snomask(SNO_SKILL, L_ALL,
1334 "Received SAVE message for %s from %s",
1335 target_p->name, source_p->name);
1336 if (MyClient(target_p))
1337 {
1338 sendto_one_numeric(target_p, RPL_SAVENICK,
1339 form_str(RPL_SAVENICK), target_p->id);
1340 change_local_nick(target_p, target_p, target_p->id, 0);
3f7e0642 1341 target_p->tsinfo = SAVE_NICKTS;
212380e3 1342 }
1343 else
3f7e0642 1344 change_remote_nick(target_p, target_p, SAVE_NICKTS, target_p->id, 0);
212380e3 1345}
0624f969
JT
1346
1347static void bad_nickname(struct Client *client_p, const char *nick)
1348{
1349 char squitreason[100];
1350
1351 sendto_wallops_flags(UMODE_WALLOP, &me,
1352 "Squitting %s because of bad nickname %s (NICKLEN mismatch?)",
1353 client_p->name, nick);
1354 sendto_server(NULL, NULL, CAP_TS6, NOCAPS,
1355 ":%s WALLOPS :Squitting %s because of bad nickname %s (NICKLEN mismatch?)",
1356 me.id, client_p->name, nick);
1357 sendto_server(NULL, NULL, NOCAPS, CAP_TS6,
1358 ":%s WALLOPS :Squitting %s because of bad nickname %s (NICKLEN mismatch?)",
1359 me.name, client_p->name, nick);
1360
1361 rb_snprintf(squitreason, sizeof squitreason,
1362 "Bad nickname introduced [%s]", nick);
1363 exit_client(client_p, client_p, &me, squitreason);
1364}