/************************************************************************
* IRC - Internet Relay Chat, modules/m_nick.c
*
* Copyright (C) 2000-2003 TR-IRCD Development
*
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Co Center
*
* See file AUTHORS in IRC package for additional names of
* the programmers.
*
* This program is free softwmare; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "chanmode.h"
#include "s_conf.h"
#include "throttle.h"
#include "usermode.h"
#include "h.h"
static char *n_token = TOK1_NICK;
static char *c_token = TOK1_CLIENT;
static int collide_nicknames(char *nick, int new, int newts,
char **parv, aClient *cptr, aClient *sptr);
static struct Message n_msgtab[] = {
{MSG_NICK, 0, MAXPARA, M_SLOW, 0L,
u_nick, u_nick, u_nick, s_nick, m_ignore}
};
static struct Message c_msgtab[] = {
{MSG_CLIENT, 0, MAXPARA, M_SLOW, 0l,
m_ignore, m_ignore, m_ignore, m_client, m_ignore}
};
#ifndef STATIC_MODULES
char *_version = "$Revision: 1.11 $";
void _modinit(void)
{
mod_add_cmd(n_msgtab);
tok1_msgtab[(u_char) *n_token].msg = n_msgtab;
mod_add_cmd(c_msgtab);
tok1_msgtab[(u_char) *c_token].msg = c_msgtab;
}
void _moddeinit(void)
{
mod_del_cmd(n_msgtab);
tok1_msgtab[(u_char) *n_token].msg = NULL;
mod_del_cmd(c_msgtab);
tok1_msgtab[(u_char) *c_token].msg = NULL;
}
#else
void m_nick_init(void)
{
mod_add_cmd(n_msgtab);
tok1_msgtab[(u_char) *n_token].msg = n_msgtab;
mod_add_cmd(c_msgtab);
tok1_msgtab[(u_char) *c_token].msg = c_msgtab;
}
#endif
/* clean_nick_name()
*
* input - nickname
* output - none
* side effects - walks through the nickname, returning 0 if erroneous
*/
static int clean_nick_name(char *nick)
{
if (nick == NULL || *nick == '\0')
return 0;
/* nicks cant start with a digit or - */
if (*nick == '-' || IsDigit(*nick))
return 0;
for (; *nick; nick++) {
if (!IsNickChar(*nick))
return 0;
}
return 1;
}
/*
*
* m_nick
* parv[0] = sender prefix
* parv[1] = nickname
* parv[2] = hopcount when new user; TS when nick change
* parv[3] = TS
* ---- new user only below ----
* parv[4] = umode
* parv[5] = username
* parv[6] = hostname
* parv[7] = server
* parv[8] = serviceid
* parv[9] = ircname
* ---- DT1 protocol change ----
* parv[4] = umode
* parv[5] = username
* parv[6] = hostname
* parv[7] = fakehost
* parv[8] = server
* parv[9] = serviceid
* parv[10] = IP
* parv[11] = ircname
* -- endif
*/
int s_nick(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *uplink;
char nick[NICKLEN + 2];
long newts = 0;
int samenick = 0;
int test = 0;
/* We do not blame servers by sending them numerics. Since s_nick can
* only result from a server, we silently return when parc < 2.
* -TimeMr14C
*/
if (parc < 3)
return 0;
/*
* parc == 2 on a normal client sign on (local) and a normal client nick change
* parc == 4 on a normal server-to-server client nick change
* parc >= 10 on a normal TS style server-to-server NICK introduction
*/
if (parc > 3 && parc < 10) {
/*
* We got the wrong number of params. Someone is trying to trick
* us. Kill it. -ThemBones As discussed with ThemBones, not much
* point to this code now sending a whack of global kills would
* also be more annoying then its worth, just note the problem,
* and continue -Dianora
*/
sendto_lev(SNOTICE_LEV, "IGNORING BAD NICK: %s[%s@%s] on %s (from %s)",
parv[1], (parc >= 6) ? parv[5] : "-",
(parc >= 7) ? parv[6] : "-", (parc >= 8) ? parv[7] : "-", parv[0]);
return 0;
}
/* Here we had a check after a dot in the hostname. This is removed
* due to the fact that operators might have dotless hostnames due to
* a DALnet like usage of oper hostmasking feature.
* That check did not do anything but crying out loud, so it was of no
* effect anyway. 29.04.2002 -TimeMr14C
*/
strlcpy_irc(nick, parv[1], NICKLEN);
/*
* if clean_nick_name() returns a null name OR if the server sent a
* nick name and clean_nick_name() changed it in some way (due to rules
* of nick creation) then reject it. If from a server and we reject
* it, and KILL it. -avalon 4/4/92
*/
if (clean_nick_name(nick) == 0 || strcmp(nick, parv[1])) {
send_me_numeric(cptr, ERR_ERRONEUSNICKNAME, parv[1]);
ircstp->is_kill++;
sendto_lev(DEBUG_LEV, "Bad Nick: %s From: %s %s",
parv[1], parv[0], get_client_name(cptr, FALSE));
sendto_one(cptr, ":%C %s %s :Bad Nick", &me, MSG_KILL, parv[1]);
if (sptr != cptr) {
sendto_serv_butone(cptr, &me, TOK1_KILL, "%~C :Incoherent Nickname", cptr);
sptr->flags |= FLAGS_KILLED;
return exit_client(sptr, &me, "Incoherent Nickname");
}
return 0;
}
/*
* * Check against nick name collisions. *
*
* We check against server name list before determining if the
* nickname * is present in the nicklist (due to the way the below
* for loop is * constructed). -avalon
*/
test = collide_nicknames(nick, 0, newts, parv, cptr, sptr);
if (test != -1)
return test;
if (parc == 12) {
aClient *acptr2;
long flag;
char *m;
u_long newip = 0;
uplink = find_server(parv[8]);
if (!uplink) {
sendto_lev(SNOTICE_LEV, "Remote nick %s on UNKNOWN server %s", nick, parv[8]);
return 0;
}
acptr2 = make_client(cptr);
acptr2->servptr = uplink;
strcpy(acptr2->name, nick);
add_client_to_list(acptr2);
add_to_client_hash_table(nick, acptr2);
if (IsULine(uplink))
acptr2->protoflags |= PFLAGS_ULINE;
acptr2->hopcount = atoi(parv[2]);
newts = atol(parv[3]);
if (!newts)
newts = timeofday;
acptr2->tsval = newts;
m = &parv[4][1];
while (*m) {
if (umodetab[(int) *m].in_use) {
flag = umodetab[(int) *m].type;
if ((flag == UMODE_o))
Count.oper++;
if ((flag & UMODE_i))
Count.invisi++;
acptr2->umode |= flag & SEND_UMODES;
}
m++;
}
newip = strtoul(parv[10], NULL, 0);
IN4_ADDR(acptr2->ip) = newip;
/* adding the remote client to the throttle hash.
* checking local clients takes place in s_bsd.c
* -epi */
if (newip != 0)
throttle_check(inetntoa((char *) &acptr2->ip), -1, acptr2->tsval);
return do_remote_user(nick, cptr, acptr2, parv[5], parv[6], parv[7],
parv[8], strtoul(parv[9], NULL, 0), parv[11]);
}
else if (sptr->name[0]) {
/*
* * Client just changing his/her nick. If he/she is * on a
* channel, send note of change to all clients * on that channel.
* Propagate notice to other servers.
*/
newts = atol(parv[2]);
/*
* if the nickname is different, set the TS
* AND set it -r. No need to propogate MODE -r and spam
* the network on registered nick changes. yuck. - lucas
*/
if (irc_strcmp(parv[0], nick)) {
sptr->tsval = newts ? newts : (long) timeofday;
sptr->umode &= ~UMODE_r;
}
sendto_common_channels(sptr, ":%C %s :%s", sptr, MSG_NICK, nick);
if (sptr->user) {
add_history(sptr, 1);
sendto_serv_butone(cptr, sptr, TOK1_NICK, "%s :%T", nick, sptr);
sendto_service(SERVICE_SEE_NICKS, 0, sptr, NULL, TOK1_NICK, "%s :%T", nick, sptr);
}
del_from_client_hash_table(sptr->name, sptr);
samenick = irc_strcmp(sptr->name, nick) ? 0 : 1;
if (!samenick)
hash_check_watch(sptr, RPL_LOGOFF);
strcpy(sptr->name, nick);
add_to_client_hash_table(nick, sptr);
if (!samenick)
hash_check_watch(sptr, RPL_LOGON);
return 0;
}
return 0;
}
/* This function is a new version of the SERVER NICK line,
* it is only exchanged between nativemode servers, and does not
* have too many case differentiations.
*/
/*
*
* m_nick
* parv[0] = sender prefix
* parv[1] = nickname
* parv[2] = hopcount when new user; TS when nick change
* parv[3] = TS
* parv[4] = umode
* parv[5] = username
* parv[6] = hostname
* parv[7] = fakehost
* parv[8] = language
* parv[9] = server OR id/server-pair
* parv[10] = serviceid
* parv[11] = ircname
* -- endif
*/
int m_client(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *uplink;
char nick[NICKLEN + 2];
long newts = 0;
int test = 0;
if (parc < 2) {
send_me_numeric(sptr, ERR_NONICKNAMEGIVEN);
return 0;
}
newts = atol(parv[3]);
strlcpy_irc(nick, parv[1], NICKLEN);
/*
* if clean_nick_name() returns a null name OR if the server sent a
* nick name and clean_nick_name() changed it in some way (due to rules
* of nick creation) then reject it. If from a server and we reject
* it, and KILL it. -avalon 4/4/92
*/
if (clean_nick_name(nick) == 0 || strcmp(nick, parv[1])) {
send_me_numeric(cptr, ERR_ERRONEUSNICKNAME, parv[1]);
ircstp->is_kill++;
sendto_lev(DEBUG_LEV, "Bad Nick: %s From: %s %s",
parv[1], parv[0], get_client_name(cptr, FALSE));
sendto_one(cptr, ":%C %s %s :Bad Nick", &me, MSG_KILL, parv[1]);
if (sptr != cptr) {
sendto_serv_butone(cptr, &me, TOK1_KILL, "%~C :Bad Nick", cptr);
sptr->flags |= FLAGS_KILLED;
return exit_client(sptr, &me, "BadNick");
}
return 0;
}
/*
* * Check against nick name collisions. *
*
* We check against server name list before determining if the
* nickname * is present in the nicklist (due to the way the below
* for loop is * constructed). -avalon
*/
test = collide_nicknames(nick, 0, newts, parv, cptr, sptr);
if (test != -1)
return test;
if (parc == 12) {
aClient *acptr2;
long flag = 0;
int pflags = 0;
char *m;
u_long newid, newip = 0;
char *base64id = NULL;
char *ipp;
char *newhostip = NULL;
aClient *bucptr;
base64id = &parv[9][1];
ipp = strchr(base64id, '%');
if (ipp) {
*ipp++ = '\0';
newhostip = ipp;
pflags |= PFLAGS_IPV6HOST;
} else {
ipp = strchr(base64id, ':');
if (ipp) {
*ipp++ = '\0';
newip = base64dec(ipp);
}
}
if ((bucptr = find_by_base64_id(base64id))) {
sendto_ops("IDENTITY COLLISION! (%s[%s][%s] <> %s[%s][%s])",
sptr->name, sptr->servptr->name, base64id,
bucptr->name, bucptr->servptr->name, bucptr->id.string);
return exit_client(bucptr, &me, "Identity collision!");
}
uplink = find_server_by_base64_id(base64id, &newid);
if (uplink) {
parv[9] = uplink->name;
} else {
sendto_lev(SNOTICE_LEV, "Remote nick %s on UNKNOWN server %s", nick, parv[9]);
return 0;
}
acptr2 = make_client(cptr);
acptr2->servptr = uplink;
strcpy(acptr2->name, nick);
add_client_to_list(acptr2);
add_to_client_hash_table(nick, acptr2);
SetHasID(acptr2); /* this client is identity capable */
acptr2->id.id = newid; /* new identity! */
strlcpy_irc(acptr2->id.string, base64id, 8);
add_userid_to_server(uplink, acptr2);
if (IsULine(uplink))
pflags |= PFLAGS_ULINE;
acptr2->hopcount = atoi(parv[2]);
if (!newts)
newts = timeofday;
acptr2->tsval = newts;
m = &parv[4][1];
while (*m) {
if (umodetab[(int) *m].in_use) {
flag = umodetab[(int) *m].type;
if ((flag == UMODE_o))
Count.oper++;
if ((flag & UMODE_i))
Count.invisi++;
acptr2->umode |= flag & SEND_UMODES;
}
m++;
}
if (newip) {
IN4_ADDR(acptr2->ip) = newip;
throttle_check(inetntoa((char *) &acptr2->ip), -1, acptr2->tsval);
}
if (newhostip) {
strlcpy_irc(acptr2->hostip, newhostip, HOSTIPLEN);
throttle_check(newhostip, -1, acptr2->tsval);
}
acptr2->lang = atoi(parv[8]);
acptr2->protoflags |= pflags;
return do_remote_user(nick, cptr, acptr2, parv[5], parv[6], parv[7],
parv[9], base64dec(parv[10]), parv[11]);
}
return 0;
}
/* guaranteed sptr == cptr, !IsServer(cptr), !IsServer(sptr) */
int u_nick(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aMaskItem *ami;
aChannel *chptr;
dlink_node *lp;
char nick[NICKLEN + 2];
long newts = 0;
int samenick = 0;
int test = 0;
if (parc < 2) {
send_me_numeric(sptr, ERR_NONICKNAMEGIVEN);
return 0;
}
strlcpy_irc(nick, parv[1], NICKLEN);
/*
* if clean_nick_name() returns a null name OR if the server sent a
* nick name and clean_nick_name() changed it in some way (due to rules
* of nick creation) then reject it. If from a server and we reject
* it, and KILL it. -avalon 4/4/92
*/
if (clean_nick_name(nick) == 0) {
send_me_numeric(cptr, ERR_ERRONEUSNICKNAME, parv[1]);
return 0;
}
/*
* * Check against nick name collisions. *
*
* Put this 'if' here so that the nesting goes nicely on the screen
* :) * We check against server name list before determining if the
* nickname * is present in the nicklist (due to the way the below
* for loop is * constructed). -avalon
*/
test = collide_nicknames(nick, 1, newts, parv, cptr, sptr);
if (test != -1)
return test;
if (sptr->name[0]) {
/*
* * Client just changing his/her nick. If he/she is * on a
* channel, send note of change to all clients * on that channel.
* Propagate notice to other servers.
*/
if ((ami = find_maskitem(nick, NULL, MASKITEM_QUARANTINE, 1)) && !IsAnOper(sptr)) {
send_me_numeric(sptr, ERR_ERRONEUSNICKNAME, nick, ami->reason);
send_me_numeric(sptr, ERR_EVALUATINGQLINE, ami->string, ami->reason);
sendto_lev(QLINE_LEV,
"Forbidding Quarantined nick %s from %s. Qline [%s] evaluates into %s", nick,
get_client_name(cptr, FALSE), ami->string, nick);
return 0;
} else if ((ami = find_maskitem(nick, NULL, MASKITEM_QUARANTINE_CONFIG, 1)) && !IsAnOper(sptr)) {
send_me_numeric(sptr, ERR_ERRONEUSNICKNAME, nick, ami->reason);
send_me_numeric(sptr, ERR_EVALUATINGQLINE, ami->string, ami->reason);
sendto_lev(QLINE_LEV,
"Forbidding Quarantined nick %s from %s. Qline [%s] evaluates into %s", nick,
get_client_name(cptr, FALSE), ami->string, nick);
return 0;
} else if (ServerOpts.use_regex && !IsAnOper(sptr) &&
(ami = find_maskitem(nick, NULL, MASKITEM_QUARANTINE_REGEX, 1))) {
send_me_numeric(sptr, ERR_ERRONEUSNICKNAME, nick, ami->reason);
send_me_numeric(sptr, ERR_EVALUATINGQLINE, ami->string, ami->reason);
sendto_lev(QLINE_LEV,
"Forbidding Quarantined nick %s from %s. Qline [%s] evaluates into %s", nick,
get_client_name(cptr, FALSE), ami->string, nick);
return 0;
}
if (IsPerson(sptr)) {
for (lp = sptr->user->channel.head; lp; lp = lp->next) {
chptr = lp->data;
if (nick_is_nuhed(chptr, nick, sptr, &chptr->banlist) != NULL) {
send_me_numeric(sptr, ERR_BANONCHAN, nick, chptr->chname);
return 0;
}
}
if (ServerOpts.anti_nick_flood) {
if ((sptr->last_nick_time + ServerOpts.max_nick_time) < NOW)
sptr->count_nick = 0;
sptr->last_nick_time = NOW;
sptr->count_nick++;
}
if (sptr->count_nick <= ServerOpts.max_nick_changes || IsAnOper(sptr)) {
/*
* if the nickname is different, set the TS
* AND set it -r. No need to propogate MODE -r and spam
* the network on registered nick changes. yuck. - lucas
*/
if (irc_strcmp(parv[0], nick)) {
sptr->tsval = timeofday;
sptr->umode &= ~UMODE_r;
}
sendto_common_channels(sptr, ":%C %s :%s", sptr, MSG_NICK, nick);
if (sptr->user) {
add_history(sptr, 1);
sendto_serv_butone(cptr, sptr, TOK1_NICK, "%s :%T", nick, sptr);
sendto_service(SERVICE_SEE_NICKS, 0, sptr, NULL,
TOK1_NICK, "%s :%T", nick, sptr);
}
} else {
send_me_notice(sptr,
":*** Notice -- Too many nick changes. Wait %d seconds"
"before trying again", ServerOpts.max_nick_time);
return 0;
}
}
del_from_client_hash_table(sptr->name, sptr);
samenick = irc_strcmp(sptr->name, nick) ? 0 : 1;
if (IsPerson(sptr) && !samenick)
hash_check_watch(sptr, RPL_LOGOFF);
strcpy(sptr->name, nick);
add_to_client_hash_table(nick, sptr);
if (IsPerson(sptr) && !samenick)
hash_check_watch(sptr, RPL_LOGON);
fd_note(sptr->fd, "Nick %s", nick);
}
else {
/* Client setting NICK the first time */
if ((ami = find_maskitem(nick, NULL, MASKITEM_QUARANTINE, 1))) {
send_me_numeric(sptr, ERR_ERRONEUSNICKNAME, nick, ami->reason);
send_me_numeric(sptr, ERR_EVALUATINGQLINE, ami->string, ami->reason);
sendto_lev(QLINE_LEV,
"Forbidding Quarantined nick %s from %s. Qline [%s] evaluates into %s", nick,
get_client_name(cptr, FALSE), ami->string, nick);
return 0;
} else if ((ami = find_maskitem(nick, NULL, MASKITEM_QUARANTINE_CONFIG, 1))) {
send_me_numeric(sptr, ERR_ERRONEUSNICKNAME, nick, ami->reason);
send_me_numeric(sptr, ERR_EVALUATINGQLINE, ami->string, ami->reason);
sendto_lev(QLINE_LEV,
"Forbidding Quarantined nick %s from %s. Qline [%s] evaluates into %s", nick,
get_client_name(cptr, FALSE), ami->string, nick);
return 0;
} else if (ServerOpts.use_regex &&
(ami = find_maskitem(nick, NULL, MASKITEM_QUARANTINE_REGEX, 1))) {
send_me_numeric(sptr, ERR_ERRONEUSNICKNAME, nick, ami->reason);
send_me_numeric(sptr, ERR_EVALUATINGQLINE, ami->string, ami->reason);
sendto_lev(QLINE_LEV,
"Forbidding Quarantined nick %s from %s. Qline [%s] evaluates into %s", nick,
get_client_name(cptr, FALSE), ami->string, nick);
return 0;
}
strcpy(sptr->name, nick);
sptr->tsval = timeofday;
add_to_client_hash_table(nick, sptr);
fd_note(sptr->fd, "Nick %s", nick);
if (sptr->user) {
/* USER already received, now we have NICK. */
return register_local_user(cptr, sptr, nick, sptr->user->username);
}
}
return 0;
}
static int collide_nicknames(char *nick, int new, int newts, char **parv,
aClient *cptr, aClient *sptr)
{
aClient *acptr;
int sameuser = 0;
if (new) {
/* nothing else is using this nick, great! */
if (!(acptr = find_client(nick)))
return -1;
/*
* * If acptr == sptr, then we have a client doing a nick * change
* between *equivalent* nicknames as far as server * is concerned
* (user is changing the case of his/her * nickname or somesuch)
*/
if (acptr == sptr) {
if (strcmp(acptr->name, nick) != 0)
return -1;
else
return 0;
}
if (IsUnknown(acptr)) {
exit_client(acptr, &me, "Overridden by older signon");
return -1;
}
/*
* * NICK is coming from local client connection. Just * send
* error reply and ignore the command.
* parv[0] is empty on connecting clients
*/
send_me_numeric(cptr, ERR_NICKNAMEINUSE, nick);
return 0;
}
if (!(acptr = find_client(nick)))
return -1;
/*
* * If acptr == sptr, then we have a client doing a nick * change
* between *equivalent* nicknames as far as server * is concerned
* (user is changing the case of his/her * nickname or somesuch)
*/
if (acptr == sptr) {
if (strcmp(acptr->name, nick) != 0)
return -1;
else
return 0;
}
/*
* * If the older one is "non-person", the new entry is just *
* allowed to overwrite it. Just silently drop non-person, * and
* proceed with the nick. This should take care of the * "dormant
* nick" way of generating collisions...
*/
if (IsUnknown(acptr)) {
exit_client(acptr, &me, "Overridden by older signon");
return -1;
}
if (!newts || !acptr->tsval || (newts == acptr->tsval)) {
sendto_lev(SKILL_LEV, "Nick collision on %s", acptr->name);
ircstp->is_kill++;
send_me_numeric(acptr, ERR_NICKCOLLISION, acptr->name);
sendto_serv_butone(NULL, &me, TOK1_KILL, "%~C :Nick Collision", acptr);
acptr->flags |= FLAGS_KILLED;
exit_client(acptr, &me, "Nick collision");
return 0;
} else {
sameuser = (acptr->user) &&
irc_strcmp(acptr->user->username, parv[5]) == 0 &&
irc_strcmp(acptr->user->host, parv[6]) == 0;
if ((sameuser && newts < acptr->tsval)
|| (!sameuser && newts > acptr->tsval))
return 0;
else {
if (sameuser)
sendto_lev(SKILL_LEV, "Nick collision on %s", acptr->name);
else
sendto_lev(SKILL_LEV, "Nick collision on %s", acptr->name);
ircstp->is_kill++;
send_me_numeric(acptr, ERR_NICKCOLLISION, acptr->name);
sendto_serv_butone(sptr, &me, TOK1_KILL, "%~C :Nick Collision", acptr);
acptr->flags |= FLAGS_KILLED;
exit_client(acptr, &me, "Nick collision");
return -1;
}
}
/*
* * A NICK change has collided (e.g. message type * ":old NICK
* new". This requires more complex cleanout. * Both clients must be
* purged from this server, the "new" * must be killed from the
* incoming connection, and "old" must * be purged from all outgoing
* connections.
*/
if (!newts || !acptr->tsval || (newts == acptr->tsval)
|| !sptr->user) {
sendto_lev(SKILL_LEV, "Nick change collision from %s to %s", sptr->name, acptr->name);
ircstp->is_kill++;
send_me_numeric(acptr, ERR_NICKCOLLISION, acptr->name);
sendto_serv_butone(NULL, &me, TOK1_KILL, "%~C :Nick collision", sptr);
ircstp->is_kill++;
sendto_serv_butone(NULL, &me, TOK1_KILL, "%~C :Nick collision", acptr);
acptr->flags |= FLAGS_KILLED;
exit_client(acptr, &me, "Nick collision(new)");
sptr->flags |= FLAGS_KILLED;
exit_client(sptr, &me, "Nick collision(old)");
return 0;
} else {
sameuser =
irc_strcmp(acptr->user->username, sptr->user->username) == 0
&& irc_strcmp(acptr->user->host, sptr->user->host) == 0;
if ((sameuser && newts < acptr->tsval)
|| (!sameuser && newts > acptr->tsval)) {
if (sameuser)
sendto_lev(SKILL_LEV,
"Nick change collision from %s to %s(older killed)",
sptr->name, acptr->name);
ircstp->is_kill++;
sendto_serv_butone(cptr, &me, TOK1_KILL, "%~C :Nick Collision", sptr);
sptr->flags |= FLAGS_KILLED;
if (sameuser)
exit_client(sptr, &me, "Nick collision(old)");
else
exit_client(sptr, &me, "Nick collision(new)");
return 0;
} else {
sendto_lev(SKILL_LEV, "Nick collision on %s", acptr->name);
ircstp->is_kill++;
send_me_numeric(acptr, ERR_NICKCOLLISION, acptr->name);
sendto_serv_butone(sptr, &me, TOK1_KILL, "%~C :Nick Collision", acptr);
acptr->flags |= FLAGS_KILLED;
exit_client(acptr, &me, "Nick collision");
return 0;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1