mirror of
https://github.com/osmarks/ngircd.git
synced 2025-02-22 20:20:03 +00:00
New function IRC_KillClient() to kill clients
The old local function Kill_Nick() in irc.c has been an ugly hack. This patch implements a generic function for killing clients. Adjust all callers of Kill_Nick() and respect the return code!
This commit is contained in:
parent
cccd8fc957
commit
b5faf3055b
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -39,7 +39,6 @@
|
||||
#include "exp.h"
|
||||
#include "irc-login.h"
|
||||
|
||||
static void Kill_Nick PARAMS((char *Nick, char *Reason));
|
||||
static void Change_Nick PARAMS((CLIENT * Origin, CLIENT * Target, char *NewNick,
|
||||
bool InformClient));
|
||||
|
||||
@ -303,17 +302,21 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
|
||||
* the new nick is already present on this server:
|
||||
* the new and the old one have to be disconnected now.
|
||||
*/
|
||||
Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
|
||||
Kill_Nick( Req->argv[0], "Nick collision" );
|
||||
return CONNECTED;
|
||||
Log(LOG_ERR,
|
||||
"Server %s introduces already registered nick \"%s\"!",
|
||||
Client_ID(Client), Req->argv[0]);
|
||||
return IRC_KillClient(Client, NULL, Req->argv[0],
|
||||
"Nick collision");
|
||||
}
|
||||
|
||||
/* Find the Server this client is connected to */
|
||||
intr_c = Client_GetFromToken(Client, token);
|
||||
if (!intr_c) {
|
||||
Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
|
||||
Kill_Nick( Req->argv[0], "Unknown server" );
|
||||
return CONNECTED;
|
||||
Log(LOG_ERR,
|
||||
"Server %s introduces nick \"%s\" on unknown server!?",
|
||||
Client_ID(Client), Req->argv[0]);
|
||||
return IRC_KillClient(Client, NULL, Req->argv[0],
|
||||
"Unknown server");
|
||||
}
|
||||
|
||||
c = Client_NewRemoteUser(intr_c, nick, hops, user, hostname,
|
||||
@ -324,8 +327,8 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
|
||||
Log(LOG_ALERT,
|
||||
"Can't create client structure! (on connection %d)",
|
||||
Client_Conn(Client));
|
||||
Kill_Nick(Req->argv[0], "Server error");
|
||||
return CONNECTED;
|
||||
return IRC_KillClient(Client, NULL, Req->argv[0],
|
||||
"Server error");
|
||||
}
|
||||
|
||||
/* RFC 2813: client is now fully registered, inform all the
|
||||
@ -536,19 +539,19 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
|
||||
c = Client_Search(nick);
|
||||
if(c) {
|
||||
/* Nickname collision: disconnect (KILL) both clients! */
|
||||
Log(LOG_ERR, "Server %s introduces already registered service \"%s\"!",
|
||||
Log(LOG_ERR,
|
||||
"Server %s introduces already registered service \"%s\"!",
|
||||
Client_ID(Client), nick);
|
||||
Kill_Nick(nick, "Nick collision");
|
||||
return CONNECTED;
|
||||
return IRC_KillClient(Client, NULL, nick, "Nick collision");
|
||||
}
|
||||
|
||||
/* Get the server to which the service is connected */
|
||||
intr_c = Client_GetFromToken(Client, token);
|
||||
if (! intr_c) {
|
||||
Log(LOG_ERR, "Server %s introduces service \"%s\" on unknown server!?",
|
||||
Log(LOG_ERR,
|
||||
"Server %s introduces service \"%s\" on unknown server!?",
|
||||
Client_ID(Client), nick);
|
||||
Kill_Nick(nick, "Unknown server");
|
||||
return CONNECTED;
|
||||
return IRC_KillClient(Client, NULL, nick, "Unknown server");
|
||||
}
|
||||
|
||||
/* Get user and host name */
|
||||
@ -577,10 +580,10 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
|
||||
if (! c) {
|
||||
/* Couldn't create client structure, so KILL the service to
|
||||
* keep network status consistent ... */
|
||||
Log(LOG_ALERT, "Can't create client structure! (on connection %d)",
|
||||
Log(LOG_ALERT,
|
||||
"Can't create client structure! (on connection %d)",
|
||||
Client_Conn(Client));
|
||||
Kill_Nick(nick, "Server error");
|
||||
return CONNECTED;
|
||||
return IRC_KillClient(Client, NULL, nick, "Server error");
|
||||
}
|
||||
|
||||
Client_Introduce(Client, c, CLIENT_SERVICE);
|
||||
@ -855,31 +858,6 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
|
||||
return CONNECTED;
|
||||
} /* IRC_PONG */
|
||||
|
||||
/**
|
||||
* Kill all users with a specific nickname in the network.
|
||||
*
|
||||
* @param Nick Nickname.
|
||||
* @param Reason Reason for the KILL.
|
||||
*/
|
||||
static void
|
||||
Kill_Nick(char *Nick, char *Reason)
|
||||
{
|
||||
REQUEST r;
|
||||
|
||||
assert (Nick != NULL);
|
||||
assert (Reason != NULL);
|
||||
|
||||
r.prefix = NULL;
|
||||
r.argv[0] = Nick;
|
||||
r.argv[1] = Reason;
|
||||
r.argc = 2;
|
||||
|
||||
Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s!",
|
||||
Nick, Reason);
|
||||
|
||||
IRC_KILL(Client_ThisServer(), &r);
|
||||
} /* Kill_Nick */
|
||||
|
||||
/**
|
||||
* Change the nickname of a client.
|
||||
*
|
||||
|
135
src/ngircd/irc.c
135
src/ngircd/irc.c
@ -128,9 +128,8 @@ IRC_ERROR(CLIENT *Client, REQUEST *Req)
|
||||
GLOBAL bool
|
||||
IRC_KILL(CLIENT *Client, REQUEST *Req)
|
||||
{
|
||||
CLIENT *prefix, *c;
|
||||
char reason[COMMAND_LEN], *msg;
|
||||
CONN_ID my_conn, conn;
|
||||
CLIENT *prefix;
|
||||
char reason[COMMAND_LEN];
|
||||
|
||||
assert (Client != NULL);
|
||||
assert (Req != NULL);
|
||||
@ -166,59 +165,8 @@ IRC_KILL(CLIENT *Client, REQUEST *Req)
|
||||
else
|
||||
strlcpy(reason, Req->argv[1], sizeof(reason));
|
||||
|
||||
/* Inform other servers */
|
||||
IRC_WriteStrServersPrefix(Client, prefix, "KILL %s :%s",
|
||||
Req->argv[0], reason);
|
||||
|
||||
/* Save ID of this connection */
|
||||
my_conn = Client_Conn( Client );
|
||||
|
||||
/* Do we host such a client? */
|
||||
c = Client_Search( Req->argv[0] );
|
||||
if (c) {
|
||||
if (Client_Type(c) != CLIENT_USER
|
||||
&& Client_Type(c) != CLIENT_GOTNICK) {
|
||||
/* Target of this KILL is not a regular user, this is
|
||||
* invalid! So we ignore this case if we received a
|
||||
* regular KILL from the network and try to kill the
|
||||
* client/connection anyway (but log an error!) if the
|
||||
* origin is the local server. */
|
||||
|
||||
if (Client != Client_ThisServer()) {
|
||||
/* Invalid KILL received from remote */
|
||||
if (Client_Type(c) == CLIENT_SERVER)
|
||||
msg = ERR_CANTKILLSERVER_MSG;
|
||||
else
|
||||
msg = ERR_NOPRIVILEGES_MSG;
|
||||
return IRC_WriteErrClient(Client, msg,
|
||||
Client_ID(Client));
|
||||
}
|
||||
|
||||
Log(LOG_ERR,
|
||||
"Got KILL for invalid client type: %d, \"%s\"!",
|
||||
Client_Type( c ), Req->argv[0] );
|
||||
}
|
||||
|
||||
/* Kill the client NOW:
|
||||
* - Close the local connection (if there is one),
|
||||
* - Destroy the CLIENT structure for remote clients.
|
||||
* Note: Conn_Close() removes the CLIENT structure as well. */
|
||||
conn = Client_Conn( c );
|
||||
if(conn > NONE)
|
||||
Conn_Close(conn, NULL, reason, true);
|
||||
else
|
||||
Client_Destroy(c, NULL, reason, false);
|
||||
}
|
||||
else
|
||||
Log(LOG_NOTICE, "Client with nick \"%s\" is unknown here.",
|
||||
Req->argv[0]);
|
||||
|
||||
/* Are we still connected or were we killed, too? */
|
||||
if (my_conn > NONE && Conn_GetClient(my_conn))
|
||||
return CONNECTED;
|
||||
else
|
||||
return DISCONNECTED;
|
||||
} /* IRC_KILL */
|
||||
return IRC_KillClient(Client, prefix, Req->argv[0], reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for the IRC "NOTICE" command.
|
||||
@ -376,6 +324,81 @@ IRC_HELP(CLIENT *Client, REQUEST *Req)
|
||||
return CONNECTED;
|
||||
} /* IRC_HELP */
|
||||
|
||||
/**
|
||||
* Kill an client identified by its nick name.
|
||||
*
|
||||
* Please note that after killig a client, its CLIENT cond CONNECTION
|
||||
* structures are invalid. So the caller must make sure on its own not to
|
||||
* access data of probably killed clients after calling this function!
|
||||
*
|
||||
* @param Client The client from which the command leading to the KILL has
|
||||
* been received, or NULL. The KILL will no be forwarded in this
|
||||
* direction. Only relevant when From is set, too.
|
||||
* @param From The client from which the command originated, or NULL for
|
||||
the local server.
|
||||
* @param Nick The nick name to kill.
|
||||
* @param Reason Text to send as reason to the client and other servers.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_KillClient(CLIENT *Client, CLIENT *From, const char *Nick, const char *Reason)
|
||||
{
|
||||
const char *msg;
|
||||
CONN_ID my_conn, conn;
|
||||
CLIENT *c;
|
||||
|
||||
/* Inform other servers */
|
||||
IRC_WriteStrServersPrefix(From ? Client : NULL,
|
||||
From ? From : Client_ThisServer(),
|
||||
"KILL %s :%s", Nick, Reason);
|
||||
|
||||
/* Do we know such a client? */
|
||||
c = Client_Search(Nick);
|
||||
if (!c) {
|
||||
LogDebug("Client with nick \"%s\" is unknown here.", Nick);
|
||||
return CONNECTED;
|
||||
}
|
||||
|
||||
if (Client_Type(c) != CLIENT_USER && Client_Type(c) != CLIENT_GOTNICK) {
|
||||
/* Target of this KILL is not a regular user, this is
|
||||
* invalid! So we ignore this case if we received a
|
||||
* regular KILL from the network and try to kill the
|
||||
* client/connection anyway (but log an error!) if the
|
||||
* origin is the local server. */
|
||||
|
||||
if (Client != Client_ThisServer()) {
|
||||
/* Invalid KILL received from remote */
|
||||
if (Client_Type(c) == CLIENT_SERVER)
|
||||
msg = ERR_CANTKILLSERVER_MSG;
|
||||
else
|
||||
msg = ERR_NOPRIVILEGES_MSG;
|
||||
return IRC_WriteErrClient(Client, msg, Client_ID(Client));
|
||||
}
|
||||
|
||||
Log(LOG_ERR,
|
||||
"Got KILL for invalid client type: %d, \"%s\"!",
|
||||
Client_Type(c), Nick);
|
||||
}
|
||||
|
||||
/* Save ID of this connection */
|
||||
my_conn = Client_Conn(Client);
|
||||
|
||||
/* Kill the client NOW:
|
||||
* - Close the local connection (if there is one),
|
||||
* - Destroy the CLIENT structure for remote clients.
|
||||
* Note: Conn_Close() removes the CLIENT structure as well. */
|
||||
conn = Client_Conn(c);
|
||||
if(conn > NONE)
|
||||
Conn_Close(conn, NULL, Reason, true);
|
||||
else
|
||||
Client_Destroy(c, NULL, Reason, false);
|
||||
|
||||
/* Are we still connected or were we killed, too? */
|
||||
if (my_conn > NONE && Conn_GetClient(my_conn))
|
||||
return CONNECTED;
|
||||
else
|
||||
return DISCONNECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send help for a given topic to the client.
|
||||
*
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
* Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -28,6 +28,9 @@ GLOBAL bool IRC_SQUERY PARAMS((CLIENT *Client, REQUEST *Req));
|
||||
GLOBAL bool IRC_TRACE PARAMS((CLIENT *Client, REQUEST *Req));
|
||||
GLOBAL bool IRC_HELP PARAMS((CLIENT *Client, REQUEST *Req));
|
||||
|
||||
GLOBAL bool IRC_KillClient PARAMS((CLIENT *Client, CLIENT *From,
|
||||
const char *Nick, const char *Reason));
|
||||
|
||||
#endif
|
||||
|
||||
/* -eof- */
|
||||
|
Loading…
x
Reference in New Issue
Block a user