ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 6313
Committed: Sat Aug 1 18:03:39 2015 UTC (10 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 27839 byte(s)
Log Message:
- Make use of the *Flag() macros in some more places

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

Properties

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