mirror of
https://github.com/osmarks/ngircd.git
synced 2025-04-28 21:53:11 +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
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -39,7 +39,6 @@
|
|||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
#include "irc-login.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,
|
static void Change_Nick PARAMS((CLIENT * Origin, CLIENT * Target, char *NewNick,
|
||||||
bool InformClient));
|
bool InformClient));
|
||||||
|
|
||||||
@ -303,17 +302,21 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
|
|||||||
* the new nick is already present on this server:
|
* the new nick is already present on this server:
|
||||||
* the new and the old one have to be disconnected now.
|
* 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] );
|
Log(LOG_ERR,
|
||||||
Kill_Nick( Req->argv[0], "Nick collision" );
|
"Server %s introduces already registered nick \"%s\"!",
|
||||||
return CONNECTED;
|
Client_ID(Client), Req->argv[0]);
|
||||||
|
return IRC_KillClient(Client, NULL, Req->argv[0],
|
||||||
|
"Nick collision");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the Server this client is connected to */
|
/* Find the Server this client is connected to */
|
||||||
intr_c = Client_GetFromToken(Client, token);
|
intr_c = Client_GetFromToken(Client, token);
|
||||||
if (!intr_c) {
|
if (!intr_c) {
|
||||||
Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
|
Log(LOG_ERR,
|
||||||
Kill_Nick( Req->argv[0], "Unknown server" );
|
"Server %s introduces nick \"%s\" on unknown server!?",
|
||||||
return CONNECTED;
|
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,
|
c = Client_NewRemoteUser(intr_c, nick, hops, user, hostname,
|
||||||
@ -324,8 +327,8 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
|
|||||||
Log(LOG_ALERT,
|
Log(LOG_ALERT,
|
||||||
"Can't create client structure! (on connection %d)",
|
"Can't create client structure! (on connection %d)",
|
||||||
Client_Conn(Client));
|
Client_Conn(Client));
|
||||||
Kill_Nick(Req->argv[0], "Server error");
|
return IRC_KillClient(Client, NULL, Req->argv[0],
|
||||||
return CONNECTED;
|
"Server error");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC 2813: client is now fully registered, inform all the
|
/* RFC 2813: client is now fully registered, inform all the
|
||||||
@ -536,19 +539,19 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
|
|||||||
c = Client_Search(nick);
|
c = Client_Search(nick);
|
||||||
if(c) {
|
if(c) {
|
||||||
/* Nickname collision: disconnect (KILL) both clients! */
|
/* 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);
|
Client_ID(Client), nick);
|
||||||
Kill_Nick(nick, "Nick collision");
|
return IRC_KillClient(Client, NULL, nick, "Nick collision");
|
||||||
return CONNECTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the server to which the service is connected */
|
/* Get the server to which the service is connected */
|
||||||
intr_c = Client_GetFromToken(Client, token);
|
intr_c = Client_GetFromToken(Client, token);
|
||||||
if (! intr_c) {
|
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);
|
Client_ID(Client), nick);
|
||||||
Kill_Nick(nick, "Unknown server");
|
return IRC_KillClient(Client, NULL, nick, "Unknown server");
|
||||||
return CONNECTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get user and host name */
|
/* Get user and host name */
|
||||||
@ -577,10 +580,10 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
|
|||||||
if (! c) {
|
if (! c) {
|
||||||
/* Couldn't create client structure, so KILL the service to
|
/* Couldn't create client structure, so KILL the service to
|
||||||
* keep network status consistent ... */
|
* 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));
|
Client_Conn(Client));
|
||||||
Kill_Nick(nick, "Server error");
|
return IRC_KillClient(Client, NULL, nick, "Server error");
|
||||||
return CONNECTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client_Introduce(Client, c, CLIENT_SERVICE);
|
Client_Introduce(Client, c, CLIENT_SERVICE);
|
||||||
@ -855,31 +858,6 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
|
|||||||
return CONNECTED;
|
return CONNECTED;
|
||||||
} /* IRC_PONG */
|
} /* 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.
|
* 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
|
GLOBAL bool
|
||||||
IRC_KILL(CLIENT *Client, REQUEST *Req)
|
IRC_KILL(CLIENT *Client, REQUEST *Req)
|
||||||
{
|
{
|
||||||
CLIENT *prefix, *c;
|
CLIENT *prefix;
|
||||||
char reason[COMMAND_LEN], *msg;
|
char reason[COMMAND_LEN];
|
||||||
CONN_ID my_conn, conn;
|
|
||||||
|
|
||||||
assert (Client != NULL);
|
assert (Client != NULL);
|
||||||
assert (Req != NULL);
|
assert (Req != NULL);
|
||||||
@ -166,59 +165,8 @@ IRC_KILL(CLIENT *Client, REQUEST *Req)
|
|||||||
else
|
else
|
||||||
strlcpy(reason, Req->argv[1], sizeof(reason));
|
strlcpy(reason, Req->argv[1], sizeof(reason));
|
||||||
|
|
||||||
/* Inform other servers */
|
return IRC_KillClient(Client, prefix, Req->argv[0], reason);
|
||||||
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 */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for the IRC "NOTICE" command.
|
* Handler for the IRC "NOTICE" command.
|
||||||
@ -376,6 +324,81 @@ IRC_HELP(CLIENT *Client, REQUEST *Req)
|
|||||||
return CONNECTED;
|
return CONNECTED;
|
||||||
} /* IRC_HELP */
|
} /* 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.
|
* Send help for a given topic to the client.
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* ngIRCd -- The Next Generation IRC Daemon
|
* 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
|
* 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
|
* 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_TRACE PARAMS((CLIENT *Client, REQUEST *Req));
|
||||||
GLOBAL bool IRC_HELP 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
|
#endif
|
||||||
|
|
||||||
/* -eof- */
|
/* -eof- */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user