From d692286d7a5a31f5ccef4f8d6b3ddee2188950ff Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Mon, 1 Aug 2011 09:07:32 +0200 Subject: IRC_MODE(), Client_Mode(): code cleanup [1/2] --- src/ngircd/irc-mode.c | 144 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 50b0db04..2cc60f46 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -50,25 +50,39 @@ static bool Send_ListChange PARAMS((const char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Mask)); +/** + * Handler for the IRC "MODE" command. + * + * See RFC 2812 section 3.1.5 ("user mode message") and section 3.2.3 + * ("channel mode message"), and RFC 2811 section 4 ("channel modes"). + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @returns CONNECTED or DISCONNECTED. + */ GLOBAL bool IRC_MODE( CLIENT *Client, REQUEST *Req ) { CLIENT *cl, *origin; CHANNEL *chan; - assert( Client != NULL ); - assert( Req != NULL ); + assert(Client != NULL); + assert(Req != NULL); /* No parameters? */ - if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); + if (Req->argc < 1) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); /* Origin for answers */ - if( Client_Type( Client ) == CLIENT_SERVER ) - { - origin = Client_Search( Req->prefix ); - if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - } - else origin = Client; + if (Client_Type(Client) == CLIENT_SERVER) { + origin = Client_Search(Req->prefix); + if (!origin) + return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, + Client_ID(Client), + Req->prefix); + } else + origin = Client; /* Channel or user mode? */ cl = NULL; chan = NULL; @@ -88,51 +102,65 @@ IRC_MODE( CLIENT *Client, REQUEST *Req ) } /* IRC_MODE */ +/** + * Handle client mode requests + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @param Origin The originator of the MODE command (prefix). + * @param Target The target (client) of this MODE command. + * @returns CONNECTED or DISCONNECTED. + */ static bool Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) { - /* Handle client mode requests */ - char the_modes[COMMAND_LEN], x[2], *mode_ptr; bool ok, set; int mode_arg; size_t len; /* Is the client allowed to request or change the modes? */ - if( Client_Type( Client ) == CLIENT_USER ) - { + if (Client_Type(Client) == CLIENT_USER) { /* Users are only allowed to manipulate their own modes! */ - if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client )); + if (Target != Client) + return IRC_WriteStrClient(Client, + ERR_USERSDONTMATCH_MSG, + Client_ID(Client)); } /* Mode request: let's answer it :-) */ - if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target )); + if (Req->argc == 1) + return IRC_WriteStrClient(Origin, RPL_UMODEIS_MSG, + Client_ID(Origin), + Client_Modes(Target)); mode_arg = 1; mode_ptr = Req->argv[mode_arg]; /* Initial state: set or unset modes? */ - if( *mode_ptr == '+' ) set = true; - else if( *mode_ptr == '-' ) set = false; - else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin )); - - /* Prepare reply string */ - if( set ) strcpy( the_modes, "+" ); - else strcpy( the_modes, "-" ); + if (*mode_ptr == '+') { + set = true; + strcpy(the_modes, "+"); + } else if (*mode_ptr == '-') { + set = false; + strcpy(the_modes, "-"); + } else + return IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG_MSG, + Client_ID(Origin)); x[1] = '\0'; ok = CONNECTED; - while( mode_ptr ) - { + while (mode_ptr) { mode_ptr++; - if( ! *mode_ptr ) - { + if (!*mode_ptr) { /* Try next argument if there's any */ mode_arg++; - if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg]; - else break; + if (mode_arg < Req->argc) + mode_ptr = Req->argv[mode_arg]; + else + break; } - + switch( *mode_ptr ) { case '+': @@ -217,49 +245,53 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) x[0] = '\0'; goto client_exit; } - if( ! ok ) break; + if (!ok) + break; /* Is there a valid mode change? */ - if( ! x[0] ) continue; - - if( set ) - { - /* Set mode */ - if( Client_ModeAdd( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes )); + if (!x[0]) + continue; + if (set) { + if (Client_ModeAdd(Target, x[0])) + strlcat(the_modes, x, sizeof(the_modes)); + } else { + if (Client_ModeDel(Target, x[0])) + strlcat(the_modes, x, sizeof(the_modes)); } - else - { - /* Unset mode */ - if( Client_ModeDel( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes )); - } } client_exit: - + /* Are there changed modes? */ - if( the_modes[1] ) - { + if (the_modes[1]) { /* Remoce needless action modifier characters */ - len = strlen( the_modes ) - 1; - if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0'; + len = strlen(the_modes) - 1; + if (the_modes[len] == '+' || the_modes[len] == '-') + the_modes[len] = '\0'; - if( Client_Type( Client ) == CLIENT_SERVER ) - { + if (Client_Type(Client) == CLIENT_SERVER) { /* Forward modes to other servers */ - IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes ); - } - else - { + IRC_WriteStrServersPrefix(Client, Origin, + "MODE %s :%s", + Client_ID(Target), + the_modes); + } else { /* Send reply to client and inform other servers */ - ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes ); - IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes ); + ok = IRC_WriteStrClientPrefix(Client, Origin, + "MODE %s :%s", + Client_ID(Target), + the_modes); + IRC_WriteStrServersPrefix(Client, Origin, + "MODE %s :%s", + Client_ID(Target), + the_modes); } LogDebug("%s \"%s\": Mode change, now \"%s\".", Client_TypeText(Target), Client_Mask(Target), Client_Modes(Target)); } - - IRC_SetPenalty( Client, 1 ); + + IRC_SetPenalty(Client, 1); return ok; } /* Client_Mode */ -- cgit 1.4.1 From 3dc3a035386789852ba5a9fbc22b9b3c2793f0b0 Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Mon, 1 Aug 2011 21:10:16 +0200 Subject: Infom clients when other servers change their user modes --- src/ngircd/irc-mode.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 2cc60f46..1222bc5c 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -271,6 +271,14 @@ client_exit: if (Client_Type(Client) == CLIENT_SERVER) { /* Forward modes to other servers */ + if (Client_Conn(Target) != NONE) { + /* Remote server (service?) changed modes + * for one of our clients. Inform it! */ + IRC_WriteStrClientPrefix(Target, Origin, + "MODE %s :%s", + Client_ID(Target), + the_modes); + } IRC_WriteStrServersPrefix(Client, Origin, "MODE %s :%s", Client_ID(Target), -- cgit 1.4.1 From ea725b99b7cc308de6a035e016e4d89e268cbf1f Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Mon, 1 Aug 2011 21:21:01 +0200 Subject: Enlarge client user mode buffer, reduce client flags buffer We have to enlage our user mode buffer, so we can handle even unknown user modes in the future; and reduce the client flags buffer, because I can't imagine why we ever would need ~100 flags!? Now we support up to 15 user modes (was: 8) and up to 15 flags (was: 99). So in the end, we even save 99-15+8-15=77 bytes for each client structure! --- src/ngircd/defines.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index 688f2d3a..8f62279d 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -44,10 +44,10 @@ see RFC 2812, section 1.2.1 */ #define CLIENT_NAME_LEN 32 /* Max. length of "real names" */ #define CLIENT_HOST_LEN 64 /* Max. host name length */ -#define CLIENT_MODE_LEN 9 /* Max. lenth of all client modes */ +#define CLIENT_MODE_LEN 16 /* Max. lenth of all client modes */ #define CLIENT_INFO_LEN 64 /* Max. length of server info texts */ #define CLIENT_AWAY_LEN 128 /* Max. length of away messages */ -#define CLIENT_FLAGS_LEN 100 /* Max. length of client flags */ +#define CLIENT_FLAGS_LEN 16 /* Max. length of client flags */ #define CHANNEL_NAME_LEN 51 /* Max. length of a channel name, see RFC 2812 section 1.3 */ -- cgit 1.4.1 From 1ed602eb47ef7c9257559209407a5b9363c532f8 Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Mon, 1 Aug 2011 21:51:31 +0200 Subject: IRC_MODE(), Client_Mode(): code cleanup [2/2] --- src/ngircd/irc-mode.c | 163 ++++++++++++++++++++++++++------------------------ 1 file changed, 86 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 1222bc5c..7861868d 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -161,90 +161,99 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) break; } - switch( *mode_ptr ) - { - case '+': - case '-': - if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set ))) - { - /* Action modifier ("+"/"-") must be changed ... */ - len = strlen( the_modes ) - 1; - if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) - { - /* Adjust last action modifier in result */ - the_modes[len] = *mode_ptr; - } - else - { - /* Append modifier character to result string */ - x[0] = *mode_ptr; - strlcat( the_modes, x, sizeof( the_modes )); - } - if( *mode_ptr == '+' ) set = true; - else set = false; + switch(*mode_ptr) { + case '+': + case '-': + if ((*mode_ptr == '+' && !set) + || (*mode_ptr == '-' && set)) { + /* Action modifier ("+"/"-") must be changed */ + len = strlen(the_modes) - 1; + if (the_modes[len] == '+' + || the_modes[len] == '-') { + /* Last character in the "result + * string" was an "action", so just + * overwrite it with the new action */ + the_modes[len] = *mode_ptr; + } else { + /* Append new modifier character to + * the resulting mode string */ + x[0] = *mode_ptr; + strlcat(the_modes, x, + sizeof(the_modes)); } - continue; + if (*mode_ptr == '+') + set = true; + else + set = false; + } + continue; } - + /* Validate modes */ x[0] = '\0'; - switch( *mode_ptr ) - { - case 'i': /* Invisible */ - case 's': /* Server messages */ - case 'w': /* Wallops messages */ - x[0] = *mode_ptr; - break; - - case 'a': /* Away */ - if( Client_Type( Client ) == CLIENT_SERVER ) - { - x[0] = 'a'; - Client_SetAway( Origin, DEFAULT_AWAY_MSG ); - } - else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin )); - break; - - case 'c': /* Receive connect notices - * (only settable by IRC operators!) */ - if(!set || Client_OperByMe(Origin) - || Client_Type(Client) == CLIENT_SERVER) - x[0] = 'c'; - else - ok = IRC_WriteStrClient(Origin, + switch (*mode_ptr) { + case 'i': /* Invisible */ + case 's': /* Server messages */ + case 'w': /* Wallops messages */ + x[0] = *mode_ptr; + break; + case 'a': /* Away */ + if (Client_Type(Client) == CLIENT_SERVER) { + x[0] = 'a'; + Client_SetAway(Origin, DEFAULT_AWAY_MSG); + } else + ok = IRC_WriteStrClient(Origin, ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); - break; - - case 'o': /* IRC operator (only unsettable!) */ - if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER )) - { - Client_SetOperByMe( Target, false ); - x[0] = 'o'; - } - else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin )); - break; - - case 'r': /* Restricted (only settable) */ - if(( set ) || ( Client_Type( Client ) == CLIENT_SERVER )) x[0] = 'r'; - else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin )); - break; - - case 'x': /* Cloak hostname */ - if (Client_HasMode(Client, 'r')) - ok = IRC_WriteStrClient(Origin, - ERR_RESTRICTED_MSG, - Client_ID(Origin)); - else - x[0] = 'x'; - break; - - default: - Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin )); - if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr ); - x[0] = '\0'; - goto client_exit; + break; + case 'c': /* Receive connect notices + * (only settable by IRC operators!) */ + if (!set || Client_Type(Client) == CLIENT_SERVER + || Client_OperByMe(Origin)) + x[0] = 'c'; + else + ok = IRC_WriteStrClient(Origin, + ERR_NOPRIVILEGES_MSG, + Client_ID(Origin)); + break; + case 'o': /* IRC operator (only unsettable!) */ + if (!set || Client_Type(Client) == CLIENT_SERVER) { + Client_SetOperByMe(Target, false); + x[0] = 'o'; + } else + ok = IRC_WriteStrClient(Origin, + ERR_NOPRIVILEGES_MSG, + Client_ID(Origin)); + break; + case 'r': /* Restricted (only settable) */ + if (set || Client_Type(Client) == CLIENT_SERVER) + x[0] = 'r'; + else + ok = IRC_WriteStrClient(Origin, + ERR_RESTRICTED_MSG, + Client_ID(Origin)); + break; + case 'x': /* Cloak hostname */ + if (Client_HasMode(Client, 'r')) + ok = IRC_WriteStrClient(Origin, + ERR_RESTRICTED_MSG, + Client_ID(Origin)); + else + x[0] = 'x'; + break; + default: + Log(LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", + set ? '+' : '-', *mode_ptr, Client_ID(Origin)); + if (Client_Type(Client) != CLIENT_SERVER) + ok = IRC_WriteStrClient(Origin, + ERR_UMODEUNKNOWNFLAG2_MSG, + Client_ID(Origin), + set ? '+' : '-', + *mode_ptr); + x[0] = '\0'; + goto client_exit; } + if (!ok) break; -- cgit 1.4.1 From 2dfa24d2fa42bdfece472da57c823a3968230fae Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Mon, 1 Aug 2011 22:09:40 +0200 Subject: Handle unknown user modes on server links --- src/ngircd/irc-mode.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 7861868d..b469a169 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -242,16 +242,25 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) x[0] = 'x'; break; default: - Log(LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", - set ? '+' : '-', *mode_ptr, Client_ID(Origin)); - if (Client_Type(Client) != CLIENT_SERVER) + if (Client_Type(Client) != CLIENT_SERVER) { + Log(LOG_DEBUG, + "Unknown mode \"%c%c\" from \"%s\"!?", + set ? '+' : '-', *mode_ptr, + Client_ID(Origin)); ok = IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID(Origin), set ? '+' : '-', *mode_ptr); - x[0] = '\0'; - goto client_exit; + x[0] = '\0'; + goto client_exit; + } else { + Log(LOG_DEBUG, + "Handling unknown mode \"%c%c\" from \"%s\" for \"%s\" ...", + set ? '+' : '-', *mode_ptr, + Client_ID(Origin), Client_ID(Target)); + x[0] = *mode_ptr; + } } if (!ok) -- cgit 1.4.1 From 2fd42667c2a064bab6e28523a7e68383604a1e15 Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Mon, 1 Aug 2011 22:30:00 +0200 Subject: Handle unknown channel modes on server links --- src/ngircd/irc-mode.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index b469a169..326c1046 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -650,18 +650,25 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) } break; default: - Log(LOG_DEBUG, - "Unknown mode \"%c%c\" from \"%s\" on %s!?", - set ? '+' : '-', *mode_ptr, Client_ID(Origin), - Channel_Name(Channel)); - if (Client_Type(Client) != CLIENT_SERVER) + if (Client_Type(Client) != CLIENT_SERVER) { + Log(LOG_DEBUG, + "Unknown mode \"%c%c\" from \"%s\" on %s!?", + set ? '+' : '-', *mode_ptr, + Client_ID(Origin), Channel_Name(Channel)); connected = IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID(Origin), set ? '+' : '-', *mode_ptr); - x[0] = '\0'; - goto chan_exit; - } /* switch() */ + x[0] = '\0'; + goto chan_exit; + } else { + Log(LOG_DEBUG, + "Handling unknown mode \"%c%c\" from \"%s\" on %s ...", + set ? '+' : '-', *mode_ptr, + Client_ID(Origin), Channel_Name(Channel)); + x[0] = *mode_ptr; + } + } if (!connected) break; -- cgit 1.4.1 From 989c9fa531d83c9b1a302b222a4bcfeef767c2b6 Mon Sep 17 00:00:00 2001 From: Alexander Barton Date: Mon, 1 Aug 2011 23:30:55 +0200 Subject: Handle channel user modes 'a', 'h', and 'q' from remote servers These channel user modes aren't used for anything at the moment, but ngIRCd knows that these three modes are "channel user modes" and not "channel modes", that is that these modes take an "nick name" argument. Like unknown user and channel modes, these modes are saved and forwarded, but ignored otherwise. --- src/ngircd/irc-mode.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 326c1046..3cceaeb8 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -594,6 +594,16 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) Channel_Name(Channel)); break; /* --- Channel user modes --- */ + case 'a': + case 'h': + case 'q': + if (Client_Type(Client) != CLIENT_SERVER) { + connected = IRC_WriteStrClient(Origin, + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), + Channel_Name(Channel)); + goto chan_exit; + } case 'o': /* Channel operator */ case 'v': /* Voice */ if (arg_arg > mode_arg) { -- cgit 1.4.1