X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc.c;h=ad8c0506905eca3fdaf5787914be740b7a4b9e21;hp=7dafaf0539b005bdf808dcefb870838dfae8dfcc;hb=52ccba5d1e8cd2e648cf3c14598332bde6b9910d;hpb=08f9d31d60220e8a389a2d24f42625be7749f090 diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index 7dafaf05..ad8c0506 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2015 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 @@ -16,26 +16,27 @@ * IRC commands */ -#include "imp.h" #include #include #include +#include +#include #include "ngircd.h" #include "conn-func.h" #include "conf.h" #include "channel.h" -#include "conn-encoding.h" -#include "defines.h" +#ifdef ICONV +# include "conn-encoding.h" +#endif #include "irc-macros.h" #include "irc-write.h" #include "log.h" #include "match.h" #include "messages.h" #include "parse.h" -#include "tool.h" +#include "op.h" -#include "exp.h" #include "irc.h" static char *Option_String PARAMS((CONN_ID Idx)); @@ -127,16 +128,14 @@ 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); - if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client)) - return IRC_WriteErrClient(Client, ERR_NOPRIVILEGES_MSG, - Client_ID(Client)); + if (Client_Type(Client) != CLIENT_SERVER && !Op_Check(Client, Req)) + return Op_NoPrivileges(Client, Req); /* Get prefix (origin); use the client if no prefix is given. */ if (Req->prefix) @@ -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. @@ -276,13 +224,6 @@ IRC_TRACE(CLIENT *Client, REQUEST *Req) assert(Client != NULL); assert(Req != NULL); - IRC_SetPenalty(Client, 3); - - /* Bad number of arguments? */ - if (Req->argc > 1) - return IRC_WriteErrClient(Client, ERR_NORECIPIENT_MSG, - Client_ID(Client), Req->command); - _IRC_GET_SENDER_OR_RETURN_(from, Req, Client) _IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, from) @@ -299,7 +240,7 @@ IRC_TRACE(CLIENT *Client, REQUEST *Req) PACKAGE_VERSION, Client_ID(target), Client_ID(Client_NextHop(target)), Option_String(idx2), - time(NULL) - Conn_StartTime(idx2), + (long)(time(NULL) - Conn_StartTime(idx2)), Conn_SendQ(idx), Conn_SendQ(idx2))) return DISCONNECTED; @@ -358,8 +299,6 @@ IRC_HELP(CLIENT *Client, REQUEST *Req) assert(Client != NULL); assert(Req != NULL); - IRC_SetPenalty(Client, 2); - if ((Req->argc == 0 && array_bytes(&Conf_Helptext) > 0) || (Req->argc >= 1 && strcasecmp(Req->argv[0], "Commands") != 0)) { /* Help text available and requested */ @@ -381,6 +320,85 @@ 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 = NONE, conn; + CLIENT *c; + + assert(Nick != NULL); + assert(Reason != NULL); + + /* Do we know such a client in the network? */ + c = Client_Search(Nick); + if (!c) { + LogDebug("Client with nick \"%s\" is unknown, not forwaring.", Nick); + return CONNECTED; + } + + /* Inform other servers */ + IRC_WriteStrServersPrefix(From ? Client : NULL, + From ? From : Client_ThisServer(), + "KILL %s :%s", Nick, Reason); + + 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 */ + if (Client) + 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. * @@ -460,9 +478,7 @@ Option_String(UNUSED CONN_ID Idx) #endif { static char option_txt[8]; -#ifdef ZLIB UINT16 options; -#endif assert(Idx != NONE); @@ -514,7 +530,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) Client_ID(Client), Req->command); } - if (Client_Type(Client) == CLIENT_SERVER) + if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) from = Client_Search(Req->prefix); else from = Client;