ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 2403
Committed: Tue Jul 16 15:22:41 2013 UTC (10 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 30127 byte(s)
Log Message:
- mr_nick(): remove legacy code for nicks cantaining '~'. valid_nickname()
  already takes care of this.

File Contents

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

Properties

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