X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc-info.c;h=54f83170e3bceea94828acb1baf83de868a43261;hp=092ca0a3957dd2896ce6d01fafa4efb91fcbab07;hb=48326e061aacd954e24f76c53ded10448cbc28eb;hpb=af13732ec7bb09c9e1bc942a355990ab2767eca7 diff --git a/src/ngircd/irc-info.c b/src/ngircd/irc-info.c index 092ca0a3..54f83170 100644 --- a/src/ngircd/irc-info.c +++ b/src/ngircd/irc-info.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2012 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 @@ -37,7 +37,9 @@ #include "match.h" #include "tool.h" #include "parse.h" +#include "irc.h" #include "irc-write.h" +#include "client-cap.h" #include "exp.h" #include "irc-info.h" @@ -115,7 +117,7 @@ IRC_INFO(CLIENT * Client, REQUEST * Req) target = Client_Search(Req->argv[0]); else target = Client_ThisServer(); - + /* Make sure that the target is a server */ if (target && Client_Type(target) != CLIENT_SERVER) target = Client_Introducer(target); @@ -200,51 +202,74 @@ IRC_ISON( CLIENT *Client, REQUEST *Req ) } /* IRC_ISON */ +/** + * Handler for the IRC "LINKS" command. + * + * See RFC 2812, 3.4.5 "Links message". + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @return CONNECTED or DISCONNECTED. + */ GLOBAL bool -IRC_LINKS( CLIENT *Client, REQUEST *Req ) +IRC_LINKS(CLIENT *Client, REQUEST *Req) { CLIENT *target, *from, *c; char *mask; - assert( Client != NULL ); - assert( Req != NULL ); + assert(Client != NULL); + assert(Req != NULL); - if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); + IRC_SetPenalty(Client, 1); - /* Server-Mask ermitteln */ - if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1]; - else mask = "*"; + if (Req->argc > 2) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); - /* Absender ermitteln */ - 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 ); + /* Get pointer to server mask or "*", if none given */ + if (Req->argc > 0) + mask = Req->argv[Req->argc - 1]; + else + mask = "*"; - /* An anderen Server forwarden? */ - if( Req->argc == 2 ) - { - target = Client_Search( Req->argv[0] ); - if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] ); - else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] ); - } + 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); - /* Wer ist der Absender? */ - if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix ); - else target = Client; - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); + /* Forward? */ + if (Req->argc == 2) { + target = Client_Search(Req->argv[0]); + if (! target || Client_Type(target) != CLIENT_SERVER) + return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG, + Client_ID(from), + Req->argv[0] ); + else + if (target != Client_ThisServer()) + return IRC_WriteStrClientPrefix(target, from, + "LINKS %s %s", Req->argv[0], + Req->argv[1]); + } - c = Client_First( ); - while( c ) - { - if( Client_Type( c ) == CLIENT_SERVER ) - { - if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_TopServer( c ) ? Client_TopServer( c ) : Client_ThisServer( )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED; + c = Client_First(); + while (c) { + if (Client_Type(c) == CLIENT_SERVER + && MatchCaseInsensitive(mask, Client_ID(c))) { + if (!IRC_WriteStrClient(from, RPL_LINKS_MSG, + Client_ID(from), Client_ID(c), + Client_ID(Client_TopServer(c) + ? Client_TopServer(c) + : Client_ThisServer()), + Client_Hops(c), Client_Info(c))) + return DISCONNECTED; } - c = Client_Next( c ); + c = Client_Next(c); } - - IRC_SetPenalty( target, 1 ); - return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask ); + return IRC_WriteStrClient(from, RPL_ENDOFLINKS_MSG, + Client_ID(from), mask); } /* IRC_LINKS */ @@ -624,10 +649,10 @@ IRC_STATS( CLIENT *Client, REQUEST *Req ) * therefore answers with ERR_SUMMONDISABLED. */ GLOBAL bool -IRC_SUMMON(CLIENT * Client, REQUEST * Req) +IRC_SUMMON(CLIENT * Client, UNUSED REQUEST * Req) { return IRC_WriteStrClient(Client, ERR_SUMMONDISABLED_MSG, - Client_ID(Client), Req->command); + Client_ID(Client)); } /* IRC_SUMMON */ @@ -717,10 +742,10 @@ IRC_USERHOST(CLIENT *Client, REQUEST *Req) * See RFC 2812 section 4.6. As suggested there the command is disabled. */ GLOBAL bool -IRC_USERS(CLIENT * Client, REQUEST * Req) +IRC_USERS(CLIENT * Client, UNUSED REQUEST * Req) { return IRC_WriteStrClient(Client, ERR_USERSDISABLED_MSG, - Client_ID(Client), Req->command); + Client_ID(Client)); } /* IRC_USERS */ @@ -782,14 +807,48 @@ who_flags_status(const char *client_modes) } -static const char * -who_flags_qualifier(const char *chan_user_modes) +/** + * Return channel user mode prefix(es). + * + * @param Client The client requesting the mode prefixes. + * @param chan_user_modes String with channel user modes. + * @param str String buffer to which the prefix(es) will be appended. + * @param len Size of "str" buffer. + * @return Pointer to "str". + */ +static char * +who_flags_qualifier(CLIENT *Client, const char *chan_user_modes, + char *str, size_t len) { - if (strchr(chan_user_modes, 'o')) - return "@"; + assert(Client != NULL); + + if (Client_Cap(Client) & CLIENT_CAP_MULTI_PREFIX) { + if (strchr(chan_user_modes, 'q')) + strlcat(str, "~", len); + if (strchr(chan_user_modes, 'a')) + strlcat(str, "&", len); + if (strchr(chan_user_modes, 'o')) + strlcat(str, "@", len); + if (strchr(chan_user_modes, 'h')) + strlcat(str, "%", len); + if (strchr(chan_user_modes, 'v')) + strlcat(str, "+", len); + + return str; + } + + if (strchr(chan_user_modes, 'q')) + strlcat(str, "~", len); + else if (strchr(chan_user_modes, 'a')) + strlcat(str, "&", len); + else if (strchr(chan_user_modes, 'o')) + strlcat(str, "@", len); + else if (strchr(chan_user_modes, 'h')) + strlcat(str, "%", len); else if (strchr(chan_user_modes, 'v')) - return "+"; - return ""; + strlcat(str, "+", len); + + return str; } @@ -807,13 +866,15 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) bool is_visible, is_member, is_ircop; CL2CHAN *cl2chan; const char *client_modes; - const char *chan_user_modes; - char flags[8]; + char flags[10]; CLIENT *c; + int count = 0; assert( Client != NULL ); assert( Chan != NULL ); + IRC_SetPenalty(Client, 1); + is_member = Channel_IsMemberOf(Chan, Client); /* Secret channel? */ @@ -836,15 +897,20 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) if (is_ircop) strlcat(flags, "*", sizeof(flags)); - chan_user_modes = Channel_UserModes(Chan, c); - strlcat(flags, who_flags_qualifier(chan_user_modes), - sizeof(flags)); + who_flags_qualifier(Client, Channel_UserModes(Chan, c), + flags, sizeof(flags)); if (!write_whoreply(Client, c, Channel_Name(Chan), flags)) return DISCONNECTED; + count++; } } + + /* If there are a lot of clients, augment penalty a bit */ + if (count > MAX_RPL_WHO) + IRC_SetPenalty(Client, 1); + return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan)); } @@ -866,12 +932,14 @@ IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps) CHANNEL *chan; bool client_match, is_visible; char flags[4]; + int count = 0; assert (Client != NULL); if (Mask) ngt_LowerStr(Mask); + IRC_SetPenalty(Client, 3); for (c = Client_First(); c != NULL; c = Client_Next(c)) { if (Client_Type(c) != CLIENT_USER) continue; @@ -916,13 +984,16 @@ IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps) if (!is_visible) /* target user is not visible */ continue; + if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO")) + break; + strcpy(flags, who_flags_status(Client_Modes(c))); if (strchr(Client_Modes(c), 'o')) strlcat(flags, "*", sizeof(flags)); if (!write_whoreply(Client, c, "*", flags)) return DISCONNECTED; - + count++; } return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), @@ -972,13 +1043,11 @@ IRC_WHO(CLIENT *Client, REQUEST *Req) chan = Channel_Search(Req->argv[0]); if (chan) { /* Members of a channel have been requested */ - IRC_SetPenalty(Client, 1); return IRC_WHO_Channel(Client, chan, only_ops); } if (strcmp(Req->argv[0], "0") != 0) { /* A mask has been given. But please note this RFC * stupidity: "0" is same as no arguments ... */ - IRC_SetPenalty(Client, 3); return IRC_WHO_Mask(Client, Req->argv[0], only_ops); } } @@ -992,10 +1061,10 @@ IRC_WHO(CLIENT *Client, REQUEST *Req) /** * Generate WHOIS reply of one actual client. * - * @param Client The client from which this command has been received. - * @param from The client requesting the information ("originator"). - * @param c The client of which information should be returned. - * @returns CONNECTED or DISCONNECTED. + * @param Client The client from which this command has been received. + * @param from The client requesting the information ("originator"). + * @param c The client of which information should be returned. + * @return CONNECTED or DISCONNECTED. */ static bool IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) @@ -1004,6 +1073,10 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) CL2CHAN *cl2chan; CHANNEL *chan; + assert(Client != NULL); + assert(from != NULL); + assert(c != NULL); + /* Nick, user, hostname and client info */ if (!IRC_WriteStrClient(from, RPL_WHOISUSER_MSG, Client_ID(from), Client_ID(c), Client_User(c), @@ -1041,8 +1114,8 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) if (str[strlen(str) - 1] != ':') strlcat(str, " ", sizeof(str)); - strlcat(str, who_flags_qualifier(Channel_UserModes(chan, c)), - sizeof(str)); + who_flags_qualifier(Client, Channel_UserModes(chan, c), + str, sizeof(str)); strlcat(str, Channel_Name(chan), sizeof(str)); if (strlen(str) > (LINE_LEN - CHANNEL_NAME_LEN - 4)) { @@ -1061,33 +1134,57 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) /* IRC-Operator? */ if (Client_HasMode(c, 'o') && - !IRC_WriteStrClient(from, RPL_WHOISOPERATOR_MSG, - Client_ID(from), Client_ID(c))) - return DISCONNECTED; + !IRC_WriteStrClient(from, RPL_WHOISOPERATOR_MSG, + Client_ID(from), Client_ID(c))) + return DISCONNECTED; + + /* IRC-Bot? */ + if (Client_HasMode(c, 'B') && + !IRC_WriteStrClient(from, RPL_WHOISBOT_MSG, + Client_ID(from), Client_ID(c))) + return DISCONNECTED; /* Connected using SSL? */ if (Conn_UsesSSL(Client_Conn(c)) && - !IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, - Client_ID(from), Client_ID(c))) + !IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from), + Client_ID(c))) + return DISCONNECTED; + + /* Registered nickname? */ + if (Client_HasMode(c, 'R') && + !IRC_WriteStrClient(from, RPL_WHOISREGNICK_MSG, + Client_ID(from), Client_ID(c))) + return DISCONNECTED; + + /* Local client and requester is the user itself or an IRC Op? */ + if (Client_Conn(c) > NONE && + (from == c || (!Conf_MorePrivacy && Client_HasMode(from, 'o')))) { + /* Client hostname */ + if (!IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, + Client_ID(from), Client_ID(c), Client_Hostname(c), + Conn_GetIPAInfo(Client_Conn(c)))) + return DISCONNECTED; + /* Client modes */ + if (!IRC_WriteStrClient(from, RPL_WHOISMODES_MSG, + Client_ID(from), Client_ID(c), Client_Modes(c))) return DISCONNECTED; + } /* Idle and signon time (local clients only!) */ if (!Conf_MorePrivacy && Client_Conn(c) > NONE && - !IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG, - Client_ID(from), Client_ID(c), - (unsigned long)Conn_GetIdle(Client_Conn(c)), - (unsigned long)Conn_GetSignon(Client_Conn(c)))) - return DISCONNECTED; + !IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG, + Client_ID(from), Client_ID(c), + (unsigned long)Conn_GetIdle(Client_Conn(c)), + (unsigned long)Conn_GetSignon(Client_Conn(c)))) + return DISCONNECTED; /* Away? */ if (Client_HasMode(c, 'a') && - !IRC_WriteStrClient(from, RPL_AWAY_MSG, - Client_ID(from), Client_ID(c), - Client_Away(c))) - return DISCONNECTED; + !IRC_WriteStrClient(from, RPL_AWAY_MSG, + Client_ID(from), Client_ID(c), Client_Away(c))) + return DISCONNECTED; - return IRC_WriteStrClient(from, RPL_ENDOFWHOIS_MSG, - Client_ID(from), Client_ID(c)); + return CONNECTED; } /* IRC_WHOIS_SendReply */ @@ -1107,7 +1204,7 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) unsigned int match_count = 0, found = 0; bool has_wildcards, is_remote; bool got_wildcard = false; - const char *query; + char mask[COMMAND_LEN], *query; assert( Client != NULL ); assert( Req != NULL ); @@ -1131,7 +1228,7 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) /* Get target server for this command */ if (Req->argc > 1) { /* Search the target server, which can be specified as a - * nick name on that server as well: */ + * nickname on that server as well: */ target = Client_Search(Req->argv[0]); if (!target) return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG, @@ -1148,7 +1245,8 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) Req->argv[0], Req->argv[1]); is_remote = Client_Conn(from) < 0; - for (query = strtok(Req->argv[Req->argc - 1], ","); + strlcpy(mask, Req->argv[Req->argc - 1], sizeof(mask)); + for (query = strtok(ngt_LowerStr(mask), ","); query && found < 3; query = strtok(NULL, ","), found++) { @@ -1159,11 +1257,11 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) * - no wildcards for remote clients * - only one wildcard target per local client * - * also, at most ten matches are returned. + * Also, at most MAX_RPL_WHOIS matches are returned. */ if (!has_wildcards || is_remote) { c = Client_Search(query); - if (c) { + if (c && Client_Type(c) == CLIENT_USER) { if (!IRC_WHOIS_SendReply(Client, from, c)) return DISCONNECTED; } else { @@ -1185,21 +1283,28 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) got_wildcard = true; IRC_SetPenalty(Client, 3); - for (c = Client_First(); c && match_count < 10; c = Client_Next(c)) { + for (c = Client_First(); c; c = Client_Next(c)) { + if (IRC_CheckListTooBig(Client, match_count, + MAX_RPL_WHOIS, "WHOIS")) + break; + if (Client_Type(c) != CLIENT_USER) continue; if (!MatchCaseInsensitive(query, Client_ID(c))) continue; if (!IRC_WHOIS_SendReply(Client, from, c)) return DISCONNECTED; + match_count++; } if (match_count == 0) - return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, - Client_ID(Client), Req->argv[Req->argc - 1]); + IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, + Client_ID(Client), + Req->argv[Req->argc - 1]); } - return CONNECTED; + return IRC_WriteStrClient(from, RPL_ENDOFWHOIS_MSG, + Client_ID(from), Req->argv[Req->argc - 1]); } /* IRC_WHOIS */ @@ -1281,11 +1386,11 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req ) if (last < 0) last = 0; - max = DEFAULT_WHOWAS; + max = DEF_RPL_WHOWAS; if (Req->argc > 1) { max = atoi(Req->argv[1]); if (max < 1) - max = MAX_WHOWAS; + max = MAX_RPL_WHOWAS; } /* @@ -1392,7 +1497,7 @@ IRC_Send_LUSERS(CLIENT *Client) Conn_CountMax(), Conn_CountAccepted())) return DISCONNECTED; #endif - + return CONNECTED; } /* IRC_Send_LUSERS */ @@ -1413,7 +1518,15 @@ Show_MOTD_Sendline(CLIENT *Client, const char *msg) static bool Show_MOTD_End(CLIENT *Client) { - return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client )); + if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client))) + return DISCONNECTED; + + if (*Conf_CloakHost) + return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG, + Client_ID(Client), + Client_Hostname(Client)); + + return CONNECTED; } #ifdef SSL_SUPPORT @@ -1469,60 +1582,70 @@ IRC_Show_MOTD( CLIENT *Client ) } /* IRC_Show_MOTD */ +/** + * Send NAMES reply for a specific client and channel. + * + * @param Client The client requesting the NAMES information. + * @param Chan The channel + * @return CONNECTED or DISCONNECTED. + */ GLOBAL bool -IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan ) +IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan) { bool is_visible, is_member; char str[LINE_LEN + 1]; CL2CHAN *cl2chan; CLIENT *cl; - assert( Client != NULL ); - assert( Chan != NULL ); + assert(Client != NULL); + assert(Chan != NULL); - if( Channel_IsMemberOf( Chan, Client )) is_member = true; - else is_member = false; + if (Channel_IsMemberOf(Chan, Client)) + is_member = true; + else + is_member = false; /* Do not print info on channel memberships to anyone that is not member? */ if (Conf_MorePrivacy && !is_member) return CONNECTED; /* Secret channel? */ - if( ! is_member && strchr( Channel_Modes( Chan ), 's' )) return CONNECTED; + if (!is_member && strchr(Channel_Modes(Chan), 's')) + return CONNECTED; - /* Alle Mitglieder suchen */ - snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan )); - cl2chan = Channel_FirstMember( Chan ); - while( cl2chan ) - { - cl = Channel_GetClient( cl2chan ); + snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, Client_ID(Client), "=", + Channel_Name(Chan)); + cl2chan = Channel_FirstMember(Chan); + while (cl2chan) { + cl = Channel_GetClient(cl2chan); - if( strchr( Client_Modes( cl ), 'i' )) is_visible = false; - else is_visible = true; + if (strchr(Client_Modes(cl), 'i')) + is_visible = false; + else + is_visible = true; - if( is_member || is_visible ) - { - /* Nick anhaengen */ - if( str[strlen( str ) - 1] != ':' ) strlcat( str, " ", sizeof( str )); - if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strlcat( str, "@", sizeof( str )); - else if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strlcat( str, "+", sizeof( str )); - strlcat( str, Client_ID( cl ), sizeof( str )); + if (is_member || is_visible) { + if (str[strlen(str) - 1] != ':') + strlcat(str, " ", sizeof(str)); - if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 )) - { - /* Zeile wird zu lang: senden! */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan )); + who_flags_qualifier(Client, Channel_UserModes(Chan, cl), + str, sizeof(str)); + strlcat(str, Client_ID(cl), sizeof(str)); + + if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 4)) { + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; + snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, + Client_ID(Client), "=", + Channel_Name(Chan)); } } - /* naechstes Mitglied suchen */ - cl2chan = Channel_NextMember( Chan, cl2chan ); + cl2chan = Channel_NextMember(Chan, cl2chan); } - if( str[strlen( str ) - 1] != ':') - { - /* Es sind noch Daten da, die gesendet werden muessen */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; + if (str[strlen(str) - 1] != ':') { + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; } return CONNECTED; @@ -1543,7 +1666,8 @@ IRC_Send_ISUPPORT(CLIENT * Client) return IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client), CHANNEL_NAME_LEN - 1, Conf_MaxNickLength - 1, COMMAND_LEN - 23, CLIENT_AWAY_LEN - 1, - COMMAND_LEN - 113); + COMMAND_LEN - 113, MAX_HNDL_MODES_ARG, + MAX_HNDL_CHANNEL_LISTS); } /* IRC_Send_ISUPPORT */