ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1997
Committed: Sat May 11 17:35:07 2013 UTC (13 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 30373 byte(s)
Log Message:
- Mostly style cleanups & whitespace changes

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

Properties

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