commit 4e56e5341f632827af3810e26cd59ac0c15b642b from: Alexander Barton date: Mon May 05 16:06:43 2008 UTC Implement IRC commands SERVICE, SERVLIST, and SQUERY as dummy functions SERVICE, SERVLIST, and SQUERY are required by RFC 2812 (it states in section 3 that "all commands described in this section MUST be implemented by any server for this protocol." -- So we implement them without (much) actual functionality ... commit - 3895b42d1bbcbe6537a01d7713ee18cb09632dae commit + 4e56e5341f632827af3810e26cd59ac0c15b642b blob - 490257eb20f2e456c8caa14fe7bd63a6f38db717 blob + 64807e7fec6e2367927f93b1e83c241a09e03f7b --- ChangeLog +++ ChangeLog @@ -12,6 +12,8 @@ ngIRCd-dev + - Implemented IRC commands SERVICE, SERVLIST, and SQUERY as dummy functions + to be even more RFC-compliant. Closes bug 74. - Fixed Bug 75: KICK now handles comma-delimited lists. (Brandon Beresini, Bryan Caldwell) - Fixed Bug 83: ngIRCd chokes on 1-character messages. blob - dbeed978d056cd041525ed398bbb0eb6ece7c96a blob + 93c43f6a35744f65c01ec054cec00f37d839be21 --- src/ngircd/irc-info.c +++ src/ngircd/irc-info.c @@ -267,8 +267,28 @@ IRC_LUSERS( CLIENT *Client, REQUEST *Req ) IRC_SetPenalty( target, 1 ); return CONNECTED; } /* IRC_LUSERS */ + + +/** + * List registered services. + * This function is a dummy that immediately returns RPL_SERVLISTEND. + */ +GLOBAL bool +IRC_SERVLIST(CLIENT *Client, REQUEST *Req) +{ + assert(Client != NULL); + assert(Req != NULL); + if (Req->argc > 2) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); + return IRC_WriteStrClient(Client, RPL_SERVLISTEND_MSG, Client_ID(Client), + Req->argc > 0 ? Req->argv[0] : "*", + Req->argc > 1 ? Req->argv[1] : "0"); +} /* IRC_SERVLIST */ + + GLOBAL bool IRC_MOTD( CLIENT *Client, REQUEST *Req ) { blob - faef75ad9ac37c55021bcca15ab887a5b648a5ff blob + fbebacc67d969d11617c874dcc41f22f0f58e496 --- src/ngircd/irc-info.h +++ src/ngircd/irc-info.h @@ -30,6 +30,7 @@ GLOBAL bool IRC_SUMMON PARAMS(( CLIENT *Client, REQUES GLOBAL bool IRC_TIME PARAMS(( CLIENT *Client, REQUEST *Req )); GLOBAL bool IRC_USERHOST PARAMS(( CLIENT *Client, REQUEST *Req )); GLOBAL bool IRC_USERS PARAMS(( CLIENT *Client, REQUEST *Req )); +GLOBAL bool IRC_SERVLIST PARAMS(( CLIENT *Client, REQUEST *Req )); GLOBAL bool IRC_VERSION PARAMS(( CLIENT *Client, REQUEST *Req )); GLOBAL bool IRC_WHO PARAMS(( CLIENT *Client, REQUEST *Req )); GLOBAL bool IRC_WHOIS PARAMS(( CLIENT *Client, REQUEST *Req )); blob - dd436192caa888c395572b91ea47d2aa10e30921 blob + e94b62fe00e35d01789e9382bfc533d4d0fd15d6 --- src/ngircd/irc-login.c +++ src/ngircd/irc-login.c @@ -391,8 +391,32 @@ IRC_USER( CLIENT *Client, REQUEST *Req ) } else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); } /* IRC_USER */ + + +/** + * Service registration. + * ngIRCd does not support services at the moment, so this function is a + * dummy that returns ERR_ERRONEUSNICKNAME on each call. + */ +GLOBAL bool +IRC_SERVICE(CLIENT *Client, REQUEST *Req) +{ + assert(Client != NULL); + assert(Req != NULL); + + if (Client_Type(Client) != CLIENT_GOTPASS) + return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG, + Client_ID(Client)); + if (Req->argc != 6) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); + return IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG, + Client_ID(Client), Req->argv[0]); +} /* IRC_SERVICE */ + + GLOBAL bool IRC_QUIT( CLIENT *Client, REQUEST *Req ) { blob - 28df23ea03bc6f39c0fa725ea42b2fca831c5a5a blob + 0b920380ae919808acfae0f81cdd5620c1b9e5cd --- src/ngircd/irc-login.h +++ src/ngircd/irc-login.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) * * 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 @@ -8,8 +8,6 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-login.h,v 1.6 2005/03/19 18:43:48 fw Exp $ - * * Login and logout (header) */ @@ -17,15 +15,14 @@ #ifndef __irc_login_h__ #define __irc_login_h__ +GLOBAL bool IRC_PASS PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_NICK PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_USER PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_SERVICE PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_PING PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_PONG PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_QUIT PARAMS((CLIENT *Client, REQUEST *Req)); -GLOBAL bool IRC_PASS PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_NICK PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_USER PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_PING PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_PONG PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_QUIT PARAMS((CLIENT *Client, REQUEST *Req )); - - #endif blob - 86f5852779cf682f8b41989183cfa9a256453e1a blob + 0418e7b4cb31cb82f4be6006c021c1af37c5f41a --- src/ngircd/irc.c +++ src/ngircd/irc.c @@ -37,7 +37,8 @@ static char UNUSED id[] = "$Id: irc.c,v 1.132 2008/01/ #include "irc.h" -static char *Option_String PARAMS(( CONN_ID Idx )); +static char *Option_String PARAMS((CONN_ID Idx)); +static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType)); GLOBAL bool @@ -201,49 +202,26 @@ IRC_NOTICE( CLIENT *Client, REQUEST *Req ) } /* IRC_NOTICE */ +/** + * Handler for the IRC command PRIVMSG. + */ GLOBAL bool -IRC_PRIVMSG( CLIENT *Client, REQUEST *Req ) +IRC_PRIVMSG(CLIENT *Client, REQUEST *Req) { - CLIENT *cl, *from; - CHANNEL *chan; - - assert( Client != NULL ); - assert( Req != NULL ); + return Send_Message(Client, Req, CLIENT_USER); +} /* IRC_PRIVMSG */ - /* Falsche Anzahl Parameter? */ - if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command ); - if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client )); - if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); - else from = Client; - if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - cl = Client_Search( Req->argv[0] ); - if( cl ) - { - /* Okay, Ziel ist ein Client. Aber ist es auch ein User? */ - if( Client_Type( cl ) != CLIENT_USER ) return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] ); +/** + * Handler for the IRC command SQUERY. + */ +GLOBAL bool +IRC_SQUERY(CLIENT *Client, REQUEST *Req) +{ + return Send_Message(Client, Req, CLIENT_SERVICE); +} /* IRC_SQUERY */ - /* Okay, Ziel ist ein User */ - if(( Client_Type( Client ) != CLIENT_SERVER ) && ( strchr( Client_Modes( cl ), 'a' ))) - { - /* Ziel-User ist AWAY: Meldung verschicken */ - if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( cl ), Client_Away( cl ))) return DISCONNECTED; - } - /* Text senden */ - if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from )); - return IRC_WriteStrClientPrefix( cl, from, "PRIVMSG %s :%s", Client_ID( cl ), Req->argv[1] ); - } - - chan = Channel_Search( Req->argv[0] ); - if( chan ) return Channel_Write( chan, from, Client, Req->argv[1] ); - - return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] ); -} /* IRC_PRIVMSG */ - - GLOBAL bool IRC_TRACE( CLIENT *Client, REQUEST *Req ) { @@ -351,4 +329,63 @@ Option_String( CONN_ID Idx ) } /* Option_String */ +static bool +Send_Message(CLIENT * Client, REQUEST * Req, int ForceType) +{ + CLIENT *cl, *from; + CHANNEL *chan; + + assert(Client != NULL); + assert(Req != NULL); + + if (Req->argc == 0) + return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG, + Client_ID(Client), Req->command); + if (Req->argc == 1) + return IRC_WriteStrClient(Client, ERR_NOTEXTTOSEND_MSG, + Client_ID(Client)); + if (Req->argc > 2) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); + + if (Client_Type(Client) == CLIENT_SERVER) + from = Client_Search(Req->prefix); + else + from = Client; + if (!from) + return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, + Client_ID(Client), Req->prefix); + + cl = Client_Search(Req->argv[0]); + if (cl) { + /* Target is a user, enforce type */ + if (Client_Type(cl) != ForceType) + return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, + Client_ID(from), + Req->argv[0]); + + if ((Client_Type(Client) != CLIENT_SERVER) + && (strchr(Client_Modes(cl), 'a'))) { + /* Target is away */ + if (!IRC_WriteStrClient + (from, RPL_AWAY_MSG, Client_ID(from), Client_ID(cl), + Client_Away(cl))) + return DISCONNECTED; + } + + if (Client_Conn(from) > NONE) + Conn_UpdateIdle(Client_Conn(from)); + return IRC_WriteStrClientPrefix(cl, from, "PRIVMSG %s :%s", + Client_ID(cl), Req->argv[1]); + } + + chan = Channel_Search(Req->argv[0]); + if (chan) + return Channel_Write(chan, from, Client, Req->argv[1]); + + return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG, + Client_ID(from), Req->argv[0]); +} /* Send_Message */ + + /* -eof- */ blob - a96c8e43b6c1b89b8e4f1566338c43bc658acb48 blob + 358d91ac5bc8032a0c5f1fc3809b348a51ffb142 --- src/ngircd/irc.h +++ src/ngircd/irc.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) * * 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 @@ -8,25 +8,20 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc.h,v 1.39 2005/03/19 18:43:49 fw Exp $ - * * IRC commands (header) */ - #ifndef __irc_h__ #define __irc_h__ +GLOBAL bool IRC_ERROR PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_KILL PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_NOTICE PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_PRIVMSG PARAMS((CLIENT *Client, REQUEST *Req)); +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_ERROR PARAMS(( CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_KILL PARAMS(( CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_NOTICE PARAMS(( CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_PRIVMSG PARAMS(( CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_TRACE PARAMS(( CLIENT *Client, REQUEST *Req )); -GLOBAL bool IRC_HELP PARAMS(( CLIENT *Client, REQUEST *Req )); - - #endif - /* -eof- */ blob - b8090d438e3e65fb698463b71849be67980bf0ef blob + bde1c095fc73cf0a58e356c6ddea758f326dcdab --- src/ngircd/messages.h +++ src/ngircd/messages.h @@ -32,6 +32,8 @@ #define RPL_STATSCOMMANDS_MSG "212 %s %s %ld %ld %ld" #define RPL_ENDOFSTATS_MSG "219 %s %c :End of STATS report" #define RPL_UMODEIS_MSG "221 %s +%s" +#define RPL_SERVLISTEND_MSG "235 %s %s %s :End of service listing" + #define RPL_STATSUPTIME "242 %s :Server Up %u days %u:%02u:%02u" #define RPL_LUSERCLIENT_MSG "251 %s :There are %ld users and %ld services on %ld servers" #define RPL_LUSEROP_MSG "252 %s %lu :operator(s) online" blob - 5cfeaaa8a9fa05ba1c5e81a5cf612c6bb77c23d1 blob + ef2dbbba0bc6d874f886e6a311bef9a233887d6d --- src/ngircd/parse.c +++ src/ngircd/parse.c @@ -92,6 +92,9 @@ static COMMAND My_Commands[] = { "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 }, { "RESTART", IRC_RESTART, CLIENT_USER, 0, 0, 0 }, { "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 }, + { "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 }, { "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },