ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1192
Committed: Thu Aug 18 20:25:18 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: 29154 byte(s)
Log Message:
- move change_local_nick() from client.c to m_nick.c

File Contents

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

Properties

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