ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.0.x/modules/core/m_nick.c
Revision: 1158
Committed: Wed Aug 10 19:46:00 2011 UTC (12 years, 8 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/core/m_nick.c
File size: 26737 byte(s)
Log Message:
- UMODE_REJ goes to usermode 'j'
- add UMODE_REGISTERED ('r') (registered nickname)

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

Properties

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