mirror of
https://github.com/osmarks/ngircd.git
synced 2025-01-19 03:52:52 +00:00
Enable SQUIT command for IRC Operators
This patch enables IRC Operators to use the SQUIT command as specified in RFC 2812, section 3.1.8 "Squit". When forwarding SQUIT commands, the server connected to the target will drop the connection (not the target server itself!). Please note: - the configuration option "AllowRemoteOper" mus be enabled on the server disconnecting the target to allow forwarding of SQUIT commands. - if the remote server is configured to establish the connection, it will just do this; so the disconnect is not permanent in this case!
This commit is contained in:
parent
03b70229eb
commit
294320ed62
@ -37,6 +37,7 @@
|
||||
#include "numeric.h"
|
||||
#include "ngircd.h"
|
||||
#include "irc-info.h"
|
||||
#include "op.h"
|
||||
|
||||
#include "exp.h"
|
||||
#include "irc-server.h"
|
||||
@ -273,21 +274,40 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req )
|
||||
GLOBAL bool
|
||||
IRC_SQUIT(CLIENT * Client, REQUEST * Req)
|
||||
{
|
||||
CLIENT *target;
|
||||
char msg[LINE_LEN + 64];
|
||||
char msg[COMMAND_LEN], logmsg[COMMAND_LEN];
|
||||
CLIENT *from, *target;
|
||||
CONN_ID con;
|
||||
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
|
||||
if (Client_Type(Client) != CLIENT_SERVER
|
||||
&& !Client_HasMode(Client, 'o'))
|
||||
return Op_NoPrivileges(Client, Req);
|
||||
|
||||
/* Bad number of arguments? */
|
||||
if (Req->argc != 2)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) {
|
||||
from = Client_Search(Req->prefix);
|
||||
if (Client_Type(from) != CLIENT_SERVER
|
||||
&& !Op_Check(Client, Req))
|
||||
return Op_NoPrivileges(Client, Req);
|
||||
} else
|
||||
from = Client;
|
||||
if (!from)
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(Client), Req->prefix);
|
||||
|
||||
Log(LOG_DEBUG, "Got SQUIT from %s for \"%s\": \"%s\" ...",
|
||||
Client_ID(Client), Req->argv[0], Req->argv[1]);
|
||||
Client_ID(from), Req->argv[0], Req->argv[1]);
|
||||
|
||||
target = Client_Search(Req->argv[0]);
|
||||
if (Client_Type(Client) != CLIENT_SERVER &&
|
||||
target == Client_ThisServer())
|
||||
return Op_NoPrivileges(Client, Req);
|
||||
if (!target) {
|
||||
/* The server is (already) unknown */
|
||||
Log(LOG_WARNING,
|
||||
@ -296,27 +316,46 @@ IRC_SQUIT(CLIENT * Client, REQUEST * Req)
|
||||
return CONNECTED;
|
||||
}
|
||||
|
||||
if (Req->argv[1][0]) {
|
||||
if (strlen(Req->argv[1]) > LINE_LEN)
|
||||
Req->argv[1][LINE_LEN] = '\0';
|
||||
snprintf(msg, sizeof(msg), "%s (SQUIT from %s).", Req->argv[1],
|
||||
Client_ID(Client));
|
||||
} else
|
||||
snprintf(msg, sizeof(msg), "Got SQUIT from %s.",
|
||||
Client_ID(Client));
|
||||
con = Client_Conn(target);
|
||||
|
||||
if (Client_Conn(target) > NONE) {
|
||||
/* We are directly connected to this server */
|
||||
if (Req->argv[1][0])
|
||||
Conn_Close(Client_Conn(target), msg, Req->argv[1],
|
||||
true);
|
||||
if (Req->argv[1][0])
|
||||
if (Client_NextHop(from) != Client || con > NONE)
|
||||
snprintf(msg, sizeof(msg), "%s (SQUIT from %s)",
|
||||
Req->argv[1], Client_ID(from));
|
||||
else
|
||||
Conn_Close(Client_Conn(target), msg, NULL, true);
|
||||
return DISCONNECTED;
|
||||
strlcpy(msg, Req->argv[1], sizeof(msg));
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Got SQUIT from %s",
|
||||
Client_ID(from));
|
||||
|
||||
if (con > NONE) {
|
||||
/* We are directly connected to the target server, so we
|
||||
* have to tear down the connection and to inform all the
|
||||
* other remaining servers in the network */
|
||||
Conn_Close(con, NULL, msg, true);
|
||||
if (con == Client_Conn(Client))
|
||||
return DISCONNECTED;
|
||||
} else {
|
||||
Client_Destroy(target, msg, Req->argv[1], false);
|
||||
return CONNECTED;
|
||||
/* This server is not directly connected, so the SQUIT must
|
||||
* be forwarded ... */
|
||||
if (Client_Type(from) != CLIENT_SERVER) {
|
||||
/* The origin is not an IRC server, so don't evaluate
|
||||
* this SQUIT but simply forward it */
|
||||
IRC_WriteStrClientPrefix(Client_NextHop(target),
|
||||
from, "SQUIT %s :%s", Req->argv[0], Req->argv[1]);
|
||||
} else {
|
||||
/* SQUIT has been generated by another server, so
|
||||
* remove the target server from the network! */
|
||||
logmsg[0] = '\0';
|
||||
if (!strchr(msg, '('))
|
||||
snprintf(logmsg, sizeof(logmsg),
|
||||
"%s (SQUIT from %s)", Req->argv[1],
|
||||
Client_ID(from));
|
||||
Client_Destroy(target, logmsg[0] ? logmsg : msg,
|
||||
msg, false);
|
||||
}
|
||||
}
|
||||
return CONNECTED;
|
||||
} /* IRC_SQUIT */
|
||||
|
||||
/* -eof- */
|
||||
|
@ -92,7 +92,7 @@ static COMMAND My_Commands[] =
|
||||
{ "SERVICE", IRC_SERVICE, 0xFFFF, 0, 0, 0 },
|
||||
{ "SERVLIST", IRC_SERVLIST, CLIENT_USER, 0, 0, 0 },
|
||||
{ "SQUERY", IRC_SQUERY, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "SQUIT", IRC_SQUIT, CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "SQUIT", IRC_SQUIT, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
|
Loading…
Reference in New Issue
Block a user