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: 1002
Committed: Sat Aug 29 22:48:40 2009 UTC (14 years, 7 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_nick.c
File size: 27153 byte(s)
Log Message:
- moved set_initial_nick() to m_nick.c

File Contents

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

Properties

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