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 23853 2007-04-22 14:09:34Z jilles $
30 #include "irc_string.h"
48 #include "s_newconf.h"
51 /* Give all UID nicks the same TS. This ensures nick TS is always the same on
52 * all servers for each nick-user pair, also if a user with a UID nick changes
53 * their nick but is collided again (the server detecting the collision will
54 * not propagate the nick change further). -- jilles
56 #define SAVE_NICKTS 100
58 static int mr_nick(struct Client
*, struct Client
*, int, const char **);
59 static int m_nick(struct Client
*, struct Client
*, int, const char **);
60 static int mc_nick(struct Client
*, struct Client
*, int, const char **);
61 static int ms_nick(struct Client
*, struct Client
*, int, const char **);
62 static int ms_uid(struct Client
*, struct Client
*, int, const char **);
63 static int ms_save(struct Client
*, struct Client
*, int, const char **);
64 static void save_user(struct Client
*, struct Client
*, struct Client
*);
66 struct Message nick_msgtab
= {
67 "NICK", 0, 0, 0, MFLG_SLOW
,
68 {{mr_nick
, 0}, {m_nick
, 0}, {mc_nick
, 3}, {ms_nick
, 8}, mg_ignore
, {m_nick
, 0}}
70 struct Message uid_msgtab
= {
71 "UID", 0, 0, 0, MFLG_SLOW
,
72 {mg_ignore
, mg_ignore
, mg_ignore
, {ms_uid
, 9}, mg_ignore
, mg_ignore
}
74 struct Message save_msgtab
= {
75 "SAVE", 0, 0, 0, MFLG_SLOW
,
76 {mg_ignore
, mg_ignore
, mg_ignore
, {ms_save
, 3}, mg_ignore
, mg_ignore
}
79 mapi_clist_av1 nick_clist
[] = { &nick_msgtab
, &uid_msgtab
, &save_msgtab
, NULL
};
80 DECLARE_MODULE_AV1(nick
, NULL
, NULL
, nick_clist
, NULL
, NULL
, "$Revision: 23853 $");
82 static int change_remote_nick(struct Client
*, struct Client
*, time_t, const char *, int);
84 static int clean_nick(const char *, int loc_client
);
85 static int clean_username(const char *);
86 static int clean_host(const char *);
87 static int clean_uid(const char *uid
);
89 static void set_initial_nick(struct Client
*client_p
, struct Client
*source_p
, char *nick
);
90 static void change_local_nick(struct Client
*client_p
, struct Client
*source_p
, char *nick
, int);
91 static int register_client(struct Client
*client_p
, struct Client
*server
,
92 const char *nick
, time_t newts
, int parc
, const char *parv
[]);
94 static int perform_nick_collides(struct Client
*, struct Client
*,
95 struct Client
*, int, const char **,
96 time_t, const char *, const char *);
97 static int perform_nickchange_collides(struct Client
*, struct Client
*,
98 struct Client
*, int, const char **,
99 time_t, const char *);
102 * parv[0] = sender prefix
106 mr_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
108 struct Client
*target_p
;
112 if(parc
< 2 || EmptyString(parv
[1]) || (parv
[1][0] == '~'))
114 sendto_one(source_p
, form_str(ERR_NONICKNAMEGIVEN
),
116 EmptyString(source_p
->name
) ? "*" : source_p
->name
);
120 /* due to the scandinavian origins, (~ being uppercase of ^) and ~
121 * being disallowed as a nick char, we need to chop the first ~
122 * instead of just erroring.
124 if((s
= strchr(parv
[1], '~')))
127 /* copy the nick and terminate it */
128 strlcpy(nick
, parv
[1], sizeof(nick
));
130 /* check the nickname is ok */
131 if(!clean_nick(nick
, 1))
133 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
),
134 me
.name
, EmptyString(parv
[0]) ? "*" : parv
[0], parv
[1]);
138 /* check if the nick is resv'd */
139 if(find_nick_resv(nick
))
141 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
),
142 me
.name
, EmptyString(source_p
->name
) ? "*" : source_p
->name
, nick
);
146 if(hash_find_nd(nick
))
148 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
150 EmptyString(source_p
->name
) ? "*" : source_p
->name
,
155 if((target_p
= find_client(nick
)) == NULL
)
156 set_initial_nick(client_p
, source_p
, nick
);
157 else if(source_p
== target_p
)
158 strcpy(source_p
->user
->nick
, nick
);
160 sendto_one(source_p
, form_str(ERR_NICKNAMEINUSE
), me
.name
, "*", nick
);
166 * parv[0] = sender prefix
170 m_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
172 struct Client
*target_p
;
176 if(parc
< 2 || EmptyString(parv
[1]) || (parv
[1][0] == '~'))
178 sendto_one(source_p
, form_str(ERR_NONICKNAMEGIVEN
),
179 me
.name
, source_p
->name
);
183 /* due to the scandinavian origins, (~ being uppercase of ^) and ~
184 * being disallowed as a nick char, we need to chop the first ~
185 * instead of just erroring.
187 if((s
= strchr(parv
[1], '~')))
190 /* mark end of grace period, to prevent nickflooding */
191 if(!IsFloodDone(source_p
))
192 flood_endgrace(source_p
);
194 /* terminate nick to NICKLEN, we dont want clean_nick() to error! */
195 strlcpy(nick
, parv
[1], sizeof(nick
));
197 /* check the nickname is ok */
198 if(!clean_nick(nick
, 1))
200 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
),
201 me
.name
, parv
[0], nick
);
205 if(!IsExemptResv(source_p
) && find_nick_resv(nick
))
207 sendto_one(source_p
, form_str(ERR_ERRONEUSNICKNAME
),
208 me
.name
, source_p
->name
, nick
);
212 if(hash_find_nd(nick
))
214 sendto_one(source_p
, form_str(ERR_UNAVAILRESOURCE
),
216 EmptyString(source_p
->name
) ? "*" : source_p
->name
,
221 if((target_p
= find_client(nick
)))
223 /* If(target_p == source_p) the client is changing nicks between
224 * equivalent nicknames ie: [nick] -> {nick}
226 if(target_p
== source_p
)
228 /* check the nick isnt exactly the same */
229 if(strcmp(target_p
->name
, nick
))
230 change_local_nick(client_p
, source_p
, nick
, 1);
234 /* drop unregged client */
235 else if(IsUnknown(target_p
))
237 exit_client(NULL
, target_p
, &me
, "Overridden");
238 change_local_nick(client_p
, source_p
, nick
, 1);
241 sendto_one(source_p
, form_str(ERR_NICKNAMEINUSE
), me
.name
, parv
[0], nick
);
246 change_local_nick(client_p
, source_p
, nick
, 1);
253 * server -> server nick change
254 * parv[0] = sender prefix
256 * parv[2] = TS when nick change
258 * server introducing new nick
259 * parv[0] = sender prefix
261 * parv[2] = hop count
270 mc_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
272 struct Client
*target_p
;
275 /* if nicks erroneous, or too long, kill */
276 if(!clean_nick(parv
[1], 0))
278 ServerStats
->is_kill
++;
279 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
280 "Bad Nick: %s From: %s(via %s)",
281 parv
[1], source_p
->servptr
->name
,
283 sendto_one(client_p
, ":%s KILL %s :%s (Bad Nickname)",
284 me
.name
, parv
[1], me
.name
);
286 /* bad nick change, issue kill for the old nick to the rest
289 kill_client_serv_butone(client_p
, source_p
,
290 "%s (Bad Nickname)", me
.name
);
291 source_p
->flags
|= FLAGS_KILLED
;
292 exit_client(client_p
, source_p
, &me
, "Bad Nickname");
296 newts
= atol(parv
[2]);
297 target_p
= find_client(parv
[1]);
299 /* if the nick doesnt exist, allow it and process like normal */
302 change_remote_nick(client_p
, source_p
, newts
, parv
[1], 1);
304 else if(IsUnknown(target_p
))
306 exit_client(NULL
, target_p
, &me
, "Overridden");
307 change_remote_nick(client_p
, source_p
, newts
, parv
[1], 1);
309 else if(target_p
== source_p
)
311 /* client changing case of nick */
312 if(strcmp(target_p
->name
, parv
[1]))
313 change_remote_nick(client_p
, source_p
, newts
, parv
[1], 1);
315 /* we've got a collision! */
317 perform_nickchange_collides(source_p
, client_p
, target_p
,
318 parc
, parv
, newts
, parv
[1]);
324 ms_nick(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
326 struct Client
*target_p
;
331 sendto_realops_flags(UMODE_ALL
, L_ALL
,
332 "Dropping server %s due to (invalid) command 'NICK' "
333 "with %d arguments (expecting 9)",
334 client_p
->name
, parc
);
335 ilog(L_SERVER
, "Excess parameters (%d) for command 'NICK' from %s.",
336 parc
, client_p
->name
);
337 exit_client(client_p
, client_p
, client_p
,
338 "Excess parameters to NICK command");
342 /* if nicks empty, erroneous, or too long, kill */
343 if(!clean_nick(parv
[1], 0))
345 ServerStats
->is_kill
++;
346 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
347 "Bad Nick: %s From: %s(via %s)",
348 parv
[1], parv
[7], client_p
->name
);
349 sendto_one(client_p
, ":%s KILL %s :%s (Bad Nickname)",
350 me
.name
, parv
[1], me
.name
);
354 /* invalid username or host? */
355 if(!clean_username(parv
[5]) || !clean_host(parv
[6]))
357 ServerStats
->is_kill
++;
358 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
359 "Bad user@host: %s@%s From: %s(via %s)",
360 parv
[5], parv
[6], parv
[7],
362 sendto_one(client_p
, ":%s KILL %s :%s (Bad user@host)",
363 me
.name
, parv
[1], me
.name
);
367 /* check the length of the clients gecos */
368 if(strlen(parv
[8]) > REALLEN
)
370 char *s
= LOCAL_COPY(parv
[8]);
371 /* why exactly do we care? --fl */
372 sendto_realops_flags(UMODE_ALL
, L_ALL
,
373 "Long realname from server %s for %s", parv
[7],
380 newts
= atol(parv
[3]);
382 target_p
= find_client(parv
[1]);
384 /* if the nick doesnt exist, allow it and process like normal */
387 register_client(client_p
, NULL
, parv
[1], newts
, parc
, parv
);
389 else if(IsUnknown(target_p
))
391 exit_client(NULL
, target_p
, &me
, "Overridden");
392 register_client(client_p
, NULL
, parv
[1], newts
, parc
, parv
);
394 else if(target_p
== source_p
)
396 /* client changing case of nick */
397 if(strcmp(target_p
->name
, parv
[1]))
398 register_client(client_p
, NULL
, parv
[1], newts
, parc
, parv
);
400 /* we've got a collision! */
402 perform_nick_collides(source_p
, client_p
, target_p
, parc
, parv
,
403 newts
, parv
[1], NULL
);
420 ms_uid(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
422 struct Client
*target_p
;
425 newts
= atol(parv
[3]);
429 sendto_realops_flags(UMODE_ALL
, L_ALL
,
430 "Dropping server %s due to (invalid) command 'UID' "
431 "with %d arguments (expecting 10)",
432 client_p
->name
, parc
);
433 ilog(L_SERVER
, "Excess parameters (%d) for command 'UID' from %s.",
434 parc
, client_p
->name
);
435 exit_client(client_p
, client_p
, client_p
,
436 "Excess parameters to UID command");
440 /* if nicks erroneous, or too long, kill */
441 if(!clean_nick(parv
[1], 0))
443 ServerStats
->is_kill
++;
444 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
445 "Bad Nick: %s From: %s(via %s)",
446 parv
[1], source_p
->name
,
448 sendto_one(client_p
, ":%s KILL %s :%s (Bad Nickname)",
449 me
.id
, parv
[8], me
.name
);
453 if(!clean_username(parv
[5]) || !clean_host(parv
[6]))
455 ServerStats
->is_kill
++;
456 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
457 "Bad user@host: %s@%s From: %s(via %s)",
458 parv
[5], parv
[6], source_p
->name
,
460 sendto_one(client_p
, ":%s KILL %s :%s (Bad user@host)",
461 me
.id
, parv
[8], me
.name
);
465 if(!clean_uid(parv
[8]))
467 ServerStats
->is_kill
++;
468 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
469 "Bad UID: %s From: %s(via %s)",
470 parv
[8], source_p
->name
,
472 sendto_one(client_p
, ":%s KILL %s :%s (Bad UID)",
473 me
.id
, parv
[8], me
.name
);
477 /* check length of clients gecos */
478 if(strlen(parv
[9]) > REALLEN
)
480 char *s
= LOCAL_COPY(parv
[9]);
481 sendto_realops_flags(UMODE_ALL
, L_ALL
, "Long realname from server %s for %s",
487 target_p
= find_client(parv
[1]);
491 register_client(client_p
, source_p
, parv
[1], newts
, parc
, parv
);
493 else if(IsUnknown(target_p
))
495 exit_client(NULL
, target_p
, &me
, "Overridden");
496 register_client(client_p
, source_p
, parv
[1], newts
, parc
, parv
);
498 /* we've got a collision! */
500 perform_nick_collides(source_p
, client_p
, target_p
, parc
, parv
,
501 newts
, parv
[1], parv
[8]);
511 ms_save(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
513 struct Client
*target_p
;
515 target_p
= find_id(parv
[1]);
516 if (target_p
== NULL
)
518 if (!IsPerson(target_p
))
519 sendto_realops_flags(UMODE_ALL
, L_ALL
,
520 "Ignored SAVE message for non-person %s from %s",
521 target_p
->name
, source_p
->name
);
522 else if (IsDigit(target_p
->name
[0]))
523 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
524 "Ignored noop SAVE message for %s from %s",
525 target_p
->name
, source_p
->name
);
526 else if (target_p
->tsinfo
== atol(parv
[2]))
527 save_user(client_p
, source_p
, target_p
);
529 sendto_realops_flags(UMODE_SKILL
, L_ALL
,
530 "Ignored SAVE message for %s from %s",
531 target_p
->name
, source_p
->name
);
537 * input - nickname to check
538 * output - 0 if erroneous, else 1
542 clean_nick(const char *nick
, int loc_client
)
546 /* nicks cant start with a digit or -, and must have a length */
547 if(*nick
== '-' || *nick
== '\0')
550 if(loc_client
&& IsDigit(*nick
))
553 for (; *nick
; nick
++)
556 if(!IsNickChar(*nick
))
569 * input - username to check
570 * output - 0 if erroneous, else 0
574 clean_username(const char *username
)
578 for (; *username
; username
++)
582 if(!IsUserChar(*username
))
594 * input - host to check
595 * output - 0 if erroneous, else 0
599 clean_host(const char *host
)
603 for (; *host
; host
++)
607 if(!IsHostChar(*host
))
618 clean_uid(const char *uid
)
640 set_initial_nick(struct Client
*client_p
, struct Client
*source_p
, char *nick
)
642 char buf
[USERLEN
+ 1];
644 /* This had to be copied here to avoid problems.. */
645 source_p
->tsinfo
= CurrentTime
;
646 if(!EmptyString(source_p
->name
))
647 del_from_client_hash(source_p
->name
, source_p
);
651 source_p
->name
= source_p
->user
->nick
;
654 strcpy(source_p
->user
->nick
, nick
);
655 add_to_client_hash(nick
, source_p
);
657 /* fd_desc is long enough */
658 comm_note(client_p
->localClient
->fd
, "Nick: %s", nick
);
660 if(HasSentUser(source_p
))
662 strlcpy(buf
, source_p
->username
, sizeof(buf
));
664 /* got user, heres nick. */
665 register_local_user(client_p
, source_p
, buf
);
671 change_local_nick(struct Client
*client_p
, struct Client
*source_p
, char *nick
,
674 struct Client
*target_p
;
675 dlink_node
*ptr
, *next_ptr
;
680 if((source_p
->localClient
->last_nick_change
+ ConfigFileEntry
.max_nick_time
) < CurrentTime
)
681 source_p
->localClient
->number_of_nick_changes
= 0;
683 if(ConfigFileEntry
.anti_nick_flood
&& !IsOper(source_p
) &&
684 source_p
->localClient
->number_of_nick_changes
> ConfigFileEntry
.max_nick_changes
)
686 sendto_one(source_p
, form_str(ERR_NICKTOOFAST
),
687 me
.name
, source_p
->name
, source_p
->name
,
688 nick
, ConfigFileEntry
.max_nick_time
);
692 source_p
->localClient
->last_nick_change
= CurrentTime
;
693 source_p
->localClient
->number_of_nick_changes
++;
696 samenick
= irccmp(source_p
->name
, nick
) ? 0 : 1;
698 /* dont reset TS if theyre just changing case of nick */
701 /* force the TS to increase -- jilles */
702 if (source_p
->tsinfo
>= CurrentTime
)
705 source_p
->tsinfo
= CurrentTime
;
706 monitor_signoff(source_p
);
707 /* we only do bancache for local users -- jilles */
709 invalidate_bancache_user(source_p
);
712 sendto_realops_flags(UMODE_NCHANGE
, L_ALL
,
713 "Nick change: From %s to %s [%s@%s]",
714 source_p
->name
, nick
, source_p
->username
, source_p
->host
);
716 /* send the nick change to the users channels */
717 sendto_common_channels_local(source_p
, ":%s!%s@%s NICK :%s",
718 source_p
->name
, source_p
->username
,
719 source_p
->host
, nick
);
721 /* send the nick change to servers.. */
722 if(IsPerson(source_p
))
724 add_history(source_p
, 1);
728 sendto_server(client_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s NICK %s :%ld",
729 use_id(source_p
), nick
, (long) source_p
->tsinfo
);
730 sendto_server(client_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s NICK %s :%ld",
731 source_p
->name
, nick
, (long) source_p
->tsinfo
);
735 /* Finally, add to hash */
736 del_from_client_hash(source_p
->name
, source_p
);
737 strcpy(source_p
->user
->nick
, nick
);
738 add_to_client_hash(nick
, source_p
);
741 monitor_signon(source_p
);
743 /* Make sure everyone that has this client on its accept list
744 * loses that reference.
746 /* we used to call del_all_accepts() here, but theres no real reason
747 * to clear a clients own list of accepted clients. So just remove
748 * them from everyone elses list --anfl
750 DLINK_FOREACH_SAFE(ptr
, next_ptr
, source_p
->on_allow_list
.head
)
752 target_p
= ptr
->data
;
754 dlinkFindDestroy(source_p
, &target_p
->localClient
->allow_list
);
755 dlinkDestroy(ptr
, &source_p
->on_allow_list
);
758 /* fd_desc is long enough */
759 comm_note(client_p
->localClient
->fd
, "Nick: %s", nick
);
765 * change_remote_nick()
768 change_remote_nick(struct Client
*client_p
, struct Client
*source_p
,
769 time_t newts
, const char *nick
, int dosend
)
772 int samenick
= irccmp(source_p
->name
, nick
) ? 0 : 1;
774 /* client changing their nick - dont reset ts if its same */
777 source_p
->tsinfo
= newts
? newts
: CurrentTime
;
778 monitor_signoff(source_p
);
781 sendto_common_channels_local(source_p
, ":%s!%s@%s NICK :%s",
782 source_p
->name
, source_p
->username
,
783 source_p
->host
, nick
);
787 add_history(source_p
, 1);
790 sendto_server(client_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s NICK %s :%ld",
791 use_id(source_p
), nick
, (long) source_p
->tsinfo
);
792 sendto_server(client_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s NICK %s :%ld",
793 source_p
->name
, nick
, (long) source_p
->tsinfo
);
797 del_from_client_hash(source_p
->name
, source_p
);
799 /* invalidate nick delay when a remote client uses the nick.. */
800 if((nd
= hash_find_nd(nick
)))
803 strcpy(source_p
->user
->nick
, nick
);
804 add_to_client_hash(nick
, source_p
);
807 monitor_signon(source_p
);
809 /* remove all accepts pointing to the client */
810 del_all_accepts(source_p
);
816 perform_nick_collides(struct Client
*source_p
, struct Client
*client_p
,
817 struct Client
*target_p
, int parc
, const char *parv
[],
818 time_t newts
, const char *nick
, const char *uid
)
822 /* if we dont have a ts, or their TS's are the same, kill both */
823 if(!newts
|| !target_p
->tsinfo
|| (newts
== target_p
->tsinfo
))
825 sendto_realops_flags(UMODE_ALL
, L_ALL
,
826 "Nick collision on %s(%s <- %s)(both killed)",
827 target_p
->name
, target_p
->from
->name
, client_p
->name
);
829 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
830 form_str(ERR_NICKCOLLISION
), target_p
->name
);
832 /* if the new client being introduced has a UID, we need to
833 * issue a KILL for it..
836 sendto_one(client_p
, ":%s KILL %s :%s (Nick collision (new))",
837 me
.id
, uid
, me
.name
);
839 /* we then need to KILL the old client everywhere */
840 kill_client_serv_butone(NULL
, target_p
,
841 "%s (Nick collision (new))", me
.name
);
842 ServerStats
->is_kill
++;
844 target_p
->flags
|= FLAGS_KILLED
;
845 exit_client(client_p
, target_p
, &me
, "Nick collision (new)");
848 /* the timestamps are different */
851 sameuser
= (target_p
->user
) && !irccmp(target_p
->username
, parv
[5])
852 && !irccmp(target_p
->host
, parv
[6]);
854 if((sameuser
&& newts
< target_p
->tsinfo
) ||
855 (!sameuser
&& newts
> target_p
->tsinfo
))
857 /* if we have a UID, then we need to issue a KILL,
858 * otherwise we do nothing and hope that the other
859 * client will collide it..
863 ":%s KILL %s :%s (Nick collision (new))",
864 me
.id
, uid
, me
.name
);
870 sendto_realops_flags(UMODE_ALL
, L_ALL
,
871 "Nick collision on %s(%s <- %s)(older killed)",
872 target_p
->name
, target_p
->from
->name
,
875 sendto_realops_flags(UMODE_ALL
, L_ALL
,
876 "Nick collision on %s(%s <- %s)(newer killed)",
877 target_p
->name
, target_p
->from
->name
,
880 ServerStats
->is_kill
++;
881 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
882 form_str(ERR_NICKCOLLISION
), target_p
->name
);
884 /* now we just need to kill the existing client */
885 kill_client_serv_butone(client_p
, target_p
,
886 "%s (Nick collision (new))", me
.name
);
888 target_p
->flags
|= FLAGS_KILLED
;
889 (void) exit_client(client_p
, target_p
, &me
, "Nick collision");
891 register_client(client_p
, parc
== 10 ? source_p
: NULL
,
892 nick
, newts
, parc
, parv
);
901 perform_nickchange_collides(struct Client
*source_p
, struct Client
*client_p
,
902 struct Client
*target_p
, int parc
,
903 const char *parv
[], time_t newts
, const char *nick
)
907 /* its a client changing nick and causing a collide */
908 if(!newts
|| !target_p
->tsinfo
|| (newts
== target_p
->tsinfo
) || !source_p
->user
)
910 sendto_realops_flags(UMODE_ALL
, L_ALL
,
911 "Nick change collision from %s to %s(%s <- %s)(both killed)",
912 source_p
->name
, target_p
->name
, target_p
->from
->name
,
915 ServerStats
->is_kill
++;
916 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
917 form_str(ERR_NICKCOLLISION
), target_p
->name
);
919 kill_client_serv_butone(NULL
, source_p
, "%s (Nick change collision)", me
.name
);
921 ServerStats
->is_kill
++;
923 kill_client_serv_butone(NULL
, target_p
, "%s (Nick change collision)", me
.name
);
925 target_p
->flags
|= FLAGS_KILLED
;
926 exit_client(NULL
, target_p
, &me
, "Nick collision(new)");
927 source_p
->flags
|= FLAGS_KILLED
;
928 exit_client(client_p
, source_p
, &me
, "Nick collision(old)");
933 sameuser
= !irccmp(target_p
->username
, source_p
->username
) &&
934 !irccmp(target_p
->host
, source_p
->host
);
936 if((sameuser
&& newts
< target_p
->tsinfo
) ||
937 (!sameuser
&& newts
> target_p
->tsinfo
))
940 sendto_realops_flags(UMODE_ALL
, L_ALL
,
941 "Nick change collision from %s to %s(%s <- %s)(older killed)",
942 source_p
->name
, target_p
->name
,
943 target_p
->from
->name
, client_p
->name
);
945 sendto_realops_flags(UMODE_ALL
, L_ALL
,
946 "Nick change collision from %s to %s(%s <- %s)(newer killed)",
947 source_p
->name
, target_p
->name
,
948 target_p
->from
->name
, client_p
->name
);
950 ServerStats
->is_kill
++;
952 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
953 form_str(ERR_NICKCOLLISION
), target_p
->name
);
955 /* kill the client issuing the nickchange */
956 kill_client_serv_butone(client_p
, source_p
,
957 "%s (Nick change collision)", me
.name
);
959 source_p
->flags
|= FLAGS_KILLED
;
962 exit_client(client_p
, source_p
, &me
, "Nick collision(old)");
964 exit_client(client_p
, source_p
, &me
, "Nick collision(new)");
970 sendto_realops_flags(UMODE_ALL
, L_ALL
,
971 "Nick collision on %s(%s <- %s)(older killed)",
972 target_p
->name
, target_p
->from
->name
,
975 sendto_realops_flags(UMODE_ALL
, L_ALL
,
976 "Nick collision on %s(%s <- %s)(newer killed)",
977 target_p
->name
, target_p
->from
->name
,
980 sendto_one_numeric(target_p
, ERR_NICKCOLLISION
,
981 form_str(ERR_NICKCOLLISION
), target_p
->name
);
983 /* kill the client who existed before hand */
984 kill_client_serv_butone(client_p
, target_p
,
985 "%s (Nick collision)", me
.name
);
987 ServerStats
->is_kill
++;
989 target_p
->flags
|= FLAGS_KILLED
;
990 (void) exit_client(client_p
, target_p
, &me
, "Nick collision");
994 change_remote_nick(client_p
, source_p
, newts
, nick
, 1);
1000 register_client(struct Client
*client_p
, struct Client
*server
,
1001 const char *nick
, time_t newts
, int parc
, const char *parv
[])
1003 struct Client
*source_p
;
1005 struct nd_entry
*nd
;
1009 source_p
= make_client(client_p
);
1010 user
= make_user(source_p
);
1012 source_p
->hopcount
= atoi(parv
[2]);
1013 source_p
->tsinfo
= newts
;
1015 source_p
->name
= source_p
->user
->nick
;
1016 strcpy(source_p
->user
->nick
, nick
);
1017 strlcpy(source_p
->username
, parv
[5], sizeof(source_p
->username
));
1018 strlcpy(source_p
->host
, parv
[6], sizeof(source_p
->host
));
1020 /* nothing must be done before this point that cant be cleaned up
1021 * just by doing a free_client(). --fl
1025 strlcpy(source_p
->info
, parv
[9], sizeof(source_p
->info
));
1026 strlcpy(source_p
->sockhost
, parv
[7], sizeof(source_p
->sockhost
));
1027 strlcpy(source_p
->id
, parv
[8], sizeof(source_p
->id
));
1028 add_to_id_hash(source_p
->id
, source_p
);
1032 strlcpy(source_p
->info
, parv
[8], sizeof(source_p
->info
));
1034 if((server
= find_server(NULL
, parv
[7])) == NULL
)
1036 sendto_realops_flags(UMODE_ALL
, L_ALL
,
1037 "Ghost killed: %s on invalid server %s",
1038 source_p
->name
, parv
[7]);
1039 kill_client(client_p
, source_p
, "%s (Server doesn't exist)", me
.name
);
1040 free_user(source_p
->user
, source_p
);
1041 free_client(source_p
);
1047 dlinkAddTail(source_p
, &source_p
->node
, &global_client_list
);
1049 /* server is guaranteed to exist at this point */
1050 source_p
->servptr
= server
;
1051 dlinkAdd(source_p
, &source_p
->lnode
, &source_p
->servptr
->serv
->users
);
1053 /* remove any nd entries for this nick */
1054 if((nd
= hash_find_nd(nick
)))
1057 add_to_client_hash(nick
, source_p
);
1058 add_to_hostname_hash(source_p
->host
, source_p
);
1059 monitor_signon(source_p
);
1064 flag
= user_modes_from_c_to_bitmask
[(unsigned char) *m
];
1066 #ifdef ENABLE_SERVICES
1067 if(flag
& UMODE_SERVICE
)
1072 DLINK_FOREACH(ptr
, service_list
.head
)
1074 if(!irccmp((const char *) ptr
->data
, source_p
->servptr
->name
))
1089 /* increment +i count if theyre invis */
1090 if(!(source_p
->umodes
& UMODE_INVISIBLE
) &&
1091 (flag
& UMODE_INVISIBLE
))
1094 /* increment opered count if theyre opered */
1095 if(!(source_p
->umodes
& UMODE_OPER
) && (flag
& UMODE_OPER
))
1098 source_p
->umodes
|= (flag
& SEND_UMODES
);
1102 SetRemoteClient(source_p
);
1104 if(++Count
.total
> Count
.max_tot
)
1105 Count
.max_tot
= Count
.total
;
1107 /* fake direction */
1108 if(source_p
->servptr
->from
!= source_p
->from
)
1110 struct Client
*target_p
= source_p
->servptr
->from
;
1112 sendto_realops_flags(UMODE_DEBUG
, L_ALL
,
1113 "Bad User [%s] :%s USER %s@%s %s, != %s[%s]",
1114 client_p
->name
, source_p
->name
,
1115 source_p
->username
, source_p
->host
,
1116 source_p
->servptr
->name
, target_p
->name
,
1117 target_p
->from
->name
);
1118 kill_client(client_p
, source_p
,
1119 "%s (NICK from wrong direction (%s != %s))",
1120 me
.name
, source_p
->servptr
->name
, target_p
->from
->name
);
1121 source_p
->flags
|= FLAGS_KILLED
;
1122 return exit_client(source_p
, source_p
, &me
, "USER server wrong direction");
1125 return (introduce_client(client_p
, source_p
, user
, nick
));
1129 save_user(struct Client
*client_p
, struct Client
*source_p
,
1130 struct Client
*target_p
)
1132 if (!MyConnect(target_p
) && (!has_id(target_p
) || !IsCapable(target_p
->from
, CAP_SAVE
)))
1134 /* This shouldn't happen */
1135 /* Note we only need SAVE support in this direction */
1136 sendto_realops_flags(UMODE_ALL
, L_ALL
,
1137 "Killed %s!%s@%s for nick collision detected by %s (%s does not support SAVE)",
1138 target_p
->name
, target_p
->username
, target_p
->host
, source_p
->name
, target_p
->from
->name
);
1139 kill_client_serv_butone(NULL
, target_p
, "%s (Nick collision (no SAVE support))", me
.name
);
1140 ServerStats
->is_kill
++;
1142 target_p
->flags
|= FLAGS_KILLED
;
1143 (void) exit_client(NULL
, target_p
, &me
, "Nick collision (no SAVE support)");
1146 sendto_server(client_p
, NULL
, CAP_SAVE
|CAP_TS6
, NOCAPS
, ":%s SAVE %s %ld",
1147 source_p
->id
, target_p
->id
, (long)target_p
->tsinfo
);
1148 sendto_server(client_p
, NULL
, CAP_TS6
, CAP_SAVE
, ":%s NICK %s :%ld",
1149 target_p
->id
, target_p
->id
, (long)SAVE_NICKTS
);
1150 sendto_server(client_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s NICK %s :%ld",
1151 target_p
->name
, target_p
->id
, (long)SAVE_NICKTS
);
1152 if (!IsMe(client_p
))
1153 sendto_realops_flags(UMODE_SKILL
, L_ALL
,
1154 "Received SAVE message for %s from %s",
1155 target_p
->name
, source_p
->name
);
1156 if (MyClient(target_p
))
1158 sendto_one_numeric(target_p
, RPL_SAVENICK
,
1159 form_str(RPL_SAVENICK
), target_p
->id
);
1160 change_local_nick(target_p
, target_p
, target_p
->id
, 0);
1161 target_p
->tsinfo
= SAVE_NICKTS
;
1164 change_remote_nick(target_p
, target_p
, SAVE_NICKTS
, target_p
->id
, 0);