ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 3109
Committed: Thu Mar 6 19:25:12 2014 UTC (12 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 29569 byte(s)
Log Message:
- Applied Adam's sendto_one_numeric() changes

File Contents

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

Properties

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