ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_nick.c
Revision: 7613
Committed: Tue Jun 21 16:50:21 2016 UTC (7 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 26819 byte(s)
Log Message:
- m_nick.c: stylistic 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 7007 * Copyright (c) 1997-2016 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 michael 4564 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * 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 "hash.h"
30     #include "fdlist.h"
31     #include "irc_string.h"
32     #include "ircd.h"
33     #include "numeric.h"
34 michael 1309 #include "conf.h"
35 michael 7235 #include "conf_resv.h"
36 michael 3347 #include "user.h"
37 adx 30 #include "whowas.h"
38     #include "send.h"
39 michael 1192 #include "channel_mode.h"
40 adx 30 #include "parse.h"
41     #include "modules.h"
42     #include "packet.h"
43 michael 876 #include "watch.h"
44 michael 3347 #include "misc.h"
45 michael 6755 #include "id.h"
46 adx 30
47    
48 michael 1997 /* check_clean_nick()
49     *
50     * input - pointer to source
51     * -
52     * - nickname
53     * - truncated nickname
54     * - origin of client
55     * - pointer to server nick is coming from
56     * output - none
57     * side effects - if nickname is erroneous, or a different length to
58     * truncated nickname, return 1
59     */
60     static int
61 michael 6751 check_clean_nick(struct Client *source_p, const char *nick)
62 michael 1997 {
63 michael 6745 assert(IsServer(source_p) || (IsClient(source_p) && !MyConnect(source_p)));
64    
65 michael 4092 /*
66     * The old code did some wacky stuff here, if the nick is invalid, kill it
67 michael 4299 * and don't bother messing at all
68 michael 1997 */
69 michael 6747 if (valid_nickname(nick, 0))
70     return 0;
71 michael 1997
72 michael 6747 ++ServerStats.is_kill;
73 michael 6751 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE, "Bad/long Nick: %s From: %s(via %s)",
74     nick, IsServer(source_p) ? source_p->name : source_p->servptr->name,
75     source_p->from->name);
76 michael 6747 sendto_one(source_p, ":%s KILL %s :%s (Bad Nickname)",
77     me.id, nick, me.name);
78 michael 1997
79 michael 6747 /* Bad nick change */
80 michael 6753 if (!IsServer(source_p))
81 michael 6747 {
82     sendto_server(source_p, 0, 0, ":%s KILL %s :%s (Bad Nickname)",
83     me.id, source_p->id, me.name);
84     AddFlag(source_p, FLAGS_KILLED);
85     exit_client(source_p, "Bad Nickname");
86 michael 1997 }
87    
88 michael 6747 return 1;
89 michael 1997 }
90    
91 michael 6755 static int
92     check_clean_uid(struct Client *source_p, const char *nick, const char *uid)
93     {
94     assert(IsServer(source_p));
95    
96     if (valid_uid(uid) && strncmp(uid, source_p->id, IRC_MAXSID) == 0)
97     return 0;
98    
99     ++ServerStats.is_kill;
100     sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
101     "Bad UID: %s Nickname: %s From: %s(via %s)",
102     uid, nick, source_p->name, source_p->from->name);
103     sendto_one(source_p, ":%s KILL %s :%s (Bad UID)",
104     me.id, uid, me.name);
105     return 1;
106     }
107    
108 michael 1997 /* check_clean_user()
109     *
110     * input - pointer to client sending data
111     * - nickname
112     * - username to check
113     * - origin of NICK
114     * output - none
115     * side effects - if username is erroneous, return 1
116     */
117     static int
118 michael 6751 check_clean_user(struct Client *source_p, const char *nick, const char *user)
119 michael 1997 {
120 michael 6745 assert(IsServer(source_p));
121    
122 michael 6747 if (valid_username(user, 0))
123     return 0;
124 michael 1997
125 michael 6747 ++ServerStats.is_kill;
126     sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
127     "Bad/Long Username: %s Nickname: %s From: %s(via %s)",
128 michael 6751 user, nick, source_p->name, source_p->from->name);
129 michael 6747 sendto_one(source_p, ":%s KILL %s :%s (Bad Username)",
130     me.id, nick, me.name);
131     return 1;
132 michael 1997 }
133    
134     /* check_clean_host()
135     *
136     * input - pointer to client sending us data
137     * - nickname
138     * - hostname to check
139     * - source name
140     * output - none
141     * side effects - if hostname is erroneous, return 1
142     */
143     static int
144 michael 6751 check_clean_host(struct Client *source_p, const char *nick, const char *host)
145 michael 1997 {
146 michael 6745 assert(IsServer(source_p));
147    
148 michael 6747 if (valid_hostname(host))
149     return 0;
150 michael 1997
151 michael 6747 ++ServerStats.is_kill;
152     sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
153     "Bad/Long Hostname: %s Nickname: %s From: %s(via %s)",
154 michael 6751 host, nick, source_p->name, source_p->from->name);
155 michael 6747 sendto_one(source_p, ":%s KILL %s :%s (Bad Hostname)",
156     me.id, nick, me.name);
157     return 1;
158 michael 1997 }
159    
160 michael 1002 /* set_initial_nick()
161     *
162     * inputs
163     * output
164     * side effects -
165     *
166     * This function is only called to set up an initially registering
167     * client.
168     */
169     static void
170 michael 1003 set_initial_nick(struct Client *source_p, const char *nick)
171 michael 1002 {
172 michael 5600 const int samenick = !irccmp(source_p->name, nick);
173 michael 1002
174 michael 5600 if (!samenick)
175     source_p->tsinfo = CurrentTime;
176    
177 michael 4589 source_p->connection->registration &= ~REG_NEED_NICK;
178 michael 1002
179     if (source_p->name[0])
180     hash_del_client(source_p);
181    
182     strlcpy(source_p->name, nick, sizeof(source_p->name));
183     hash_add_client(source_p);
184    
185     /* fd_desc is long enough */
186 michael 6634 fd_note(&source_p->connection->fd, "Nick: %s", source_p->name);
187 michael 1002
188 michael 4589 if (!source_p->connection->registration)
189 michael 1080 register_local_user(source_p);
190 michael 1002 }
191    
192 michael 1192 /* change_local_nick()
193     *
194     * inputs - pointer to server
195     * - pointer to client
196     * - nick
197 michael 2820 * output -
198 michael 1192 * side effects - changes nick of a LOCAL user
199     */
200     static void
201 michael 1193 change_local_nick(struct Client *source_p, const char *nick)
202 michael 1192 {
203     assert(source_p->name[0] && !EmptyString(nick));
204 michael 4382 assert(MyClient(source_p));
205 michael 1192
206     /*
207     * Client just changing his/her nick. If he/she is
208     * on a channel, send note of change to all clients
209     * on that channel. Propagate notice to other servers.
210     */
211 michael 4589 if ((source_p->connection->nick.last_attempt +
212 michael 4341 ConfigGeneral.max_nick_time) < CurrentTime)
213 michael 4589 source_p->connection->nick.count = 0;
214 michael 2368
215 michael 4341 if (ConfigGeneral.anti_nick_flood &&
216 michael 2368 !HasUMode(source_p, UMODE_OPER) &&
217 michael 4589 source_p->connection->nick.count >
218 michael 4341 ConfigGeneral.max_nick_changes)
219 michael 2368 {
220 michael 4378 sendto_one_numeric(source_p, &me, ERR_NICKTOOFAST, nick,
221 michael 4341 ConfigGeneral.max_nick_time);
222 michael 2368 return;
223     }
224    
225 michael 4589 source_p->connection->nick.last_attempt = CurrentTime;
226     source_p->connection->nick.count++;
227 michael 1192
228 michael 7613 int samenick = !irccmp(source_p->name, nick);
229 michael 2368
230     if (!samenick)
231 michael 1192 {
232 michael 2368 source_p->tsinfo = CurrentTime;
233     clear_ban_cache_client(source_p);
234     watch_check_hash(source_p, RPL_LOGOFF);
235 michael 1192
236 michael 2368 if (HasUMode(source_p, UMODE_REGISTERED))
237 michael 1192 {
238 michael 2368 unsigned int oldmodes = source_p->umodes;
239 michael 3680 char modebuf[IRCD_BUFSIZE] = "";
240 michael 1192
241 michael 2368 DelUMode(source_p, UMODE_REGISTERED);
242 michael 7598 send_umode(source_p, 1, oldmodes, modebuf);
243 michael 1192 }
244 michael 2368 }
245 michael 1192
246 michael 2368 sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE,
247     "Nick change: From %s to %s [%s@%s]",
248     source_p->name, nick, source_p->username, source_p->host);
249 michael 6775 sendto_common_channels_local(source_p, 1, 0, 0, ":%s!%s@%s NICK :%s",
250 michael 2368 source_p->name, source_p->username,
251     source_p->host, nick);
252     whowas_add_history(source_p, 1);
253 michael 1192
254 michael 6781 sendto_server(source_p, 0, 0, ":%s NICK %s :%ju",
255     source_p->id, nick, source_p->tsinfo);
256 michael 1192
257 michael 2368 hash_del_client(source_p);
258     strlcpy(source_p->name, nick, sizeof(source_p->name));
259     hash_add_client(source_p);
260 michael 1192
261 michael 2368 if (!samenick)
262     watch_check_hash(source_p, RPL_LOGON);
263 michael 1192
264 michael 2368 /* fd_desc is long enough */
265 michael 6634 fd_note(&source_p->connection->fd, "Nick: %s", source_p->name);
266 michael 1192 }
267    
268 michael 4092 /*!
269     *
270     * \param source_p Pointer to allocated Client struct from which the message
271     * originally comes from. This can be a local or remote client.
272     * \param parc Integer holding the number of supplied arguments.
273     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
274     * pointers.
275     * \note Valid arguments for this command are:
276     *
277     * - parv[0] = command
278     * - parv[1] = nickname
279     * - parv[2] = timestamp
280 michael 1997 */
281     static void
282 michael 4091 change_remote_nick(struct Client *source_p, char *parv[])
283 michael 1997 {
284 michael 4166 assert(!EmptyString(parv[1]));
285 michael 4091 assert(IsClient(source_p));
286     assert(source_p->name[0]);
287    
288     /* Client changing their nick */
289 michael 7613 int samenick = !irccmp(source_p->name, parv[1]);
290    
291 michael 4091 if (!samenick)
292 michael 1997 {
293 michael 4091 DelUMode(source_p, UMODE_REGISTERED);
294     watch_check_hash(source_p, RPL_LOGOFF);
295 michael 7329 source_p->tsinfo = strtoumax(parv[2], NULL, 10);
296 michael 4091 assert(source_p->tsinfo > 0);
297 michael 1997 }
298    
299 michael 6775 sendto_common_channels_local(source_p, 1, 0, 0, ":%s!%s@%s NICK :%s",
300 michael 4091 source_p->name, source_p->username,
301     source_p->host, parv[1]);
302 michael 1997
303 michael 4091 whowas_add_history(source_p, 1);
304 michael 6781 sendto_server(source_p, 0, 0, ":%s NICK %s :%ju",
305     source_p->id, parv[1], source_p->tsinfo);
306 michael 1997
307 michael 4092 /* Set the new nick name */
308 michael 4091 hash_del_client(source_p);
309     strlcpy(source_p->name, parv[1], sizeof(source_p->name));
310 michael 1997 hash_add_client(source_p);
311    
312     if (!samenick)
313     watch_check_hash(source_p, RPL_LOGON);
314     }
315    
316 michael 4092 /*!
317     *
318     * \param source_p Pointer to allocated Client struct from which the message
319     * originally comes from. This can be a local or remote client.
320     * \param parc Integer holding the number of supplied arguments.
321     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
322     * pointers.
323     * \note Valid arguments for this command are:
324     *
325     * - parv[ 0] = command
326     * - parv[ 1] = nickname
327     * - parv[ 2] = hop count
328     * - parv[ 3] = TS
329     * - parv[ 4] = umode
330     * - parv[ 5] = username
331     * - parv[ 6] = hostname
332     * - parv[ 7] = ip
333     * - parv[ 8] = uid
334 michael 4820 * - parv[ 9] = services account
335 michael 4092 * - parv[10] = ircname (gecos)
336 michael 1997 */
337     static void
338 michael 4091 uid_from_server(struct Client *source_p, int parc, char *parv[])
339 michael 1997 {
340 michael 4091 struct Client *client_p = NULL;
341 michael 1997
342 michael 4091 client_p = make_client(source_p->from);
343 michael 4137 client_p->servptr = source_p;
344 michael 4091 client_p->hopcount = atoi(parv[2]);
345 michael 7329 client_p->tsinfo = strtoumax(parv[3], NULL, 10);
346 michael 4092
347 michael 6921 strlcpy(client_p->account, parv[9], sizeof(client_p->account));
348 michael 4091 strlcpy(client_p->name, parv[1], sizeof(client_p->name));
349     strlcpy(client_p->id, parv[8], sizeof(client_p->id));
350     strlcpy(client_p->sockhost, parv[7], sizeof(client_p->sockhost));
351     strlcpy(client_p->info, parv[parc - 1], sizeof(client_p->info));
352     strlcpy(client_p->host, parv[6], sizeof(client_p->host));
353     strlcpy(client_p->username, parv[5], sizeof(client_p->username));
354 michael 1997
355 michael 4091 hash_add_client(client_p);
356     hash_add_id(client_p);
357 michael 1997
358 michael 6153 /* Parse user modes */
359 michael 3283 for (const char *m = &parv[4][1]; *m; ++m)
360 michael 1997 {
361 michael 5393 const struct user_modes *tab = umode_map[(unsigned char)*m];
362 michael 1997
363 michael 5393 if (!tab)
364     continue;
365     if ((tab->flag & UMODE_INVISIBLE) && !HasUMode(client_p, UMODE_INVISIBLE))
366 michael 1997 ++Count.invisi;
367 michael 5393 if ((tab->flag & UMODE_OPER) && !HasUMode(client_p, UMODE_OPER))
368 michael 1997 ++Count.oper;
369    
370 michael 5393 AddUMode(client_p, tab->flag);
371 michael 1997 }
372    
373 michael 4091 register_remote_user(client_p);
374 michael 1997 }
375    
376 michael 4092 /*!
377     *
378     * \param source_p Pointer to allocated Client struct from which the message
379     * originally comes from. This can be a local or remote client.
380     * \param parc Integer holding the number of supplied arguments.
381     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
382     * pointers.
383     * \note Valid arguments for this command are:
384     *
385     * - parv[ 0] = command
386     * - parv[ 1] = nickname
387     * - parv[ 2] = hop count
388     * - parv[ 3] = TS
389     * - parv[ 4] = umode
390     * - parv[ 5] = username
391     * - parv[ 6] = hostname
392     * - parv[ 7] = ip
393     * - parv[ 8] = uid
394     * - parv[ 9] = services id (account name)
395     * - parv[10] = ircname (gecos)
396     */
397 michael 4091 static int
398     perform_uid_introduction_collides(struct Client *source_p, struct Client *target_p,
399     int parc, char *parv[])
400 michael 1997 {
401 michael 4091 const char *uid = parv[8];
402 michael 7329 uintmax_t newts = strtoumax(parv[3], NULL, 10);
403 michael 2820
404 michael 4091 assert(IsServer(source_p));
405     assert(IsClient(target_p));
406    
407 michael 2004 /* Server introducing new nick */
408 michael 4091
409     /* If we don't have a TS, or their TS's are the same, kill both */
410     if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
411 michael 1997 {
412 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
413 michael 4091 "Nick collision on %s(%s <- %s)(both killed)",
414     target_p->name, target_p->from->name,
415     source_p->from->name);
416 michael 2820
417 michael 4091 sendto_one(source_p, ":%s KILL %s :%s (Nick collision (new))",
418     me.id, uid, me.name);
419 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick collision (new))",
420 michael 4091 me.id, target_p->id, me.name);
421 michael 1997
422 michael 4091 ++ServerStats.is_kill;
423     sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
424 michael 3178
425 michael 4091 AddFlag(target_p, FLAGS_KILLED);
426     exit_client(target_p, "Nick collision (new)");
427     return 0;
428     }
429 michael 1997
430 michael 4091 /* The timestamps are different */
431 michael 7613 int sameuser = !irccmp(target_p->username, parv[5]) &&
432     !irccmp(target_p->sockhost, parv[7]);
433 michael 2820
434 michael 4091 /*
435     * If the users are the same (loaded a client on a different server)
436     * and the new users ts is older, or the users are different and the
437     * new users ts is newer, ignore the new client and let it do the kill
438     */
439     if ((sameuser && newts < target_p->tsinfo) ||
440     (!sameuser && newts > target_p->tsinfo))
441     {
442     sendto_one(source_p, ":%s KILL %s :%s (Nick collision (new))",
443     me.id, uid, me.name);
444     return 0;
445     }
446 michael 1997
447 michael 4091 if (sameuser)
448 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
449 michael 4091 "Nick collision on %s(%s <- %s)(older killed)",
450     target_p->name, target_p->from->name,
451     source_p->from->name);
452     else
453 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
454 michael 4091 "Nick collision on %s(%s <- %s)(newer killed)",
455     target_p->name, target_p->from->name,
456     source_p->from->name);
457 michael 1997
458 michael 4091 ++ServerStats.is_kill;
459     sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
460 michael 1997
461 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick collision (new))",
462 michael 4091 me.id, target_p->id, me.name);
463 michael 2004
464 michael 4091 AddFlag(target_p, FLAGS_KILLED);
465     exit_client(target_p, "Nick collision");
466 michael 1997
467 michael 4091 return 1;
468     }
469    
470 michael 4092 /*!
471     *
472     * \param source_p Pointer to allocated Client struct from which the message
473     * originally comes from. This can be a local or remote client.
474     * \param parc Integer holding the number of supplied arguments.
475     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
476     * pointers.
477     * \note Valid arguments for this command are:
478     *
479     * - parv[0] = command
480     * - parv[1] = nickname
481     * - parv[2] = timestamp
482     */
483 michael 4091 static int
484     perform_nick_change_collides(struct Client *source_p, struct Client *target_p,
485     int parc, char *parv[])
486     {
487 michael 7329 uintmax_t newts = strtoumax(parv[2], NULL, 10);
488 michael 4091
489     assert(IsClient(source_p));
490     assert(IsClient(target_p));
491     assert(newts > 0);
492    
493     /* It's a client changing nick and causing a collide */
494 michael 1997 if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
495     {
496 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
497 michael 4091 "Nick change collision from %s to %s(%s <- %s)(both killed)",
498     source_p->name, target_p->name, target_p->from->name,
499     source_p->from->name);
500 michael 2820
501 michael 4091 sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
502 michael 4194 ServerStats.is_kill += 2;
503 michael 1997
504 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick change collision)",
505 michael 4091 me.id, source_p->id, me.name);
506 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick change collision)",
507 michael 4091 me.id, target_p->id, me.name);
508 michael 1997
509 michael 4194 AddFlag(source_p, FLAGS_KILLED);
510 michael 4091 AddFlag(target_p, FLAGS_KILLED);
511 michael 4194 exit_client(source_p, "Nick collision (old)");
512 michael 4091 exit_client(target_p, "Nick collision (new)");
513     return 0;
514     }
515 michael 1997
516 michael 4091 /* The timestamps are different */
517 michael 7613 int sameuser = !irccmp(target_p->username, source_p->username) &&
518     !irccmp(target_p->sockhost, source_p->sockhost);
519 michael 4091
520     if ((sameuser && newts < target_p->tsinfo) ||
521     (!sameuser && newts > target_p->tsinfo))
522 michael 2004 {
523 michael 4091 if (sameuser)
524 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
525 michael 4091 "Nick change collision from %s to %s(%s <- %s)(older killed)",
526     source_p->name, target_p->name, target_p->from->name,
527     source_p->from->name);
528     else
529 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
530 michael 4091 "Nick change collision from %s to %s(%s <- %s)(newer killed)",
531 michael 2004 source_p->name, target_p->name, target_p->from->name,
532 michael 3156 source_p->from->name);
533 michael 2004
534 michael 4091 ++ServerStats.is_kill;
535 michael 3178
536 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick change collision)",
537 michael 4091 me.id, source_p->id, me.name);
538     AddFlag(source_p, FLAGS_KILLED);
539 michael 2004
540 michael 4091 if (sameuser)
541     exit_client(source_p, "Nick collision (old)");
542 michael 1997 else
543 michael 4091 exit_client(source_p, "Nick collision (new)");
544     return 0;
545     }
546 michael 1997
547 michael 4091 if (sameuser)
548 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
549 michael 4091 "Nick collision on %s(%s <- %s)(older killed)",
550     target_p->name, target_p->from->name,
551     source_p->from->name);
552     else
553 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
554 michael 4091 "Nick collision on %s(%s <- %s)(newer killed)",
555     target_p->name, target_p->from->name,
556     source_p->from->name);
557 michael 1997
558 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick collision)",
559 michael 4091 me.id, target_p->id, me.name);
560 michael 1997
561 michael 4091 ++ServerStats.is_kill;
562     sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
563 michael 1997
564 michael 4091 AddFlag(target_p, FLAGS_KILLED);
565     exit_client(target_p, "Nick collision");
566    
567     return 1;
568 michael 1997 }
569    
570 michael 3300 /*! \brief NICK command handler
571 adx 30 *
572 michael 981 * \param source_p Pointer to allocated Client struct from which the message
573     * originally comes from. This can be a local or remote client.
574     * \param parc Integer holding the number of supplied arguments.
575     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
576     * pointers.
577     * \note Valid arguments for this command are:
578 michael 3096 * - parv[0] = command
579 michael 981 * - parv[1] = nickname
580 adx 30 */
581 michael 2820 static int
582 michael 3156 mr_nick(struct Client *source_p, int parc, char *parv[])
583 adx 30 {
584 michael 3680 char nick[NICKLEN + 1] = "";
585 michael 885 struct Client *target_p = NULL;
586 michael 7281 const struct ResvItem *resv = NULL;
587 michael 885
588 adx 30 if (parc < 2 || EmptyString(parv[1]))
589     {
590 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
591 michael 2820 return 0;
592 adx 30 }
593    
594 michael 2004 /* Copy the nick and terminate it */
595 michael 4341 strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));
596 adx 30
597 michael 2004 /* Check the nickname is ok */
598 michael 1165 if (!valid_nickname(nick, 1))
599 adx 30 {
600 michael 3109 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, parv[1], "Erroneous Nickname");
601 michael 2820 return 0;
602 adx 30 }
603    
604 michael 2004 /* Check if the nick is resv'd */
605 michael 7281 if ((resv = resv_find(nick, match)))
606 adx 30 {
607 michael 7281 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, resv->reason);
608 michael 1698 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
609 michael 2686 "Forbidding reserved nick %s from user %s",
610 michael 3156 nick, get_client_name(source_p, HIDE_IP));
611 michael 2820 return 0;
612 adx 30 }
613    
614 michael 5600 if ((target_p = hash_find_client(nick)) == NULL || target_p == source_p)
615 michael 1003 set_initial_nick(source_p, nick);
616 adx 30 else
617 michael 4229 sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);
618 michael 3109
619 michael 2820 return 0;
620 adx 30 }
621    
622 michael 3300 /*! \brief NICK command handler
623 adx 30 *
624 michael 981 * \param source_p Pointer to allocated Client struct from which the message
625     * originally comes from. This can be a local or remote client.
626     * \param parc Integer holding the number of supplied arguments.
627     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
628     * pointers.
629     * \note Valid arguments for this command are:
630 michael 3096 * - parv[0] = command
631 michael 981 * - parv[1] = nickname
632 adx 30 */
633 michael 2820 static int
634 michael 3156 m_nick(struct Client *source_p, int parc, char *parv[])
635 adx 30 {
636 michael 3680 char nick[NICKLEN + 1] = "";
637 michael 885 struct Client *target_p = NULL;
638 michael 7281 const struct ResvItem *resv = NULL;
639 adx 30
640 michael 3156 assert(MyClient(source_p));
641 michael 1193
642 adx 30 if (parc < 2 || EmptyString(parv[1]))
643     {
644 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
645 michael 2820 return 0;
646 adx 30 }
647    
648 michael 4092 /* Mark end of grace period, to prevent nickflooding */
649 adx 30 if (!IsFloodDone(source_p))
650     flood_endgrace(source_p);
651    
652 michael 4092 /* Terminate nick to NICKLEN */
653 michael 4341 strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));
654 adx 30
655 michael 4092 /* Check the nickname is ok */
656 michael 1165 if (!valid_nickname(nick, 1))
657 adx 30 {
658 michael 3109 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, "Erroneous Nickname");
659 michael 2820 return 0;
660 adx 30 }
661    
662 michael 6314 if (!HasFlag(source_p, FLAGS_EXEMPTRESV) &&
663 michael 6448 !(HasUMode(source_p, UMODE_OPER) && HasOFlag(source_p, OPER_FLAG_NICK_RESV)) &&
664 michael 7281 (resv = resv_find(nick, match)))
665 adx 30 {
666 michael 7281 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, resv->reason);
667 michael 1698 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
668 michael 2686 "Forbidding reserved nick %s from user %s",
669 michael 3156 nick, get_client_name(source_p, HIDE_IP));
670 michael 2820 return 0;
671 adx 30 }
672    
673 michael 1169 if ((target_p = hash_find_client(nick)) == NULL)
674 michael 1193 change_local_nick(source_p, nick);
675 michael 981 else if (target_p == source_p)
676 adx 30 {
677 michael 981 /*
678     * If (target_p == source_p) the client is changing nicks between
679 adx 30 * equivalent nicknames ie: [nick] -> {nick}
680     */
681    
682 michael 2004 /* Check the nick isn't exactly the same */
683 michael 981 if (strcmp(target_p->name, nick))
684 michael 1193 change_local_nick(source_p, nick);
685 michael 981 }
686     else if (IsUnknown(target_p))
687     {
688     /*
689 michael 2004 * If the client that has the nick isn't registered yet (nick but no
690 adx 30 * user) then drop the unregged client
691     */
692 michael 4092 exit_client(target_p, "Overridden by other sign on");
693 michael 1193 change_local_nick(source_p, nick);
694 adx 30 }
695     else
696 michael 4229 sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);
697 michael 3109
698 michael 2820 return 0;
699 adx 30 }
700    
701 michael 3300 /*! \brief NICK command handler
702 michael 981 *
703     * \param source_p Pointer to allocated Client struct from which the message
704     * originally comes from. This can be a local or remote client.
705     * \param parc Integer holding the number of supplied arguments.
706     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
707     * pointers.
708     * \note Valid arguments for this command are:
709     *
710 adx 30 * server -> server nick change
711 michael 3300 * - parv[0] = command
712     * - parv[1] = nickname
713 michael 4092 * - parv[2] = timestamp
714 adx 30 */
715 michael 2820 static int
716 michael 3156 ms_nick(struct Client *source_p, int parc, char *parv[])
717 adx 30 {
718 michael 981 struct Client *target_p = NULL;
719 adx 30
720 michael 4091 if (parc != 3 || EmptyString(parv[parc - 1]))
721 michael 2820 return 0;
722 adx 30
723 michael 6753 if (!IsClient(source_p))
724     return 0; /* Servers and unknown clients can't change nicks.. */
725 adx 30
726 michael 6751 if (check_clean_nick(source_p, parv[1]))
727 michael 3135 return 0;
728 adx 30
729 michael 4580 /* If the nick doesn't exist, allow it and process like normal */
730 michael 1169 if ((target_p = hash_find_client(parv[1])) == NULL)
731 michael 4091 change_remote_nick(source_p, parv);
732 michael 981 else if (IsUnknown(target_p))
733 adx 30 {
734 michael 2004 /* We're not living in the past anymore, an unknown client is local only. */
735 michael 4092 exit_client(target_p, "Overridden by other sign on");
736 michael 4091 change_remote_nick(source_p, parv);
737 adx 30 }
738 michael 981 else if (target_p == source_p)
739 adx 30 {
740 michael 981 if (strcmp(target_p->name, parv[1]))
741 michael 4091 change_remote_nick(source_p, parv);
742 adx 30 }
743 michael 4091 else if (perform_nick_change_collides(source_p, target_p, parc, parv))
744     change_remote_nick(source_p, parv);
745 michael 2820 return 0;
746 adx 30 }
747    
748 michael 3300 /*! \brief UID command handler
749 adx 30 *
750 michael 981 * \param source_p Pointer to allocated Client struct from which the message
751     * originally comes from. This can be a local or remote client.
752     * \param parc Integer holding the number of supplied arguments.
753     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
754     * pointers.
755     * \note Valid arguments for this command are:
756     *
757 michael 3300 * - parv[ 0] = command
758     * - parv[ 1] = nickname
759     * - parv[ 2] = hop count
760     * - parv[ 3] = TS
761     * - parv[ 4] = umode
762     * - parv[ 5] = username
763     * - parv[ 6] = hostname
764     * - parv[ 7] = ip
765     * - parv[ 8] = uid
766 michael 3677 * - parv[ 9] = services id (account name)
767 michael 3300 * - parv[10] = ircname (gecos)
768 adx 30 */
769 michael 2820 static int
770 michael 3156 ms_uid(struct Client *source_p, int parc, char *parv[])
771 adx 30 {
772 michael 981 struct Client *target_p = NULL;
773 adx 30
774 michael 6751 if (check_clean_nick(source_p, parv[1]) ||
775     check_clean_user(source_p, parv[1], parv[5]) ||
776 michael 6755 check_clean_host(source_p, parv[1], parv[6]) ||
777     check_clean_uid(source_p, parv[1], parv[8]))
778 michael 2820 return 0;
779 adx 30
780 michael 981 /*
781 michael 2004 * If there is an ID collision, kill our client, and kill theirs.
782     * This may generate 401's, but it ensures that both clients always
783 adx 30 * go, even if the other server refuses to do the right thing.
784     */
785 michael 3680 if ((target_p = hash_find_id(parv[8])))
786 adx 30 {
787 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
788 michael 1997 "ID collision on %s(%s <- %s)(both killed)",
789     target_p->name, target_p->from->name,
790 michael 3156 source_p->from->name);
791 adx 30
792 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (ID collision)",
793 michael 3178 me.id, target_p->id, me.name);
794    
795 michael 896 ++ServerStats.is_kill;
796 michael 1219 AddFlag(target_p, FLAGS_KILLED);
797 michael 3171 exit_client(target_p, "ID Collision");
798 michael 2820 return 0;
799 adx 30 }
800 michael 1997
801 michael 1169 if ((target_p = hash_find_client(parv[1])) == NULL)
802 michael 4091 uid_from_server(source_p, parc, parv);
803 adx 30 else if (IsUnknown(target_p))
804     {
805 michael 4092 exit_client(target_p, "Overridden by other sign on");
806 michael 4091 uid_from_server(source_p, parc, parv);
807 adx 30 }
808 michael 4091 else if (perform_uid_introduction_collides(source_p, target_p, parc, parv))
809     uid_from_server(source_p, parc, parv);
810 michael 2820 return 0;
811 adx 30 }
812    
813 michael 2820 static struct Message nick_msgtab =
814     {
815 michael 5880 .cmd = "NICK",
816     .args_max = MAXPARA,
817     .handlers[UNREGISTERED_HANDLER] = mr_nick,
818     .handlers[CLIENT_HANDLER] = m_nick,
819     .handlers[SERVER_HANDLER] = ms_nick,
820     .handlers[ENCAP_HANDLER] = m_ignore,
821     .handlers[OPER_HANDLER] = m_nick
822 michael 1230 };
823    
824 michael 2820 static struct Message uid_msgtab =
825     {
826 michael 5880 .cmd = "UID",
827 michael 6921 .args_min = 11,
828 michael 5880 .args_max = MAXPARA,
829     .handlers[UNREGISTERED_HANDLER] = m_ignore,
830     .handlers[CLIENT_HANDLER] = m_ignore,
831     .handlers[SERVER_HANDLER] = ms_uid,
832     .handlers[ENCAP_HANDLER] = m_ignore,
833     .handlers[OPER_HANDLER] = m_ignore
834 michael 1230 };
835    
836     static void
837     module_init(void)
838     {
839     mod_add_cmd(&uid_msgtab);
840     mod_add_cmd(&nick_msgtab);
841     }
842    
843     static void
844     module_exit(void)
845     {
846     mod_del_cmd(&uid_msgtab);
847     mod_del_cmd(&nick_msgtab);
848     }
849    
850 michael 2820 struct module module_entry =
851     {
852 michael 1230 .version = "$Revision$",
853     .modinit = module_init,
854     .modexit = module_exit,
855     .flags = MODULE_FLAG_CORE
856     };

Properties

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