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: 7329
Committed: Thu Feb 18 21:07:50 2016 UTC (8 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 26873 byte(s)
Log Message:
- Now that we got time_t to work nicely on openbsd with snprintf's conversion specifiers,
  we ran into a similiar issue on Raspbian/ARMv7's time_t which is of signed 32 bit and
  doesn't cope at all with %j. Instead of doing tricks, get rid of time_t everywhere and
  forever and use uintmax_t instead which has at least a 'standardized' conversion specifier
  associated with it.

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 michael 2368 int samenick = 0;
204    
205 michael 1192 assert(source_p->name[0] && !EmptyString(nick));
206 michael 4382 assert(MyClient(source_p));
207 michael 1192
208     /*
209     * Client just changing his/her nick. If he/she is
210     * on a channel, send note of change to all clients
211     * on that channel. Propagate notice to other servers.
212     */
213 michael 4589 if ((source_p->connection->nick.last_attempt +
214 michael 4341 ConfigGeneral.max_nick_time) < CurrentTime)
215 michael 4589 source_p->connection->nick.count = 0;
216 michael 2368
217 michael 4341 if (ConfigGeneral.anti_nick_flood &&
218 michael 2368 !HasUMode(source_p, UMODE_OPER) &&
219 michael 4589 source_p->connection->nick.count >
220 michael 4341 ConfigGeneral.max_nick_changes)
221 michael 2368 {
222 michael 4378 sendto_one_numeric(source_p, &me, ERR_NICKTOOFAST, nick,
223 michael 4341 ConfigGeneral.max_nick_time);
224 michael 2368 return;
225     }
226    
227 michael 4589 source_p->connection->nick.last_attempt = CurrentTime;
228     source_p->connection->nick.count++;
229 michael 1192
230 michael 2368 samenick = !irccmp(source_p->name, nick);
231    
232     if (!samenick)
233 michael 1192 {
234 michael 2368 source_p->tsinfo = CurrentTime;
235     clear_ban_cache_client(source_p);
236     watch_check_hash(source_p, RPL_LOGOFF);
237 michael 1192
238 michael 2368 if (HasUMode(source_p, UMODE_REGISTERED))
239 michael 1192 {
240 michael 2368 unsigned int oldmodes = source_p->umodes;
241 michael 3680 char modebuf[IRCD_BUFSIZE] = "";
242 michael 1192
243 michael 2368 DelUMode(source_p, UMODE_REGISTERED);
244 michael 4021 send_umode(source_p, source_p, oldmodes, modebuf);
245 michael 1192 }
246 michael 2368 }
247 michael 1192
248 michael 2368 sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE,
249     "Nick change: From %s to %s [%s@%s]",
250     source_p->name, nick, source_p->username, source_p->host);
251 michael 6775 sendto_common_channels_local(source_p, 1, 0, 0, ":%s!%s@%s NICK :%s",
252 michael 2368 source_p->name, source_p->username,
253     source_p->host, nick);
254     whowas_add_history(source_p, 1);
255 michael 1192
256 michael 6781 sendto_server(source_p, 0, 0, ":%s NICK %s :%ju",
257     source_p->id, nick, source_p->tsinfo);
258 michael 1192
259 michael 2368 hash_del_client(source_p);
260     strlcpy(source_p->name, nick, sizeof(source_p->name));
261     hash_add_client(source_p);
262 michael 1192
263 michael 2368 if (!samenick)
264     watch_check_hash(source_p, RPL_LOGON);
265 michael 1192
266 michael 2368 /* fd_desc is long enough */
267 michael 6634 fd_note(&source_p->connection->fd, "Nick: %s", source_p->name);
268 michael 1192 }
269    
270 michael 4092 /*!
271     *
272     * \param source_p Pointer to allocated Client struct from which the message
273     * originally comes from. This can be a local or remote client.
274     * \param parc Integer holding the number of supplied arguments.
275     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
276     * pointers.
277     * \note Valid arguments for this command are:
278     *
279     * - parv[0] = command
280     * - parv[1] = nickname
281     * - parv[2] = timestamp
282 michael 1997 */
283     static void
284 michael 4091 change_remote_nick(struct Client *source_p, char *parv[])
285 michael 1997 {
286 michael 6749 const int samenick = !irccmp(source_p->name, parv[1]);
287 michael 1997
288 michael 4166 assert(!EmptyString(parv[1]));
289 michael 4091 assert(IsClient(source_p));
290     assert(source_p->name[0]);
291    
292     /* Client changing their nick */
293     if (!samenick)
294 michael 1997 {
295 michael 4091 DelUMode(source_p, UMODE_REGISTERED);
296     watch_check_hash(source_p, RPL_LOGOFF);
297 michael 7329 source_p->tsinfo = strtoumax(parv[2], NULL, 10);
298 michael 4091 assert(source_p->tsinfo > 0);
299 michael 1997 }
300    
301 michael 6775 sendto_common_channels_local(source_p, 1, 0, 0, ":%s!%s@%s NICK :%s",
302 michael 4091 source_p->name, source_p->username,
303     source_p->host, parv[1]);
304 michael 1997
305 michael 4091 whowas_add_history(source_p, 1);
306 michael 6781 sendto_server(source_p, 0, 0, ":%s NICK %s :%ju",
307     source_p->id, parv[1], source_p->tsinfo);
308 michael 1997
309 michael 4092 /* Set the new nick name */
310 michael 4091 hash_del_client(source_p);
311     strlcpy(source_p->name, parv[1], sizeof(source_p->name));
312 michael 1997 hash_add_client(source_p);
313    
314     if (!samenick)
315     watch_check_hash(source_p, RPL_LOGON);
316     }
317    
318 michael 4092 /*!
319     *
320     * \param source_p Pointer to allocated Client struct from which the message
321     * originally comes from. This can be a local or remote client.
322     * \param parc Integer holding the number of supplied arguments.
323     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
324     * pointers.
325     * \note Valid arguments for this command are:
326     *
327     * - parv[ 0] = command
328     * - parv[ 1] = nickname
329     * - parv[ 2] = hop count
330     * - parv[ 3] = TS
331     * - parv[ 4] = umode
332     * - parv[ 5] = username
333     * - parv[ 6] = hostname
334     * - parv[ 7] = ip
335     * - parv[ 8] = uid
336 michael 4820 * - parv[ 9] = services account
337 michael 4092 * - parv[10] = ircname (gecos)
338 michael 1997 */
339     static void
340 michael 4091 uid_from_server(struct Client *source_p, int parc, char *parv[])
341 michael 1997 {
342 michael 4091 struct Client *client_p = NULL;
343 michael 1997
344 michael 4091 client_p = make_client(source_p->from);
345 michael 4137 client_p->servptr = source_p;
346 michael 4091 client_p->hopcount = atoi(parv[2]);
347 michael 7329 client_p->tsinfo = strtoumax(parv[3], NULL, 10);
348 michael 4092
349 michael 6921 strlcpy(client_p->account, parv[9], sizeof(client_p->account));
350 michael 4091 strlcpy(client_p->name, parv[1], sizeof(client_p->name));
351     strlcpy(client_p->id, parv[8], sizeof(client_p->id));
352     strlcpy(client_p->sockhost, parv[7], sizeof(client_p->sockhost));
353     strlcpy(client_p->info, parv[parc - 1], sizeof(client_p->info));
354     strlcpy(client_p->host, parv[6], sizeof(client_p->host));
355     strlcpy(client_p->username, parv[5], sizeof(client_p->username));
356 michael 1997
357 michael 4091 hash_add_client(client_p);
358     hash_add_id(client_p);
359 michael 1997
360 michael 6153 /* Parse user modes */
361 michael 3283 for (const char *m = &parv[4][1]; *m; ++m)
362 michael 1997 {
363 michael 5393 const struct user_modes *tab = umode_map[(unsigned char)*m];
364 michael 1997
365 michael 5393 if (!tab)
366     continue;
367     if ((tab->flag & UMODE_INVISIBLE) && !HasUMode(client_p, UMODE_INVISIBLE))
368 michael 1997 ++Count.invisi;
369 michael 5393 if ((tab->flag & UMODE_OPER) && !HasUMode(client_p, UMODE_OPER))
370 michael 1997 ++Count.oper;
371    
372 michael 5393 AddUMode(client_p, tab->flag);
373 michael 1997 }
374    
375 michael 4091 register_remote_user(client_p);
376 michael 1997 }
377    
378 michael 4092 /*!
379     *
380     * \param source_p Pointer to allocated Client struct from which the message
381     * originally comes from. This can be a local or remote client.
382     * \param parc Integer holding the number of supplied arguments.
383     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
384     * pointers.
385     * \note Valid arguments for this command are:
386     *
387     * - parv[ 0] = command
388     * - parv[ 1] = nickname
389     * - parv[ 2] = hop count
390     * - parv[ 3] = TS
391     * - parv[ 4] = umode
392     * - parv[ 5] = username
393     * - parv[ 6] = hostname
394     * - parv[ 7] = ip
395     * - parv[ 8] = uid
396     * - parv[ 9] = services id (account name)
397     * - parv[10] = ircname (gecos)
398     */
399 michael 4091 static int
400     perform_uid_introduction_collides(struct Client *source_p, struct Client *target_p,
401     int parc, char *parv[])
402 michael 1997 {
403 michael 4091 const char *uid = parv[8];
404 michael 7329 uintmax_t newts = strtoumax(parv[3], NULL, 10);
405 michael 2004 int sameuser = 0;
406 michael 2820
407 michael 4091 assert(IsServer(source_p));
408     assert(IsClient(target_p));
409    
410 michael 2004 /* Server introducing new nick */
411 michael 4091
412     /* If we don't have a TS, or their TS's are the same, kill both */
413     if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
414 michael 1997 {
415 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
416 michael 4091 "Nick collision on %s(%s <- %s)(both killed)",
417     target_p->name, target_p->from->name,
418     source_p->from->name);
419 michael 2820
420 michael 4091 sendto_one(source_p, ":%s KILL %s :%s (Nick collision (new))",
421     me.id, uid, me.name);
422 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick collision (new))",
423 michael 4091 me.id, target_p->id, me.name);
424 michael 1997
425 michael 4091 ++ServerStats.is_kill;
426     sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
427 michael 3178
428 michael 4091 AddFlag(target_p, FLAGS_KILLED);
429     exit_client(target_p, "Nick collision (new)");
430     return 0;
431     }
432 michael 1997
433 michael 4091 /* The timestamps are different */
434 michael 6919 sameuser = !irccmp(target_p->username, parv[5]) &&
435     !irccmp(target_p->sockhost, parv[7]);
436 michael 2820
437 michael 4091 /*
438     * If the users are the same (loaded a client on a different server)
439     * and the new users ts is older, or the users are different and the
440     * new users ts is newer, ignore the new client and let it do the kill
441     */
442     if ((sameuser && newts < target_p->tsinfo) ||
443     (!sameuser && newts > target_p->tsinfo))
444     {
445     sendto_one(source_p, ":%s KILL %s :%s (Nick collision (new))",
446     me.id, uid, me.name);
447     return 0;
448     }
449 michael 1997
450 michael 4091 if (sameuser)
451 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
452 michael 4091 "Nick collision on %s(%s <- %s)(older killed)",
453     target_p->name, target_p->from->name,
454     source_p->from->name);
455     else
456 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
457 michael 4091 "Nick collision on %s(%s <- %s)(newer killed)",
458     target_p->name, target_p->from->name,
459     source_p->from->name);
460 michael 1997
461 michael 4091 ++ServerStats.is_kill;
462     sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
463 michael 1997
464 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick collision (new))",
465 michael 4091 me.id, target_p->id, me.name);
466 michael 2004
467 michael 4091 AddFlag(target_p, FLAGS_KILLED);
468     exit_client(target_p, "Nick collision");
469 michael 1997
470 michael 4091 return 1;
471     }
472    
473 michael 4092 /*!
474     *
475     * \param source_p Pointer to allocated Client struct from which the message
476     * originally comes from. This can be a local or remote client.
477     * \param parc Integer holding the number of supplied arguments.
478     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
479     * pointers.
480     * \note Valid arguments for this command are:
481     *
482     * - parv[0] = command
483     * - parv[1] = nickname
484     * - parv[2] = timestamp
485     */
486 michael 4091 static int
487     perform_nick_change_collides(struct Client *source_p, struct Client *target_p,
488     int parc, char *parv[])
489     {
490     int sameuser = 0;
491 michael 7329 uintmax_t newts = strtoumax(parv[2], NULL, 10);
492 michael 4091
493     assert(IsClient(source_p));
494     assert(IsClient(target_p));
495     assert(newts > 0);
496    
497     /* It's a client changing nick and causing a collide */
498 michael 1997 if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
499     {
500 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
501 michael 4091 "Nick change collision from %s to %s(%s <- %s)(both killed)",
502     source_p->name, target_p->name, target_p->from->name,
503     source_p->from->name);
504 michael 2820
505 michael 4091 sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
506 michael 4194 ServerStats.is_kill += 2;
507 michael 1997
508 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick change collision)",
509 michael 4091 me.id, source_p->id, me.name);
510 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick change collision)",
511 michael 4091 me.id, target_p->id, me.name);
512 michael 1997
513 michael 4194 AddFlag(source_p, FLAGS_KILLED);
514 michael 4091 AddFlag(target_p, FLAGS_KILLED);
515 michael 4194 exit_client(source_p, "Nick collision (old)");
516 michael 4091 exit_client(target_p, "Nick collision (new)");
517     return 0;
518     }
519 michael 1997
520 michael 4091 /* The timestamps are different */
521 michael 6919 sameuser = !irccmp(target_p->username, source_p->username) &&
522     !irccmp(target_p->sockhost, source_p->sockhost);
523 michael 4091
524     if ((sameuser && newts < target_p->tsinfo) ||
525     (!sameuser && newts > target_p->tsinfo))
526 michael 2004 {
527 michael 4091 if (sameuser)
528 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
529 michael 4091 "Nick change collision from %s to %s(%s <- %s)(older killed)",
530     source_p->name, target_p->name, target_p->from->name,
531     source_p->from->name);
532     else
533 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
534 michael 4091 "Nick change collision from %s to %s(%s <- %s)(newer killed)",
535 michael 2004 source_p->name, target_p->name, target_p->from->name,
536 michael 3156 source_p->from->name);
537 michael 2004
538 michael 4091 ++ServerStats.is_kill;
539 michael 3178
540 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick change collision)",
541 michael 4091 me.id, source_p->id, me.name);
542     AddFlag(source_p, FLAGS_KILLED);
543 michael 2004
544 michael 4091 if (sameuser)
545     exit_client(source_p, "Nick collision (old)");
546 michael 1997 else
547 michael 4091 exit_client(source_p, "Nick collision (new)");
548     return 0;
549     }
550 michael 1997
551 michael 4091 if (sameuser)
552 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
553 michael 4091 "Nick collision on %s(%s <- %s)(older killed)",
554     target_p->name, target_p->from->name,
555     source_p->from->name);
556     else
557 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
558 michael 4091 "Nick collision on %s(%s <- %s)(newer killed)",
559     target_p->name, target_p->from->name,
560     source_p->from->name);
561 michael 1997
562 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (Nick collision)",
563 michael 4091 me.id, target_p->id, me.name);
564 michael 1997
565 michael 4091 ++ServerStats.is_kill;
566     sendto_one_numeric(target_p, &me, ERR_NICKCOLLISION, target_p->name);
567 michael 1997
568 michael 4091 AddFlag(target_p, FLAGS_KILLED);
569     exit_client(target_p, "Nick collision");
570    
571     return 1;
572 michael 1997 }
573    
574 michael 3300 /*! \brief NICK command handler
575 adx 30 *
576 michael 981 * \param source_p Pointer to allocated Client struct from which the message
577     * originally comes from. This can be a local or remote client.
578     * \param parc Integer holding the number of supplied arguments.
579     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
580     * pointers.
581     * \note Valid arguments for this command are:
582 michael 3096 * - parv[0] = command
583 michael 981 * - parv[1] = nickname
584 adx 30 */
585 michael 2820 static int
586 michael 3156 mr_nick(struct Client *source_p, int parc, char *parv[])
587 adx 30 {
588 michael 3680 char nick[NICKLEN + 1] = "";
589 michael 885 struct Client *target_p = NULL;
590 michael 7281 const struct ResvItem *resv = NULL;
591 michael 885
592 adx 30 if (parc < 2 || EmptyString(parv[1]))
593     {
594 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
595 michael 2820 return 0;
596 adx 30 }
597    
598 michael 2004 /* Copy the nick and terminate it */
599 michael 4341 strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));
600 adx 30
601 michael 2004 /* Check the nickname is ok */
602 michael 1165 if (!valid_nickname(nick, 1))
603 adx 30 {
604 michael 3109 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, parv[1], "Erroneous Nickname");
605 michael 2820 return 0;
606 adx 30 }
607    
608 michael 2004 /* Check if the nick is resv'd */
609 michael 7281 if ((resv = resv_find(nick, match)))
610 adx 30 {
611 michael 7281 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, resv->reason);
612 michael 1698 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
613 michael 2686 "Forbidding reserved nick %s from user %s",
614 michael 3156 nick, get_client_name(source_p, HIDE_IP));
615 michael 2820 return 0;
616 adx 30 }
617    
618 michael 5600 if ((target_p = hash_find_client(nick)) == NULL || target_p == source_p)
619 michael 1003 set_initial_nick(source_p, nick);
620 adx 30 else
621 michael 4229 sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);
622 michael 3109
623 michael 2820 return 0;
624 adx 30 }
625    
626 michael 3300 /*! \brief NICK command handler
627 adx 30 *
628 michael 981 * \param source_p Pointer to allocated Client struct from which the message
629     * originally comes from. This can be a local or remote client.
630     * \param parc Integer holding the number of supplied arguments.
631     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
632     * pointers.
633     * \note Valid arguments for this command are:
634 michael 3096 * - parv[0] = command
635 michael 981 * - parv[1] = nickname
636 adx 30 */
637 michael 2820 static int
638 michael 3156 m_nick(struct Client *source_p, int parc, char *parv[])
639 adx 30 {
640 michael 3680 char nick[NICKLEN + 1] = "";
641 michael 885 struct Client *target_p = NULL;
642 michael 7281 const struct ResvItem *resv = NULL;
643 adx 30
644 michael 3156 assert(MyClient(source_p));
645 michael 1193
646 adx 30 if (parc < 2 || EmptyString(parv[1]))
647     {
648 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
649 michael 2820 return 0;
650 adx 30 }
651    
652 michael 4092 /* Mark end of grace period, to prevent nickflooding */
653 adx 30 if (!IsFloodDone(source_p))
654     flood_endgrace(source_p);
655    
656 michael 4092 /* Terminate nick to NICKLEN */
657 michael 4341 strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));
658 adx 30
659 michael 4092 /* Check the nickname is ok */
660 michael 1165 if (!valid_nickname(nick, 1))
661 adx 30 {
662 michael 3109 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, "Erroneous Nickname");
663 michael 2820 return 0;
664 adx 30 }
665    
666 michael 6314 if (!HasFlag(source_p, FLAGS_EXEMPTRESV) &&
667 michael 6448 !(HasUMode(source_p, UMODE_OPER) && HasOFlag(source_p, OPER_FLAG_NICK_RESV)) &&
668 michael 7281 (resv = resv_find(nick, match)))
669 adx 30 {
670 michael 7281 sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, resv->reason);
671 michael 1698 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
672 michael 2686 "Forbidding reserved nick %s from user %s",
673 michael 3156 nick, get_client_name(source_p, HIDE_IP));
674 michael 2820 return 0;
675 adx 30 }
676    
677 michael 1169 if ((target_p = hash_find_client(nick)) == NULL)
678 michael 1193 change_local_nick(source_p, nick);
679 michael 981 else if (target_p == source_p)
680 adx 30 {
681 michael 981 /*
682     * If (target_p == source_p) the client is changing nicks between
683 adx 30 * equivalent nicknames ie: [nick] -> {nick}
684     */
685    
686 michael 2004 /* Check the nick isn't exactly the same */
687 michael 981 if (strcmp(target_p->name, nick))
688 michael 1193 change_local_nick(source_p, nick);
689 michael 981 }
690     else if (IsUnknown(target_p))
691     {
692     /*
693 michael 2004 * If the client that has the nick isn't registered yet (nick but no
694 adx 30 * user) then drop the unregged client
695     */
696 michael 4092 exit_client(target_p, "Overridden by other sign on");
697 michael 1193 change_local_nick(source_p, nick);
698 adx 30 }
699     else
700 michael 4229 sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);
701 michael 3109
702 michael 2820 return 0;
703 adx 30 }
704    
705 michael 3300 /*! \brief NICK command handler
706 michael 981 *
707     * \param source_p Pointer to allocated Client struct from which the message
708     * originally comes from. This can be a local or remote client.
709     * \param parc Integer holding the number of supplied arguments.
710     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
711     * pointers.
712     * \note Valid arguments for this command are:
713     *
714 adx 30 * server -> server nick change
715 michael 3300 * - parv[0] = command
716     * - parv[1] = nickname
717 michael 4092 * - parv[2] = timestamp
718 adx 30 */
719 michael 2820 static int
720 michael 3156 ms_nick(struct Client *source_p, int parc, char *parv[])
721 adx 30 {
722 michael 981 struct Client *target_p = NULL;
723 adx 30
724 michael 4091 if (parc != 3 || EmptyString(parv[parc - 1]))
725 michael 2820 return 0;
726 adx 30
727 michael 6753 if (!IsClient(source_p))
728     return 0; /* Servers and unknown clients can't change nicks.. */
729 adx 30
730 michael 6751 if (check_clean_nick(source_p, parv[1]))
731 michael 3135 return 0;
732 adx 30
733 michael 4580 /* If the nick doesn't exist, allow it and process like normal */
734 michael 1169 if ((target_p = hash_find_client(parv[1])) == NULL)
735 michael 4091 change_remote_nick(source_p, parv);
736 michael 981 else if (IsUnknown(target_p))
737 adx 30 {
738 michael 2004 /* We're not living in the past anymore, an unknown client is local only. */
739 michael 4092 exit_client(target_p, "Overridden by other sign on");
740 michael 4091 change_remote_nick(source_p, parv);
741 adx 30 }
742 michael 981 else if (target_p == source_p)
743 adx 30 {
744 michael 981 if (strcmp(target_p->name, parv[1]))
745 michael 4091 change_remote_nick(source_p, parv);
746 adx 30 }
747 michael 4091 else if (perform_nick_change_collides(source_p, target_p, parc, parv))
748     change_remote_nick(source_p, parv);
749 michael 2820 return 0;
750 adx 30 }
751    
752 michael 3300 /*! \brief UID command handler
753 adx 30 *
754 michael 981 * \param source_p Pointer to allocated Client struct from which the message
755     * originally comes from. This can be a local or remote client.
756     * \param parc Integer holding the number of supplied arguments.
757     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
758     * pointers.
759     * \note Valid arguments for this command are:
760     *
761 michael 3300 * - parv[ 0] = command
762     * - parv[ 1] = nickname
763     * - parv[ 2] = hop count
764     * - parv[ 3] = TS
765     * - parv[ 4] = umode
766     * - parv[ 5] = username
767     * - parv[ 6] = hostname
768     * - parv[ 7] = ip
769     * - parv[ 8] = uid
770 michael 3677 * - parv[ 9] = services id (account name)
771 michael 3300 * - parv[10] = ircname (gecos)
772 adx 30 */
773 michael 2820 static int
774 michael 3156 ms_uid(struct Client *source_p, int parc, char *parv[])
775 adx 30 {
776 michael 981 struct Client *target_p = NULL;
777 adx 30
778 michael 6751 if (check_clean_nick(source_p, parv[1]) ||
779     check_clean_user(source_p, parv[1], parv[5]) ||
780 michael 6755 check_clean_host(source_p, parv[1], parv[6]) ||
781     check_clean_uid(source_p, parv[1], parv[8]))
782 michael 2820 return 0;
783 adx 30
784 michael 981 /*
785 michael 2004 * If there is an ID collision, kill our client, and kill theirs.
786     * This may generate 401's, but it ensures that both clients always
787 adx 30 * go, even if the other server refuses to do the right thing.
788     */
789 michael 3680 if ((target_p = hash_find_id(parv[8])))
790 adx 30 {
791 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
792 michael 1997 "ID collision on %s(%s <- %s)(both killed)",
793     target_p->name, target_p->from->name,
794 michael 3156 source_p->from->name);
795 adx 30
796 michael 4963 sendto_server(NULL, 0, 0, ":%s KILL %s :%s (ID collision)",
797 michael 3178 me.id, target_p->id, me.name);
798    
799 michael 896 ++ServerStats.is_kill;
800 michael 1219 AddFlag(target_p, FLAGS_KILLED);
801 michael 3171 exit_client(target_p, "ID Collision");
802 michael 2820 return 0;
803 adx 30 }
804 michael 1997
805 michael 1169 if ((target_p = hash_find_client(parv[1])) == NULL)
806 michael 4091 uid_from_server(source_p, parc, parv);
807 adx 30 else if (IsUnknown(target_p))
808     {
809 michael 4092 exit_client(target_p, "Overridden by other sign on");
810 michael 4091 uid_from_server(source_p, parc, parv);
811 adx 30 }
812 michael 4091 else if (perform_uid_introduction_collides(source_p, target_p, parc, parv))
813     uid_from_server(source_p, parc, parv);
814 michael 2820 return 0;
815 adx 30 }
816    
817 michael 2820 static struct Message nick_msgtab =
818     {
819 michael 5880 .cmd = "NICK",
820     .args_max = MAXPARA,
821     .handlers[UNREGISTERED_HANDLER] = mr_nick,
822     .handlers[CLIENT_HANDLER] = m_nick,
823     .handlers[SERVER_HANDLER] = ms_nick,
824     .handlers[ENCAP_HANDLER] = m_ignore,
825     .handlers[OPER_HANDLER] = m_nick
826 michael 1230 };
827    
828 michael 2820 static struct Message uid_msgtab =
829     {
830 michael 5880 .cmd = "UID",
831 michael 6921 .args_min = 11,
832 michael 5880 .args_max = MAXPARA,
833     .handlers[UNREGISTERED_HANDLER] = m_ignore,
834     .handlers[CLIENT_HANDLER] = m_ignore,
835     .handlers[SERVER_HANDLER] = ms_uid,
836     .handlers[ENCAP_HANDLER] = m_ignore,
837     .handlers[OPER_HANDLER] = m_ignore
838 michael 1230 };
839    
840     static void
841     module_init(void)
842     {
843     mod_add_cmd(&uid_msgtab);
844     mod_add_cmd(&nick_msgtab);
845     }
846    
847     static void
848     module_exit(void)
849     {
850     mod_del_cmd(&uid_msgtab);
851     mod_del_cmd(&nick_msgtab);
852     }
853    
854 michael 2820 struct module module_entry =
855     {
856 michael 1230 .version = "$Revision$",
857     .modinit = module_init,
858     .modexit = module_exit,
859     .flags = MODULE_FLAG_CORE
860     };

Properties

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