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: 1080
Committed: Wed Mar 10 23:09:36 2010 UTC (14 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/modules/core/m_nick.c
File size: 26673 byte(s)
Log Message:
- Sort out unneeded arguments of some user registration functions

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

Properties

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