ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_nick.c
Revision: 4963
Committed: Mon Dec 1 13:08:44 2014 UTC (9 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 27303 byte(s)
Log Message:
- Get rid of NOCAPS

File Contents

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

Properties

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