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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1624 - (show annotations)
Thu Nov 1 13:27:04 2012 UTC (7 years, 9 months ago) by michael
File MIME type: text/x-chdr
File size: 31023 byte(s)
- Fixed compile warnings due to missing arguments to sendto_realops_flags()

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

Properties

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

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