ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_nick.c
Revision: 1442
Committed: Wed Jun 20 19:24:49 2012 UTC (14 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/core/m_nick.c
File size: 30722 byte(s)
Log Message:
- Added back server notice when a client tries to obtain a reserved nick name.
  Kinda useful notice; no idea why it got removed 10 years ago

File Contents

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

Properties

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