ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 2300
Committed: Wed Jun 19 12:10:37 2013 UTC (10 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 30369 byte(s)
Log Message:
- whowas: Renamed functions.
  add_history -> whowas_add_history
  off_history -> whowas_off_history
  get_history -> whowas_get_history

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

Properties

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