ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1193
Committed: Thu Aug 18 20:36:25 2011 UTC (15 years, 1 month ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/core/m_nick.c
File size: 29146 byte(s)
Log Message:
- change_local_nick(): remove unnecessary client_p parameter

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

Properties

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