ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/core/m_nick.c
Revision: 1017
Committed: Tue Oct 27 22:22:38 2009 UTC (16 years, 9 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_nick.c
File size: 26837 byte(s)
Log Message:
- fixed build with --enable-assert
- fixed STATS z reporting correct memory consumption of channel bans/excepts/invites and watchlist entries

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

Properties

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