2 * ircd-ratbox: A slightly useful ircd.
3 * m_nick.c: Sets a users nick.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 * $Id: m_nick.c 1885 2006-08-28 10:09:50Z jilles $
30 #include "irc_string.h"
48 #include "s_newconf.h"
51 static int mr_nick(struct Client
*, struct Client
*, int, const char **);
52 static int m_nick(struct Client
*, struct Client
*, int, const char **);
53 static int mc_nick(struct Client
*, struct Client
*, int, const char **);
54 static int ms_nick(struct Client
*, struct Client
*, int, const char **);
55 static int ms_uid(struct Client
*, struct Client
*, int, const char **);
56 static int ms_euid(struct Client
*, struct Client
*, int, const char **);
57 static int ms_save(struct Client
*, struct Client
*, int, const char **);
58 static int can_save(struct Client
*);
59 static void save_user(struct Client
*, struct Client
*, struct Client
*);
61 struct Message nick_msgtab
= {
62 "NICK", 0, 0, 0, MFLG_SLOW
,
63 {{mr_nick
, 0}, {m_nick
, 0}, {mc_nick
, 3}, {ms_nick
, 8}, mg_ignore
, {m_nick
, 0}}
65 struct Message uid_msgtab
= {
66 "UID", 0, 0, 0, MFLG_SLOW
,
67 {mg_ignore
, mg_ignore
, mg_ignore
, {ms_uid
, 9}, mg_ignore
, mg_ignore
}
69 struct Message euid_msgtab
= {
70 "EUID", 0, 0, 0, MFLG_SLOW
,
71 {mg_ignore
, mg_ignore
, mg_ignore
, {ms_euid
, 12}, mg_ignore
, mg_ignore
}
73 struct Message save_msgtab
= {
74 "SAVE", 0, 0, 0, MFLG_SLOW
,
75 {mg_ignore
, mg_ignore
, mg_ignore
, {ms_save
, 3}, mg_ignore
, mg_ignore
}
78 mapi_clist_av1 nick_clist
[] = { &nick_msgtab
, &uid_msgtab
, &euid_msgtab
,
81 DECLARE_MODULE_AV1(nick
, NULL
, NULL
, nick_clist
, NULL
, NULL
, "$Revision: 1885 $");
83 static int change_remote_nick(struct Client
*, struct Client
*, time_t,
86 static int clean_nick(const char *, int loc_client
);
87 static int clean_username(const char *);
88 static int clean_host(const char *);
89 static int clean_uid(const char *uid
);
91 static void set_initial_nick(struct Client
*client_p
, struct Client
*source_p
, char *nick
);
92 static void change_local_nick(struct Client
*client_p
, struct Client
*source_p
, char *nick
, int);
93 static int register_client(struct Client
*client_p
, struct Client
*server
,
94 const char *nick
, time_t newts
, int parc
, const char *parv
[]);
96 static int perform_nick_collides(struct Client
*, struct Client
*,
97 struct Client
*, int, const char **,
98 time_t, const char *, const char *);
99 static int perform_nickchange_collides(struct Client
*, struct Client
*,
100 struct Client
*, int, const char **, time_t, const char *);
103 * parv[0] = sender prefix
107 mr_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
109 struct Client
*target_p
;
113 if (strlen(client_p
->id
) == 3)
115 exit_client(client_p
, client_p
, client_p
, "Mixing client and server protocol");
119 if(parc
< 2 || EmptyString(parv
[1]) || (parv
[1][0] == '~'))
121 sendto_one(source_p
, form_str(ERR_NONICKNAMEGIVEN
),
122 me
.name
, EmptyString(source_p
->name
) ? "*" : source_p
->name
);
126 /* due to the scandinavian origins, (~ being uppercase of ^) and ~
127 * being disallowed as a nick char, we need to chop the first ~
128 * instead of just erroring.
130 if((s
= strchr(parv
[1], '~')))
133 /* copy the nick and terminate it */
134 strlcpy(nick
, parv
[1], sizeof(nick
));
136 /* check the nickname is ok */
137 if(!clean_nick(nick
, 1))
139 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
),
140 me
.name
, EmptyString(parv
[0]) ? "*" : parv
[0], parv
[1]);
144 /* check if the nick is resv'd */
145 if(find_nick_resv(nick
))
147 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
),
148 me
.name
, EmptyString(source_p
->name
) ? "*" : source_p
->name
, nick
);
152 if(hash_find_nd(nick
))
154 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
155 me
.name
, EmptyString(source_p
->name
) ? "*" : source_p
->name
, nick
);
159 if((target_p
= find_named_client(nick
)) == NULL
)
160 set_initial_nick(client_p
, source_p
, nick
);
161 else if(source_p
== target_p
)
162 strcpy(source_p
->name
, nick
);
164 sendto_one(source_p
, form_str(ERR_NICKNAMEINUSE
), me
.name
, "*", nick
);
170 * parv[0] = sender prefix
174 m_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
176 struct Client
*target_p
;
180 if(parc
< 2 || EmptyString(parv
[1]) || (parv
[1][0] == '~'))
182 sendto_one(source_p
, form_str(ERR_NONICKNAMEGIVEN
), me
.name
, source_p
->name
);
186 /* due to the scandinavian origins, (~ being uppercase of ^) and ~
187 * being disallowed as a nick char, we need to chop the first ~
188 * instead of just erroring.
190 if((s
= strchr(parv
[1], '~')))
193 /* mark end of grace period, to prevent nickflooding */
194 if(!IsFloodDone(source_p
))
195 flood_endgrace(source_p
);
197 /* terminate nick to NICKLEN, we dont want clean_nick() to error! */
198 strlcpy(nick
, parv
[1], sizeof(nick
));
200 /* check the nickname is ok */
201 if(!clean_nick(nick
, 1))
203 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
), me
.name
, parv
[0], nick
);
207 if(!IsExemptResv(source_p
) && find_nick_resv(nick
))
209 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
), me
.name
, source_p
->name
, nick
);
213 if(hash_find_nd(nick
))
215 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
216 me
.name
, EmptyString(source_p
->name
) ? "*" : source_p
->name
, nick
);
220 if((target_p
= find_named_client(nick
)))
222 /* If(target_p == source_p) the client is changing nicks between
223 * equivalent nicknames ie: [nick] -> {nick}
225 if(target_p
== source_p
)
227 /* check the nick isnt exactly the same */
228 if(strcmp(target_p
->name
, nick
))
229 change_local_nick(client_p
, source_p
, nick
, 1);
233 /* drop unregged client */
234 else if(IsUnknown(target_p
))
236 exit_client(NULL
, target_p
, &me
, "Overridden");
237 change_local_nick(client_p
, source_p
, nick
, 1);
240 sendto_one(source_p
, form_str(ERR_NICKNAMEINUSE
), me
.name
, parv
[0], nick
);
245 change_local_nick(client_p
, source_p
, nick
, 1);
252 * server -> server nick change
253 * parv[0] = sender prefix
255 * parv[2] = TS when nick change
257 * server introducing new nick
258 * parv[0] = sender prefix
260 * parv[2] = hop count
269 mc_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
271 struct Client
*target_p
;
274 /* if nicks erroneous, or too long, kill */
275 if(!clean_nick(parv
[1], 0))
277 ServerStats
->is_kill
++;
278 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
279 "Bad Nick: %s From: %s(via %s)",
280 parv
[1], source_p
->user
->server
, client_p
->name
);
281 sendto_one(client_p
, ":%s KILL %s :%s (Bad Nickname)", me
.name
, parv
[1], me
.name
);
283 /* bad nick change, issue kill for the old nick to the rest
286 kill_client_serv_butone(client_p
, source_p
, "%s (Bad Nickname)", me
.name
);
287 source_p
->flags
|= FLAGS_KILLED
;
288 exit_client(client_p
, source_p
, &me
, "Bad Nickname");
292 newts
= atol(parv
[2]);
293 target_p
= find_named_client(parv
[1]);
295 /* if the nick doesnt exist, allow it and process like normal */
298 change_remote_nick(client_p
, source_p
, newts
, parv
[1], 1);
300 else if(IsUnknown(target_p
))
302 exit_client(NULL
, target_p
, &me
, "Overridden");
303 change_remote_nick(client_p
, source_p
, newts
, parv
[1], 1);
305 else if(target_p
== source_p
)
307 /* client changing case of nick */
308 if(strcmp(target_p
->name
, parv
[1]))
309 change_remote_nick(client_p
, source_p
, newts
, parv
[1], 1);
311 /* we've got a collision! */
313 perform_nickchange_collides(source_p
, client_p
, target_p
,
314 parc
, parv
, newts
, parv
[1]);
320 ms_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
322 struct Client
*target_p
;
327 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
328 "Dropping server %s due to (invalid) command 'NICK' "
329 "with %d arguments (expecting 9)", client_p
->name
, parc
);
330 ilog(L_SERVER
, "Excess parameters (%d) for command 'NICK' from %s.",
331 parc
, client_p
->name
);
332 exit_client(client_p
, client_p
, client_p
, "Excess parameters to NICK command");
336 /* if nicks empty, erroneous, or too long, kill */
337 if(!clean_nick(parv
[1], 0))
339 ServerStats
->is_kill
++;
340 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
341 "Bad Nick: %s From: %s(via %s)",
342 parv
[1], parv
[7], client_p
->name
);
343 sendto_one(client_p
, ":%s KILL %s :%s (Bad Nickname)", me
.name
, parv
[1], me
.name
);
347 /* invalid username or host? */
348 if(!clean_username(parv
[5]) || !clean_host(parv
[6]))
350 ServerStats
->is_kill
++;
351 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
352 "Bad user@host: %s@%s From: %s(via %s)",
353 parv
[5], parv
[6], parv
[7], client_p
->name
);
354 sendto_one(client_p
, ":%s KILL %s :%s (Bad user@host)", me
.name
, parv
[1], me
.name
);
358 /* check the length of the clients gecos */
359 if(strlen(parv
[8]) > REALLEN
)
361 char *s
= LOCAL_COPY(parv
[8]);
362 /* why exactly do we care? --fl */
363 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
364 "Long realname from server %s for %s", parv
[7], parv
[1]);
370 newts
= atol(parv
[3]);
372 target_p
= find_named_client(parv
[1]);
374 /* if the nick doesnt exist, allow it and process like normal */
377 register_client(client_p
, NULL
, parv
[1], newts
, parc
, parv
);
379 else if(IsUnknown(target_p
))
381 exit_client(NULL
, target_p
, &me
, "Overridden");
382 register_client(client_p
, NULL
, parv
[1], newts
, parc
, parv
);
384 else if(target_p
== source_p
)
386 /* client changing case of nick */
387 if(strcmp(target_p
->name
, parv
[1]))
388 register_client(client_p
, NULL
, parv
[1], newts
, parc
, parv
);
390 /* we've got a collision! */
392 perform_nick_collides(source_p
, client_p
, target_p
, parc
, parv
,
393 newts
, parv
[1], NULL
);
410 ms_uid(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
412 struct Client
*target_p
;
415 newts
= atol(parv
[3]);
419 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
420 "Dropping server %s due to (invalid) command 'UID' "
421 "with %d arguments (expecting 10)", client_p
->name
, parc
);
422 ilog(L_SERVER
, "Excess parameters (%d) for command 'UID' from %s.",
423 parc
, client_p
->name
);
424 exit_client(client_p
, client_p
, client_p
, "Excess parameters to UID command");
428 /* if nicks erroneous, or too long, kill */
429 if(!clean_nick(parv
[1], 0))
431 ServerStats
->is_kill
++;
432 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
433 "Bad Nick: %s From: %s(via %s)",
434 parv
[1], source_p
->name
, client_p
->name
);
435 sendto_one(client_p
, ":%s KILL %s :%s (Bad Nickname)", me
.id
, parv
[8], me
.name
);
439 if(!clean_username(parv
[5]) || !clean_host(parv
[6]))
441 ServerStats
->is_kill
++;
442 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
443 "Bad user@host: %s@%s From: %s(via %s)",
444 parv
[5], parv
[6], source_p
->name
, client_p
->name
);
445 sendto_one(client_p
, ":%s KILL %s :%s (Bad user@host)", me
.id
, parv
[8], me
.name
);
449 if(!clean_uid(parv
[8]))
451 ServerStats
->is_kill
++;
452 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
453 "Bad UID: %s From: %s(via %s)",
454 parv
[8], source_p
->name
, client_p
->name
);
455 sendto_one(client_p
, ":%s KILL %s :%s (Bad UID)", me
.id
, parv
[8], me
.name
);
459 /* check length of clients gecos */
460 if(strlen(parv
[9]) > REALLEN
)
462 char *s
= LOCAL_COPY(parv
[9]);
463 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Long realname from server %s for %s",
469 target_p
= find_named_client(parv
[1]);
473 register_client(client_p
, source_p
, parv
[1], newts
, parc
, parv
);
475 else if(IsUnknown(target_p
))
477 exit_client(NULL
, target_p
, &me
, "Overridden");
478 register_client(client_p
, source_p
, parv
[1], newts
, parc
, parv
);
480 /* we've got a collision! */
482 perform_nick_collides(source_p
, client_p
, target_p
, parc
, parv
,
483 newts
, parv
[1], parv
[8]);
502 ms_euid(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
504 struct Client
*target_p
;
507 newts
= atol(parv
[3]);
511 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
512 "Dropping server %s due to (invalid) command 'EUID' "
513 "with %d arguments (expecting 12)", client_p
->name
, parc
);
514 ilog(L_SERVER
, "Excess parameters (%d) for command 'EUID' from %s.",
515 parc
, client_p
->name
);
516 exit_client(client_p
, client_p
, client_p
, "Excess parameters to EUID command");
520 /* if nicks erroneous, or too long, kill */
521 if(!clean_nick(parv
[1], 0))
523 ServerStats
->is_kill
++;
524 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
525 "Bad Nick: %s From: %s(via %s)",
526 parv
[1], source_p
->name
, client_p
->name
);
527 sendto_one(client_p
, ":%s KILL %s :%s (Bad Nickname)", me
.id
, parv
[8], me
.name
);
531 if(!clean_username(parv
[5]) || !clean_host(parv
[6]))
533 ServerStats
->is_kill
++;
534 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
535 "Bad user@host: %s@%s From: %s(via %s)",
536 parv
[5], parv
[6], source_p
->name
, client_p
->name
);
537 sendto_one(client_p
, ":%s KILL %s :%s (Bad user@host)", me
.id
, parv
[8], me
.name
);
541 if(!clean_uid(parv
[8]))
543 ServerStats
->is_kill
++;
544 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
545 "Bad UID: %s From: %s(via %s)",
546 parv
[8], source_p
->name
, client_p
->name
);
547 sendto_one(client_p
, ":%s KILL %s :%s (Bad UID)", me
.id
, parv
[8], me
.name
);
551 if(strcmp(parv
[9], "*") && !clean_host(parv
[9]))
553 ServerStats
->is_kill
++;
554 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
555 "Bad realhost: %s From: %s(via %s)",
556 parv
[9], source_p
->name
, client_p
->name
);
557 sendto_one(client_p
, ":%s KILL %s :%s (Bad user@host)", me
.id
, parv
[8], me
.name
);
561 /* check length of clients gecos */
562 if(strlen(parv
[11]) > REALLEN
)
564 char *s
= LOCAL_COPY(parv
[11]);
565 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Long realname from server %s for %s",
571 target_p
= find_named_client(parv
[1]);
575 register_client(client_p
, source_p
, parv
[1], newts
, parc
, parv
);
577 else if(IsUnknown(target_p
))
579 exit_client(NULL
, target_p
, &me
, "Overridden");
580 register_client(client_p
, source_p
, parv
[1], newts
, parc
, parv
);
582 /* we've got a collision! */
584 perform_nick_collides(source_p
, client_p
, target_p
, parc
, parv
,
585 newts
, parv
[1], parv
[8]);
595 ms_save(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
597 struct Client
*target_p
;
599 target_p
= find_id(parv
[1]);
600 if (target_p
== NULL
)
602 if (!IsPerson(target_p
))
603 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
604 "Ignored SAVE message for non-person %s from %s",
605 target_p
->name
, source_p
->name
);
606 else if (IsDigit(target_p
->name
[0]))
607 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
608 "Ignored noop SAVE message for %s from %s",
609 target_p
->name
, source_p
->name
);
610 else if (target_p
->tsinfo
== atol(parv
[2]))
611 save_user(client_p
, source_p
, target_p
);
613 sendto_realops_snomask(SNO_SKILL
, L_ALL
,
614 "Ignored SAVE message for %s from %s",
615 target_p
->name
, source_p
->name
);
621 * input - nickname to check
622 * output - 0 if erroneous, else 1
626 clean_nick(const char *nick
, int loc_client
)
630 /* nicks cant start with a digit or -, and must have a length */
631 if(*nick
== '-' || *nick
== '\0')
634 if(loc_client
&& IsDigit(*nick
))
640 if(!IsNickChar(*nick
))
653 * input - username to check
654 * output - 0 if erroneous, else 0
658 clean_username(const char *username
)
662 for(; *username
; username
++)
666 if(!IsUserChar(*username
))
678 * input - host to check
679 * output - 0 if erroneous, else 0
683 clean_host(const char *host
)
691 if(!IsHostChar(*host
))
702 clean_uid(const char *uid
)
724 set_initial_nick(struct Client
*client_p
, struct Client
*source_p
, char *nick
)
726 char buf
[USERLEN
+ 1];
728 /* This had to be copied here to avoid problems.. */
729 source_p
->tsinfo
= CurrentTime
;
730 if(source_p
->name
[0])
731 del_from_client_hash(source_p
->name
, source_p
);
733 strcpy(source_p
->name
, nick
);
734 add_to_client_hash(nick
, source_p
);
736 /* fd_desc is long enough */
737 comm_note(client_p
->localClient
->fd
, "Nick: %s", nick
);
739 if(source_p
->flags
& FLAGS_SENTUSER
)
741 strlcpy(buf
, source_p
->username
, sizeof(buf
));
743 /* got user, heres nick. */
744 register_local_user(client_p
, source_p
, buf
);
750 change_local_nick(struct Client
*client_p
, struct Client
*source_p
,
751 char *nick
, int dosend
)
753 struct Client
*target_p
;
754 dlink_node
*ptr
, *next_ptr
;
755 struct Channel
*chptr
;
760 chptr
= find_bannickchange_channel(source_p
);
763 sendto_one_numeric(source_p
, ERR_BANNICKCHANGE
,
764 form_str(ERR_BANNICKCHANGE
),
765 nick
, chptr
->chname
);
768 if((source_p
->localClient
->last_nick_change
+ ConfigFileEntry
.max_nick_time
) < CurrentTime
)
769 source_p
->localClient
->number_of_nick_changes
= 0;
771 source_p
->localClient
->last_nick_change
= CurrentTime
;
772 source_p
->localClient
->number_of_nick_changes
++;
774 if(ConfigFileEntry
.anti_nick_flood
&& !IsOper(source_p
) &&
775 source_p
->localClient
->number_of_nick_changes
> ConfigFileEntry
.max_nick_changes
)
777 sendto_one(source_p
, form_str(ERR_NICKTOOFAST
),
778 me
.name
, source_p
->name
, source_p
->name
,
779 nick
, ConfigFileEntry
.max_nick_time
);
784 samenick
= irccmp(source_p
->name
, nick
) ? 0 : 1;
786 /* dont reset TS if theyre just changing case of nick */
789 source_p
->tsinfo
= CurrentTime
;
790 monitor_signoff(source_p
);
791 /* we only do bancache for local users -- jilles */
793 invalidate_bancache_user(source_p
);
796 sendto_realops_snomask(SNO_NCHANGE
, L_ALL
,
797 "Nick change: From %s to %s [%s@%s]",
798 source_p
->name
, nick
, source_p
->username
, source_p
->host
);
800 /* send the nick change to the users channels */
801 sendto_common_channels_local(source_p
, ":%s!%s@%s NICK :%s",
802 source_p
->name
, source_p
->username
, source_p
->host
, nick
);
804 /* send the nick change to servers.. */
807 add_history(source_p
, 1);
811 sendto_server(client_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s NICK %s :%ld",
812 use_id(source_p
), nick
, (long) source_p
->tsinfo
);
813 sendto_server(client_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s NICK %s :%ld",
814 source_p
->name
, nick
, (long) source_p
->tsinfo
);
818 /* Finally, add to hash */
819 del_from_client_hash(source_p
->name
, source_p
);
820 strcpy(source_p
->name
, nick
);
821 add_to_client_hash(nick
, source_p
);
824 monitor_signon(source_p
);
826 /* Make sure everyone that has this client on its accept list
827 * loses that reference.
829 /* we used to call del_all_accepts() here, but theres no real reason
830 * to clear a clients own list of accepted clients. So just remove
831 * them from everyone elses list --anfl
833 DLINK_FOREACH_SAFE(ptr
, next_ptr
, source_p
->on_allow_list
.head
)
835 target_p
= ptr
->data
;
837 dlinkFindDestroy(source_p
, &target_p
->localClient
->allow_list
);
838 dlinkDestroy(ptr
, &source_p
->on_allow_list
);
841 /* fd_desc is long enough */
842 comm_note(client_p
->localClient
->fd
, "Nick: %s", nick
);
848 * change_remote_nick()
851 change_remote_nick(struct Client
*client_p
, struct Client
*source_p
,
852 time_t newts
, const char *nick
, int dosend
)
855 int samenick
= irccmp(source_p
->name
, nick
) ? 0 : 1;
857 /* client changing their nick - dont reset ts if its same */
860 source_p
->tsinfo
= newts
? newts
: CurrentTime
;
861 monitor_signoff(source_p
);
864 sendto_common_channels_local(source_p
, ":%s!%s@%s NICK :%s",
865 source_p
->name
, source_p
->username
, source_p
->host
, nick
);
869 add_history(source_p
, 1);
872 sendto_server(client_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s NICK %s :%ld",
873 use_id(source_p
), nick
, (long) source_p
->tsinfo
);
874 sendto_server(client_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s NICK %s :%ld",
875 source_p
->name
, nick
, (long) source_p
->tsinfo
);
879 del_from_client_hash(source_p
->name
, source_p
);
881 /* invalidate nick delay when a remote client uses the nick.. */
882 if((nd
= hash_find_nd(nick
)))
885 strcpy(source_p
->name
, nick
);
886 add_to_client_hash(nick
, source_p
);
889 monitor_signon(source_p
);
891 /* remove all accepts pointing to the client */
892 del_all_accepts(source_p
);
898 perform_nick_collides(struct Client
*source_p
, struct Client
*client_p
,
899 struct Client
*target_p
, int parc
, const char *parv
[],
900 time_t newts
, const char *nick
, const char *uid
)
906 use_save
= ConfigFileEntry
.collision_fnc
&& can_save(target_p
) &&
907 uid
!= NULL
&& can_save(source_p
);
908 action
= use_save
? "saved" : "killed";
910 /* if we dont have a ts, or their TS's are the same, kill both */
911 if(!newts
|| !target_p
->tsinfo
|| (newts
== target_p
->tsinfo
))
913 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
914 "Nick collision on %s(%s <- %s)(both %s)",
915 target_p
->name
, target_p
->from
->name
, client_p
->name
, action
);
919 save_user(&me
, &me
, target_p
);
920 ServerStats
->is_save
++;
921 sendto_one(client_p
, ":%s SAVE %s %ld", me
.id
,
923 register_client(client_p
, source_p
,
924 uid
, newts
, parc
, parv
);
928 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
929 form_str(ERR_NICKCOLLISION
), target_p
->name
);
931 /* if the new client being introduced has a UID, we need to
932 * issue a KILL for it..
935 sendto_one(client_p
, ":%s KILL %s :%s (Nick collision (new))",
936 me
.id
, uid
, me
.name
);
938 /* we then need to KILL the old client everywhere */
939 kill_client_serv_butone(NULL
, target_p
, "%s (Nick collision (new))", me
.name
);
940 ServerStats
->is_kill
++;
942 target_p
->flags
|= FLAGS_KILLED
;
943 exit_client(client_p
, target_p
, &me
, "Nick collision (new)");
947 /* the timestamps are different */
950 sameuser
= (target_p
->user
) && !irccmp(target_p
->username
, parv
[5])
951 && !irccmp(target_p
->host
, parv
[6]);
953 if((sameuser
&& newts
< target_p
->tsinfo
) ||
954 (!sameuser
&& newts
> target_p
->tsinfo
))
956 /* if we have a UID, then we need to issue a KILL,
957 * otherwise we do nothing and hope that the other
958 * client will collide it..
962 sendto_one(client_p
, ":%s SAVE %s %ld", me
.id
,
964 register_client(client_p
, source_p
,
965 uid
, newts
, parc
, parv
);
969 ":%s KILL %s :%s (Nick collision (new))",
970 me
.id
, uid
, me
.name
);
976 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
977 "Nick collision on %s(%s <- %s)(older %s)",
978 target_p
->name
, target_p
->from
->name
,
979 client_p
->name
, action
);
981 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
982 "Nick collision on %s(%s <- %s)(newer %s)",
983 target_p
->name
, target_p
->from
->name
,
984 client_p
->name
, action
);
988 ServerStats
->is_save
++;
989 save_user(&me
, &me
, target_p
);
993 ServerStats
->is_kill
++;
994 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
995 form_str(ERR_NICKCOLLISION
), target_p
->name
);
997 /* now we just need to kill the existing client */
998 kill_client_serv_butone(client_p
, target_p
,
999 "%s (Nick collision (new))", me
.name
);
1001 target_p
->flags
|= FLAGS_KILLED
;
1002 (void) exit_client(client_p
, target_p
, &me
, "Nick collision");
1005 register_client(client_p
, parc
>= 10 ? source_p
: NULL
,
1006 nick
, newts
, parc
, parv
);
1015 perform_nickchange_collides(struct Client
*source_p
, struct Client
*client_p
,
1016 struct Client
*target_p
, int parc
,
1017 const char *parv
[], time_t newts
, const char *nick
)
1023 use_save
= ConfigFileEntry
.collision_fnc
&& can_save(target_p
) &&
1025 action
= use_save
? "saved" : "killed";
1027 /* its a client changing nick and causing a collide */
1028 if(!newts
|| !target_p
->tsinfo
|| (newts
== target_p
->tsinfo
) || !source_p
->user
)
1030 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1031 "Nick change collision from %s to %s(%s <- %s)(both %s)",
1032 source_p
->name
, target_p
->name
, target_p
->from
->name
,
1033 client_p
->name
, action
);
1037 ServerStats
->is_save
+= 2;
1038 save_user(&me
, &me
, target_p
);
1039 sendto_one(client_p
, ":%s SAVE %s %ld", me
.id
,
1040 source_p
->id
, (long)newts
);
1041 /* don't send a redundant nick change */
1042 if (!IsDigit(source_p
->name
[0]))
1043 change_remote_nick(client_p
, source_p
, CurrentTime
, source_p
->id
, 1);
1047 ServerStats
->is_kill
++;
1048 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
1049 form_str(ERR_NICKCOLLISION
), target_p
->name
);
1051 kill_client_serv_butone(NULL
, source_p
, "%s (Nick change collision)", me
.name
);
1053 ServerStats
->is_kill
++;
1055 kill_client_serv_butone(NULL
, target_p
, "%s (Nick change collision)", me
.name
);
1057 target_p
->flags
|= FLAGS_KILLED
;
1058 exit_client(NULL
, target_p
, &me
, "Nick collision(new)");
1059 source_p
->flags
|= FLAGS_KILLED
;
1060 exit_client(client_p
, source_p
, &me
, "Nick collision(old)");
1066 sameuser
= !irccmp(target_p
->username
, source_p
->username
) &&
1067 !irccmp(target_p
->host
, source_p
->host
);
1069 if((sameuser
&& newts
< target_p
->tsinfo
) ||
1070 (!sameuser
&& newts
> target_p
->tsinfo
))
1073 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1074 "Nick change collision from %s to %s(%s <- %s)(older %s)",
1075 source_p
->name
, target_p
->name
,
1076 target_p
->from
->name
, client_p
->name
, action
);
1078 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1079 "Nick change collision from %s to %s(%s <- %s)(newer %s)",
1080 source_p
->name
, target_p
->name
,
1081 target_p
->from
->name
, client_p
->name
, action
);
1085 ServerStats
->is_save
++;
1086 /* can't broadcast a SAVE because the
1087 * nickchange has happened at client_p
1088 * but not in other directions -- jilles */
1089 sendto_one(client_p
, ":%s SAVE %s %ld", me
.id
,
1090 source_p
->id
, (long)newts
);
1091 /* same CurrentTime as in save_user() */
1092 /* send a :<id> NICK <id> <ts> (!) */
1093 if (!IsDigit(source_p
->name
[0]))
1094 change_remote_nick(client_p
, source_p
, CurrentTime
, source_p
->id
, 1);
1098 ServerStats
->is_kill
++;
1100 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
1101 form_str(ERR_NICKCOLLISION
), target_p
->name
);
1103 /* kill the client issuing the nickchange */
1104 kill_client_serv_butone(client_p
, source_p
,
1105 "%s (Nick change collision)", me
.name
);
1107 source_p
->flags
|= FLAGS_KILLED
;
1110 exit_client(client_p
, source_p
, &me
, "Nick collision(old)");
1112 exit_client(client_p
, source_p
, &me
, "Nick collision(new)");
1119 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1120 "Nick collision on %s(%s <- %s)(older %s)",
1121 target_p
->name
, target_p
->from
->name
,
1122 client_p
->name
, action
);
1124 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1125 "Nick collision on %s(%s <- %s)(newer %s)",
1126 target_p
->name
, target_p
->from
->name
,
1127 client_p
->name
, action
);
1131 ServerStats
->is_save
++;
1132 save_user(&me
, &me
, target_p
);
1136 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
1137 form_str(ERR_NICKCOLLISION
), target_p
->name
);
1139 /* kill the client who existed before hand */
1140 kill_client_serv_butone(client_p
, target_p
, "%s (Nick collision)", me
.name
);
1142 ServerStats
->is_kill
++;
1144 target_p
->flags
|= FLAGS_KILLED
;
1145 (void) exit_client(client_p
, target_p
, &me
, "Nick collision");
1150 change_remote_nick(client_p
, source_p
, newts
, nick
, 1);
1156 register_client(struct Client
*client_p
, struct Client
*server
,
1157 const char *nick
, time_t newts
, int parc
, const char *parv
[])
1159 struct Client
*source_p
;
1161 struct nd_entry
*nd
;
1165 source_p
= make_client(client_p
);
1166 user
= make_user(source_p
);
1167 dlinkAddTail(source_p
, &source_p
->node
, &global_client_list
);
1169 source_p
->hopcount
= atoi(parv
[2]);
1170 source_p
->tsinfo
= newts
;
1172 strcpy(source_p
->name
, nick
);
1173 strlcpy(source_p
->username
, parv
[5], sizeof(source_p
->username
));
1174 strlcpy(source_p
->host
, parv
[6], sizeof(source_p
->host
));
1175 strlcpy(source_p
->orighost
, source_p
->host
, sizeof(source_p
->orighost
));
1179 user
->server
= find_or_add(server
->name
);
1180 strlcpy(source_p
->info
, parv
[11], sizeof(source_p
->info
));
1181 strlcpy(source_p
->sockhost
, parv
[7], sizeof(source_p
->sockhost
));
1182 strlcpy(source_p
->id
, parv
[8], sizeof(source_p
->id
));
1183 add_to_id_hash(source_p
->id
, source_p
);
1184 if (strcmp(parv
[9], "*"))
1186 strlcpy(source_p
->orighost
, parv
[9], sizeof(source_p
->orighost
));
1187 if (irccmp(source_p
->host
, source_p
->orighost
))
1188 SetDynSpoof(source_p
);
1190 if (strcmp(parv
[10], "*"))
1191 strlcpy(source_p
->user
->suser
, parv
[10], sizeof(source_p
->user
->suser
));
1195 user
->server
= find_or_add(server
->name
);
1196 strlcpy(source_p
->info
, parv
[9], sizeof(source_p
->info
));
1197 strlcpy(source_p
->sockhost
, parv
[7], sizeof(source_p
->sockhost
));
1198 strlcpy(source_p
->id
, parv
[8], sizeof(source_p
->id
));
1199 add_to_id_hash(source_p
->id
, source_p
);
1203 user
->server
= find_or_add(parv
[7]);
1204 strlcpy(source_p
->info
, parv
[8], sizeof(source_p
->info
));
1207 /* remove any nd entries for this nick */
1208 if((nd
= hash_find_nd(nick
)))
1211 add_to_client_hash(nick
, source_p
);
1212 add_to_hostname_hash(source_p
->host
, source_p
);
1213 monitor_signon(source_p
);
1218 flag
= user_modes
[(unsigned char) *m
];
1220 if(flag
& UMODE_SERVICE
)
1225 DLINK_FOREACH(ptr
, service_list
.head
)
1227 if(!irccmp((const char *) ptr
->data
, user
->server
))
1241 /* increment +i count if theyre invis */
1242 if(!(source_p
->umodes
& UMODE_INVISIBLE
) && (flag
& UMODE_INVISIBLE
))
1245 /* increment opered count if theyre opered */
1246 if(!(source_p
->umodes
& UMODE_OPER
) && (flag
& UMODE_OPER
))
1249 source_p
->umodes
|= flag
;
1253 if(IsOper(source_p
) && !IsService(source_p
))
1254 dlinkAddAlloc(source_p
, &oper_list
);
1256 SetRemoteClient(source_p
);
1258 if(++Count
.total
> Count
.max_tot
)
1259 Count
.max_tot
= Count
.total
;
1263 if((source_p
->servptr
= find_server(NULL
, user
->server
)) == NULL
)
1265 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1266 "Ghost killed: %s on invalid server %s",
1267 source_p
->name
, user
->server
);
1268 kill_client(client_p
, source_p
, "%s (Server doesn't exist)", me
.name
);
1269 source_p
->flags
|= FLAGS_KILLED
;
1270 return exit_client(NULL
, source_p
, &me
, "Ghosted Client");
1274 source_p
->servptr
= server
;
1276 dlinkAdd(source_p
, &source_p
->lnode
, &source_p
->servptr
->serv
->users
);
1278 /* fake direction */
1279 if(source_p
->servptr
->from
!= source_p
->from
)
1281 struct Client
*target_p
= source_p
->servptr
->from
;
1283 sendto_realops_snomask(SNO_DEBUG
, L_ALL
,
1284 "Bad User [%s] :%s USER %s@%s %s, != %s[%s]",
1285 client_p
->name
, source_p
->name
,
1286 source_p
->username
, source_p
->host
,
1287 user
->server
, target_p
->name
, target_p
->from
->name
);
1288 kill_client(client_p
, source_p
,
1289 "%s (NICK from wrong direction (%s != %s))",
1290 me
.name
, user
->server
, target_p
->from
->name
);
1291 source_p
->flags
|= FLAGS_KILLED
;
1292 return exit_client(source_p
, source_p
, &me
, "USER server wrong direction");
1295 call_hook(h_new_remote_user
, source_p
);
1297 return (introduce_client(client_p
, source_p
, user
, nick
, parc
== 12));
1300 /* Check if we can do SAVE. target_p can be a client to save or a
1301 * server introducing a client -- jilles */
1303 can_save(struct Client
*target_p
)
1305 struct Client
*serv_p
;
1307 if (MyClient(target_p
))
1309 if (!has_id(target_p
))
1311 serv_p
= IsServer(target_p
) ? target_p
: target_p
->servptr
;
1312 while (serv_p
!= NULL
&& serv_p
!= &me
)
1314 if (!(serv_p
->serv
->caps
& CAP_SAVE
))
1316 serv_p
= serv_p
->servptr
;
1318 return serv_p
== &me
;
1322 save_user(struct Client
*client_p
, struct Client
*source_p
,
1323 struct Client
*target_p
)
1325 if (!MyConnect(target_p
) && (!has_id(target_p
) || !IsCapable(target_p
->from
, CAP_SAVE
)))
1327 /* This shouldn't happen */
1328 /* Note we only need SAVE support in this direction */
1329 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1330 "Killed %s!%s@%s for nick collision detected by %s (%s does not support SAVE)",
1331 target_p
->name
, target_p
->username
, target_p
->host
, source_p
->name
, target_p
->from
->name
);
1332 kill_client_serv_butone(NULL
, target_p
, "%s (Nick collision (no SAVE support))", me
.name
);
1333 ServerStats
->is_kill
++;
1335 target_p
->flags
|= FLAGS_KILLED
;
1336 (void) exit_client(NULL
, target_p
, &me
, "Nick collision (no SAVE support)");
1339 sendto_server(client_p
, NULL
, CAP_SAVE
|CAP_TS6
, NOCAPS
, ":%s SAVE %s %ld",
1340 source_p
->id
, target_p
->id
, (long)target_p
->tsinfo
);
1341 sendto_server(client_p
, NULL
, CAP_TS6
, CAP_SAVE
, ":%s NICK %s :%ld",
1342 target_p
->id
, target_p
->id
, (long)CurrentTime
);
1343 sendto_server(client_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s NICK %s :%ld",
1344 target_p
->name
, target_p
->id
, (long)CurrentTime
);
1345 if (!IsMe(client_p
))
1346 sendto_realops_snomask(SNO_SKILL
, L_ALL
,
1347 "Received SAVE message for %s from %s",
1348 target_p
->name
, source_p
->name
);
1349 if (MyClient(target_p
))
1351 sendto_one_numeric(target_p
, RPL_SAVENICK
,
1352 form_str(RPL_SAVENICK
), target_p
->id
);
1353 change_local_nick(target_p
, target_p
, target_p
->id
, 0);
1357 /* XXX the uid nick gets garbage TS; shouldn't matter though */
1358 change_remote_nick(target_p
, target_p
, CurrentTime
, target_p
->id
, 0);