ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1182
Committed: Tue Aug 16 08:18:13 2011 UTC (14 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/core/m_nick.c
File size: 26295 byte(s)
Log Message:
- nick_from_server, uid_from_server: don't blindly increment Count.invisi
  without checking if we already did. Fixes invalid usercount in case servers
  sends redundant modes within an NICK/UID message.


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

Properties

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