From: Alexander Barton Date: Wed, 21 Nov 2007 12:16:33 +0000 (+0000) Subject: Introduce option to configure the maximum nick name lenth in ngircd.conf X-Git-Tag: rel-0-11-0-pre2~17 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=commitdiff_plain;h=47ca178a219d682c589b27e64ee1a4e936cc7bdc Introduce option to configure the maximum nick name lenth in ngircd.conf - New configuration option "MaxNickLength" to specify the allowed maximum length of user nick names. Note: must be unique in an IRC network! - Enhanced the IRC+ protocol to support an enhanced "server handshake" and enable server to recognice numeric 005 (ISUPPORT) and 376 (ENDOFMOTD). See doc/Protocol.txt for details. --- diff --git a/ChangeLog b/ChangeLog index fbc51766..d39fbd51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,11 @@ ngIRCd HEAD + - New configuration option "MaxNickLength" to specify the allowed maximum + length of user nick names. Note: must be unique in an IRC network! + - Enhanced the IRC+ protocol to support an enhanced "server handshake" and + enable server to recognice numeric 005 (ISUPPORT) and 376 (ENDOFMOTD). + See doc/Protocol.txt for details. - Re-added doc/SSL.txt to distribution -- got lost somewhere!? - Fixes the wrong logging output when nested servers are introduced to the network as well as the wrong output of the LINKS command. @@ -713,4 +718,4 @@ ngIRCd 0.0.1, 31.12.2001 -- -$Id: ChangeLog,v 1.328 2007/11/20 21:39:35 alex Exp $ +$Id: ChangeLog,v 1.329 2007/11/21 12:16:33 alex Exp $ diff --git a/NEWS b/NEWS index 2591b230..a604926b 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ ngIRCd HEAD + - New configuration option "MaxNickLength" to specify the allowed maximum + length of user nick names. Note: must be unique in an IRC network! - Numeric 317: implemented "signon time" (displayed in WHOIS result). - Added new server configuration option "Passive" for "Server" blocks to disable automatic outgoing connections (similar to -p option to ngircd, @@ -246,4 +248,4 @@ ngIRCd 0.0.1, 31.12.2001 -- -$Id: NEWS,v 1.81 2007/10/14 14:17:32 alex Exp $ +$Id: NEWS,v 1.82 2007/11/21 12:16:33 alex Exp $ diff --git a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj index 1ca7140d..1a032a79 100644 --- a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj +++ b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ FA322D4D0CEF74B1001761B3 /* resolve.c in Sources */ = {isa = PBXBuildFile; fileRef = FA322D0C0CEF74B1001761B3 /* resolve.c */; }; FA322DBE0CEF7766001761B3 /* tool.c in Sources */ = {isa = PBXBuildFile; fileRef = FA322D330CEF74B1001761B3 /* tool.c */; }; FA322DC10CEF77CB001761B3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FA322DC00CEF77CB001761B3 /* libz.dylib */; }; + FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */ = {isa = PBXBuildFile; fileRef = FAE5CC2D0CF2308A007D69B6 /* numeric.c */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -198,6 +199,8 @@ FA322DB10CEF7565001761B3 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; FA322DBB0CEF773C001761B3 /* cvs-version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "cvs-version.h"; sourceTree = ""; }; FA322DC00CEF77CB001761B3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; + FAE5CC2C0CF2308A007D69B6 /* numeric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = numeric.h; sourceTree = ""; }; + FAE5CC2D0CF2308A007D69B6 /* numeric.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = numeric.c; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -309,6 +312,8 @@ FA322D050CEF74B1001761B3 /* messages.h */, FA322D060CEF74B1001761B3 /* ngircd.c */, FA322D070CEF74B1001761B3 /* ngircd.h */, + FAE5CC2D0CF2308A007D69B6 /* numeric.c */, + FAE5CC2C0CF2308A007D69B6 /* numeric.h */, FA322D080CEF74B1001761B3 /* parse.c */, FA322D090CEF74B1001761B3 /* parse.h */, FA322D0A0CEF74B1001761B3 /* rendezvous.c */, @@ -622,6 +627,7 @@ FA322D4C0CEF74B1001761B3 /* rendezvous.c in Sources */, FA322D4D0CEF74B1001761B3 /* resolve.c in Sources */, FA322DBE0CEF7766001761B3 /* tool.c in Sources */, + FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/doc/Protocol.txt b/doc/Protocol.txt index 14da8475..c81143e3 100644 --- a/doc/Protocol.txt +++ b/doc/Protocol.txt @@ -1,7 +1,7 @@ ngIRCd - Next Generation IRC Server - (c)2001-2003 by Alexander Barton, + (c)2001-2007 Alexander Barton, alex@barton.de, http://www.barton.de/ ngIRCd is free software and published under the @@ -79,6 +79,9 @@ The following are defined at the moment: peer understands this flag, it will send "MODE +I" and "MODE +b" commands after the server link has been established. +- H: The server supports the "enhanced server handshake", see section II.2 + for a detailed description. + - o: IRC operators are allowed to change channel- and channel-user-modes even if they aren't channel-operator of the affected channel. @@ -90,7 +93,50 @@ The optional parameter is used to propagate server options as defined in RFC 2813, section 4.1.1. -II.2 Exchange channel-modes, topics, and persistent channels +II.2 Enhanced Server Handshake + +The "enhanced server handshake" is used when both servers support this IRC+ +extension, which is indicated by the 'H' flag in the sent with +the PASS command, see section II.1. + +It basically means, that after exchanging the PASS and SERVER commands the +server is not registered in the network (as usual), but that IRC numerics +are exchanged until the numeric 376 (ENDOFMOTD) is received. Afterwards the +peer is registered in the network as with the regular IRC protocol. + +A server implementing the enhanced server handshake (and indicating this +using 'H' in the ) MUST ignore all unknown numerics to it +silently. + +In addition, such a server should at least send the numeric 005 (ISUPPORT) +to its peer, containing the following information. Syntax: =, +one token per IRC parameter. If the server has to send more than 12 token +it must send separate ISUPPORT numerics (this is a limitation of the IRC +protocol which allows at max 15 arguments per command). + + - NICKLEN: Maximum nickname length. Default: 9. + - CASEMAPPING: Case mapping used for nick- and channel name comparing. + Default: "ascii", the chars [a-z] are lowercase of [A-Z]. + - PREFIX: List of channel modes a person can get and the respective prefix + a channel or nickname will get in case the person has it. The order of the + modes goes from most powerful to least powerful. Default: "(ov)@+" + - CHANTYPES: Supported channel prefixes. Default: "#". + - CHANMODES: List of channel modes for 4 types, separated by comma (","): + Mode that adds or removes a nick or address to a list, mode that changes + a setting (both have always has a parameter), mode that changes a setting + and only has a parameter when set, and mode that changes a setting and + never has a parameter. For example "bI,k,l,imnPst". + - CHANLIMIT: Maximum number of channels allowed to join by channel prefix, + for example "#:10". + +Please see for details. + +The information exchanged using ISUPPORT can be used to detect configuration +incompatibilities (different maximum nick name length, for example) and +therefore to disconnect the peer prior to registering it in the network. + + +II.3 Exchange channel-modes, topics, and persistent channels Command: CHANINFO Parameters: + [] @@ -115,4 +161,4 @@ channel mode). In this case should be "0". -- -$Id: Protocol.txt,v 1.13 2005/08/27 19:00:06 alex Exp $ +$Id: Protocol.txt,v 1.14 2007/11/21 12:16:35 alex Exp $ diff --git a/doc/sample-ngircd.conf b/doc/sample-ngircd.conf index e17b0e60..924f0595 100644 --- a/doc/sample-ngircd.conf +++ b/doc/sample-ngircd.conf @@ -1,4 +1,4 @@ -# $Id: sample-ngircd.conf,v 1.41 2007/10/13 20:45:11 fw Exp $ +# $Id: sample-ngircd.conf,v 1.42 2007/11/21 12:16:35 alex Exp $ # # This is a sample configuration file for the ngIRCd, which must be adepted @@ -111,6 +111,11 @@ # Maximum number of channels a user can be member of (0: no limit): ;MaxJoins = 10 + # Maximum length of an user nick name (Default: 9, as in RFC 2812). + # Please note that all servers in an IRC network MUST use the same + # maximum nick name length! + ;MaxNickLength = 9 + [Operator] # [Operator] sections are used to define IRC Operators. There may be # more than one [Operator] block, one for each local operator. diff --git a/man/ngircd.conf.5.tmpl b/man/ngircd.conf.5.tmpl index 83219009..457a162c 100644 --- a/man/ngircd.conf.5.tmpl +++ b/man/ngircd.conf.5.tmpl @@ -1,5 +1,5 @@ .\" -.\" $Id: ngircd.conf.5.tmpl,v 1.5 2007/10/25 11:01:19 fw Exp $ +.\" $Id: ngircd.conf.5.tmpl,v 1.6 2007/11/21 12:16:36 alex Exp $ .\" .TH ngircd.conf 5 "August 2005" ngircd "ngIRCd Manual" .SH NAME @@ -170,6 +170,11 @@ the risk of denial of service attacks (DoS). Default: 5. \fBMaxJoins\fR Maximum number of channels a user can be member of (0: no limit). Default: 10. +.TP +\fBMaxNickLength\fR +Maximum length of an user nick name (Default: 9, as in RFC 2812). Please +note that all servers in an IRC network MUST use the same maximum nick name +length! .SH [OPERATOR] .I [Operator] sections are used to define IRC Operators. There may be more than one diff --git a/src/ngircd/Makefile.am b/src/ngircd/Makefile.am index 52bd1615..46513a8a 100644 --- a/src/ngircd/Makefile.am +++ b/src/ngircd/Makefile.am @@ -8,7 +8,7 @@ # (at your option) any later version. # Please read the file COPYING, README and AUTHORS for more information. # -# $Id: Makefile.am,v 1.49 2006/03/11 01:48:50 alex Exp $ +# $Id: Makefile.am,v 1.50 2007/11/21 12:16:36 alex Exp $ # AUTOMAKE_OPTIONS = ../portab/ansi2knr @@ -23,7 +23,7 @@ sbin_PROGRAMS = ngircd ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \ conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \ irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \ - match.c parse.c rendezvous.c resolve.c + match.c numeric.c parse.c rendezvous.c resolve.c ngircd_LDFLAGS = -L../portab -L../tool @@ -32,7 +32,7 @@ ngircd_LDADD = -lngportab -lngtool noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conn.h conn-func.h \ conn-zip.h hash.h io.h irc.h irc-channel.h irc-info.h irc-login.h \ irc-mode.h irc-op.h irc-oper.h irc-server.h irc-write.h lists.h log.h \ - match.h parse.h rendezvous.h resolve.h \ + match.h numeric.h parse.h rendezvous.h resolve.h \ defines.h messages.h clean-local: diff --git a/src/ngircd/client.c b/src/ngircd/client.c index 474ae4b6..c7d6427f 100644 --- a/src/ngircd/client.c +++ b/src/ngircd/client.c @@ -17,7 +17,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: client.c,v 1.96 2007/10/25 11:01:19 fw Exp $"; +static char UNUSED id[] = "$Id: client.c,v 1.97 2007/11/21 12:16:36 alex Exp $"; #include "imp.h" #include @@ -609,7 +609,8 @@ Client_ID( CLIENT *Client ) assert( Client != NULL ); #ifdef DEBUG - if( Client->type == CLIENT_USER ) assert( strlen( Client->id ) < CLIENT_NICK_LEN ); + if(Client->type == CLIENT_USER) + assert(strlen(Client->id) < Conf_MaxNickLength); #endif if( Client->id[0] ) return Client->id; @@ -952,7 +953,7 @@ Client_IsValidNick( const char *Nick ) if( Nick[0] == '#' ) return false; if( strchr( goodchars, Nick[0] )) return false; - if( strlen( Nick ) >= CLIENT_NICK_LEN ) return false; + if( strlen( Nick ) >= Conf_MaxNickLength) return false; ptr = Nick; while( *ptr ) diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index c9643dad..c55aaf53 100644 --- a/src/ngircd/conf.c +++ b/src/ngircd/conf.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: conf.c,v 1.101 2007/10/25 11:01:19 fw Exp $"; +static char UNUSED id[] = "$Id: conf.c,v 1.102 2007/11/21 12:16:36 alex Exp $"; #include "imp.h" #include @@ -208,7 +208,8 @@ Conf_Test( void ) printf( " NoDNS = %s\n", Conf_NoDNS ? "yes" : "no"); printf( " MaxConnections = %ld\n", Conf_MaxConnections); printf( " MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP); - printf( " MaxJoins = %d\n\n", Conf_MaxJoins); + printf( " MaxJoins = %d\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1); + printf( " MaxNickLength = %u\n\n", Conf_MaxNickLength - 1); for( i = 0; i < Conf_Oper_Count; i++ ) { if( ! Conf_Oper[i].name[0] ) continue; @@ -452,6 +453,7 @@ Set_Defaults( bool InitServers ) Conf_MaxConnections = 0; Conf_MaxConnectionsIP = 5; Conf_MaxJoins = 10; + Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT; /* Initialize server configuration structures */ if( InitServers ) for( i = 0; i < MAX_SERVERS; Init_Server_Struct( &Conf_Server[i++] )); @@ -638,6 +640,27 @@ Check_ArgIsTrue( const char *Arg ) } /* Check_ArgIsTrue */ +static unsigned int Handle_MaxNickLength(int Line, const char *Arg) +{ + unsigned new; + + new = (unsigned) atoi(Arg) + 1; + if (new > CLIENT_NICK_LEN) { + Config_Error(LOG_WARNING, + "%s, line %d: Value of \"MaxNickLength\" exceeds %u!", + NGIRCd_ConfFile, Line, CLIENT_NICK_LEN - 1); + return CLIENT_NICK_LEN; + } + if (new < 2) { + Config_Error(LOG_WARNING, + "%s, line %d: Value of \"MaxNickLength\" must be at least 1!", + NGIRCd_ConfFile, Line); + return 2; + } + return new; +} /* Handle_MaxNickLength */ + + static void Handle_GLOBAL( int Line, char *Var, char *Arg ) { @@ -827,6 +850,13 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) Conf_MaxJoins = atoi( Arg ); return; } + if( strcasecmp( Var, "MaxNickLength" ) == 0 ) { + /* Maximum length of a nick name; must be same on all servers + * within the IRC network! */ + Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg); + return; + } + if( strcasecmp( Var, "Listen" ) == 0 ) { /* IP-Address to bind sockets */ len = strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress )); diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h index ce09997c..371f94db 100644 --- a/src/ngircd/conf.h +++ b/src/ngircd/conf.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: conf.h,v 1.44 2007/10/25 11:01:19 fw Exp $ + * $Id: conf.h,v 1.45 2007/11/21 12:16:36 alex Exp $ * * Configuration management (header) */ @@ -135,6 +135,8 @@ GLOBAL int Conf_MaxJoins; /* Maximum number of connections per IP address */ GLOBAL int Conf_MaxConnectionsIP; +/* Maximum length of a nick name */ +GLOBAL unsigned int Conf_MaxNickLength; GLOBAL void Conf_Init PARAMS((void)); GLOBAL void Conf_Rehash PARAMS((void)); diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index 251a6997..cccf48b4 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: defines.h,v 1.61 2007/08/02 10:14:26 fw Exp $ + * $Id: defines.h,v 1.62 2007/11/21 12:16:36 alex Exp $ */ @@ -47,8 +47,9 @@ #define CLIENT_ID_LEN 64 /* Max. length of an IRC ID; see RFC RFC 2812 section 1.1 and 1.2.1 */ -#define CLIENT_NICK_LEN 10 /* Max. nick length, see. RFC 2812 - section 1.2.1 */ +#define CLIENT_NICK_LEN_DEFAULT 10 /* Default nick length, see. RFC 2812 + * section 1.2.1 */ +#define CLIENT_NICK_LEN 32 /* Maximum nick name length */ #define CLIENT_PASS_LEN 21 /* Max. password length */ #define CLIENT_USER_LEN 10 /* Max. length of user name ("login") see RFC 2812, section 1.2.1 */ @@ -81,7 +82,7 @@ protocol, see doc/Protocol.txt */ #ifdef IRCPLUS -# define IRCPLUSFLAGS "CL" /* Standard IRC+ flags */ +# define IRCPLUSFLAGS "CHL" /* Standard IRC+ flags */ #endif #define STARTUP_DELAY 1 /* Delay outgoing connections n seconds diff --git a/src/ngircd/irc-info.c b/src/ngircd/irc-info.c index 4ed05b33..683f7d1b 100644 --- a/src/ngircd/irc-info.c +++ b/src/ngircd/irc-info.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-info.c,v 1.39 2007/11/18 15:05:35 alex Exp $"; +static char UNUSED id[] = "$Id: irc-info.c,v 1.40 2007/11/21 12:16:36 alex Exp $"; #include "imp.h" #include @@ -1050,4 +1050,22 @@ IRC_Send_WHO( CLIENT *Client, CHANNEL *Chan, bool OnlyOps ) } /* IRC_Send_WHO */ +/** + * Send the ISUPPORT numeric (005). + * This numeric indicates the features that are supported by this server. + * See for details. + */ +GLOBAL bool +IRC_Send_ISUPPORT PARAMS((CLIENT * Client)) +{ + if (!IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client), + Conf_MaxJoins)) + return DISCONNECTED; + 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); +} /* IRC_Send_ISUPPORT */ + + /* -eof- */ diff --git a/src/ngircd/irc-info.h b/src/ngircd/irc-info.h index 24181e37..41e3953d 100644 --- a/src/ngircd/irc-info.h +++ b/src/ngircd/irc-info.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-info.h,v 1.3 2005/03/19 18:43:48 fw Exp $ + * $Id: irc-info.h,v 1.4 2007/11/21 12:16:36 alex Exp $ * * IRC info commands (header) */ @@ -36,6 +36,7 @@ GLOBAL bool IRC_Send_LUSERS PARAMS(( CLIENT *Client )); GLOBAL bool IRC_Send_NAMES PARAMS(( CLIENT *Client, CHANNEL *Chan )); GLOBAL bool IRC_Show_MOTD PARAMS(( CLIENT *Client )); GLOBAL bool IRC_Send_WHO PARAMS(( CLIENT *Client, CHANNEL *Chan, bool OnlyOps )); +GLOBAL bool IRC_Send_ISUPPORT PARAMS(( CLIENT *Client )); #endif diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c index caa78a1f..a095ddc0 100644 --- a/src/ngircd/irc-login.c +++ b/src/ngircd/irc-login.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-login.c,v 1.53 2006/10/03 10:28:38 alex Exp $"; +static char UNUSED id[] = "$Id: irc-login.c,v 1.54 2007/11/21 12:16:36 alex Exp $"; #include "imp.h" #include @@ -618,12 +618,7 @@ Hello_User( CLIENT *Client ) /* Features supported by this server (005 numeric, ISUPPORT), * see for details. */ - if (! IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client), - Conf_MaxJoins)) - return DISCONNECTED; - if (! IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client), - CHANNEL_NAME_LEN-1, CLIENT_NICK_LEN-1, COMMAND_LEN-23, - CLIENT_AWAY_LEN-1, COMMAND_LEN-113)) + if (! IRC_Send_ISUPPORT(Client)) return DISCONNECTED; Client_SetType( Client, CLIENT_USER ); diff --git a/src/ngircd/irc-server.c b/src/ngircd/irc-server.c index 3fc0e2dc..d342ffab 100644 --- a/src/ngircd/irc-server.c +++ b/src/ngircd/irc-server.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-server.c,v 1.45 2007/11/20 20:02:41 alex Exp $"; +static char UNUSED id[] = "$Id: irc-server.c,v 1.46 2007/11/21 12:16:36 alex Exp $"; #include "imp.h" #include @@ -35,54 +35,14 @@ static char UNUSED id[] = "$Id: irc-server.c,v 1.45 2007/11/20 20:02:41 alex Exp #include "log.h" #include "messages.h" #include "parse.h" +#include "numeric.h" #include "ngircd.h" +#include "irc-info.h" #include "exp.h" #include "irc-server.h" -#ifdef IRCPLUS -static bool -Synchronize_Lists( CLIENT *Client ) -{ - CHANNEL *c; - struct list_head *head; - struct list_elem *elem; - - assert( Client != NULL ); - - c = Channel_First(); - - while (c) { - head = Channel_GetListBans(c); - - elem = Lists_GetFirst(head); - while (elem) { - if( ! IRC_WriteStrClient( Client, "MODE %s +b %s", - Channel_Name(c), Lists_GetMask(elem))) - { - return false; - } - elem = Lists_GetNext(elem); - } - - head = Channel_GetListInvites(c); - elem = Lists_GetFirst(head); - while (elem) { - if( ! IRC_WriteStrClient( Client, "MODE %s +I %s", - Channel_Name( c ), Lists_GetMask(elem))) - { - return false; - } - elem = Lists_GetNext(elem); - } - c = Channel_Next(c); - } - return true; -} -#endif - - /** * Handler for the IRC command "SERVER". * See RFC 2813 section 4.1.2. @@ -90,12 +50,10 @@ Synchronize_Lists( CLIENT *Client ) GLOBAL bool IRC_SERVER( CLIENT *Client, REQUEST *Req ) { - char str[LINE_LEN], *ptr, *modes, *topic; - CLIENT *from, *c, *cl; - CL2CHAN *cl2chan; - int max_hops, i; - CHANNEL *chan; + char str[LINE_LEN], *ptr; + CLIENT *from, *c; bool ok; + int i; CONN_ID con; assert( Client != NULL ); @@ -164,10 +122,10 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) Client_SetToken( Client, atoi( Req->argv[1] )); } - Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), con ); - - Client_SetType( Client, CLIENT_SERVER ); - Conf_SetServer( i, con ); + /* Mark this connection as belonging to an configured server */ + Conf_SetServer(i, con); + + Client_SetType(Client, CLIENT_UNKNOWNSERVER); #ifdef ZLIB /* Kompression initialisieren, wenn erforderlich */ @@ -182,145 +140,23 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) } #endif - /* maximalen Hop Count ermitteln */ - max_hops = 0; - c = Client_First( ); - while( c ) - { - if( Client_Hops( c ) > max_hops ) max_hops = Client_Hops( c ); - c = Client_Next( c ); - } - - /* Alle bisherigen Server dem neuen Server bekannt machen, - * die bisherigen Server ueber den neuen informierenn */ - for( i = 0; i < ( max_hops + 1 ); i++ ) - { - c = Client_First( ); - while( c ) - { - if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )) && ( Client_Hops( c ) == i )) - { - if( Client_Conn( c ) > NONE ) - { - /* Dem gefundenen Server gleich den neuen - * Server bekannt machen */ - if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED; - } - - /* Inform the new server about this one */ - if (! IRC_WriteStrClientPrefix(Client, - Client_Hops(c) == 1 ? Client_ThisServer() : Client_TopServer(c), - "SERVER %s %d %d :%s", - Client_ID(c), Client_Hops(c) + 1, - Client_MyToken(c), Client_Info(c))) - return DISCONNECTED; - } - c = Client_Next( c ); - } - } - - /* alle User dem neuen Server bekannt machen */ - c = Client_First( ); - while( c ) - { - if( Client_Type( c ) == CLIENT_USER ) - { - /* User an neuen Server melden */ - if( ! IRC_WriteStrClient( Client, "NICK %s %d %s %s %d +%s :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_User( c ), Client_Hostname( c ), Client_MyToken( Client_Introducer( c )), Client_Modes( c ), Client_Info( c ))) return DISCONNECTED; - } - c = Client_Next( c ); - } - - /* Channels dem neuen Server bekannt machen */ - chan = Channel_First( ); - while( chan ) - { #ifdef IRCPLUS - /* Send CHANINFO if the peer supports it */ - if( strchr( Client_Flags( Client ), 'C' )) - { -#ifdef DEBUG - Log( LOG_DEBUG, "Sending CHANINFO commands ..." ); -#endif - modes = Channel_Modes( chan ); - topic = Channel_Topic( chan ); - - if( *modes || *topic ) - { - /* send CHANINFO */ - if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' )) && ( ! *topic )) - { - /* "CHANINFO +" */ - if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s", Channel_Name( chan ), modes )) return DISCONNECTED; - } - else if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' ))) - { - /* "CHANINFO + :" */ - if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s :%s", Channel_Name( chan ), modes, topic )) return DISCONNECTED; - } - else - { - /* "CHANINFO + :" */ - if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s %s %lu :%s", - Channel_Name( chan ), modes, - strchr( Channel_Modes( chan ), 'k' ) ? Channel_Key( chan ) : "*", - strchr( Channel_Modes( chan ), 'l' ) ? Channel_MaxUsers( chan ) : 0, topic )) - { - return DISCONNECTED; - } - } - } - } + if (strchr(Client_Flags(Client), 'H')) { + LogDebug("Peer supports IRC+ extended server handshake ..."); + if (!IRC_Send_ISUPPORT(Client)) + return DISCONNECTED; + return IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, + Client_ID(Client)); + } else { #endif - - /* alle Member suchen */ - cl2chan = Channel_FirstMember( chan ); - snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan )); - while( cl2chan ) - { - cl = Channel_GetClient( cl2chan ); - assert( cl != NULL ); - - /* Nick, ggf. mit Modes, anhaengen */ - if( str[strlen( str ) - 1] != ':' ) strlcat( str, ",", sizeof( str )); - if( strchr( Channel_UserModes( chan, cl ), 'v' )) strlcat( str, "+", sizeof( str )); - if( strchr( Channel_UserModes( chan, cl ), 'o' )) strlcat( str, "@", sizeof( str )); - strlcat( str, Client_ID( cl ), sizeof( str )); - - if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 8 )) - { - /* Zeile senden */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan )); - } - - cl2chan = Channel_NextMember( chan, cl2chan ); - } - - /* noch Daten da? */ - if( str[strlen( str ) - 1] != ':') - { - /* Ja; Also senden ... */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - } - - /* Get next channel ... */ - chan = Channel_Next(chan); - } - + if (Conf_MaxNickLength != CLIENT_NICK_LEN_DEFAULT) + Log(LOG_CRIT, + "Attention: this server uses a non-standard nick length, but the peer doesn't support the IRC+ extended server handshake!"); #ifdef IRCPLUS - if (strchr(Client_Flags(Client), 'L')) { -#ifdef DEBUG - Log(LOG_DEBUG, - "Synchronizing INVITE- and BAN-lists ..."); -#endif - /* Synchronize INVITE- and BAN-lists */ - if (!Synchronize_Lists(Client)) - return DISCONNECTED; } #endif - return CONNECTED; + return IRC_Num_ENDOFMOTD(Client, Req); } else if( Client_Type( Client ) == CLIENT_SERVER ) { @@ -364,8 +200,9 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c )); return CONNECTED; - } - else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); + } else + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); } /* IRC_SERVER */ diff --git a/src/ngircd/irc-server.h b/src/ngircd/irc-server.h index 6322b253..9940d791 100644 --- a/src/ngircd/irc-server.h +++ b/src/ngircd/irc-server.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-server.h,v 1.5 2005/03/19 18:43:49 fw Exp $ + * $Id: irc-server.h,v 1.6 2007/11/21 12:16:36 alex Exp $ * * IRC commands for server links (header) */ @@ -22,6 +22,8 @@ GLOBAL bool IRC_SERVER PARAMS((CLIENT *Client, REQUEST *Req )); GLOBAL bool IRC_NJOIN PARAMS((CLIENT *Client, REQUEST *Req )); GLOBAL bool IRC_SQUIT PARAMS((CLIENT *Client, REQUEST *Req )); +GLOBAL bool IRC_ENDOFMOTD_Server PARAMS((CLIENT *Client)); + #endif diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c index 1eb68b4c..d2a6d7ea 100644 --- a/src/ngircd/ngircd.c +++ b/src/ngircd/ngircd.c @@ -12,7 +12,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: ngircd.c,v 1.116 2007/11/15 01:03:01 fw Exp $"; +static char UNUSED id[] = "$Id: ngircd.c,v 1.117 2007/11/21 12:16:36 alex Exp $"; /** * @file @@ -422,6 +422,7 @@ GLOBAL void NGIRCd_Rehash( void ) { char old_name[CLIENT_ID_LEN]; + unsigned old_nicklen; Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" ); NGIRCd_SignalRehash = false; @@ -429,17 +430,22 @@ NGIRCd_Rehash( void ) /* Close down all listening sockets */ Conn_ExitListeners( ); - /* Remember old server name */ + /* Remember old server name and nick name length */ strlcpy( old_name, Conf_ServerName, sizeof old_name ); + old_nicklen = Conf_MaxNickLength; /* Re-read configuration ... */ Conf_Rehash( ); - /* Recover old server name: it can't be changed during run-time */ - if( strcmp( old_name, Conf_ServerName ) != 0 ) - { - strlcpy( Conf_ServerName, old_name, sizeof Conf_ServerName ); - Log( LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name." ); + /* Recover old server name and nick name length: these values can't + * be changed during run-time */ + if (strcmp(old_name, Conf_ServerName) != 0 ) { + strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName); + Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name."); + } + if (old_nicklen != Conf_MaxNickLength) { + Conf_MaxNickLength = old_nicklen; + Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value."); } /* Create new pre-defined channels */ diff --git a/src/ngircd/parse.c b/src/ngircd/parse.c index b5e64a33..5109169b 100644 --- a/src/ngircd/parse.c +++ b/src/ngircd/parse.c @@ -12,7 +12,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: parse.c,v 1.68 2007/08/02 10:14:26 fw Exp $"; +static char UNUSED id[] = "$Id: parse.c,v 1.69 2007/11/21 12:16:36 alex Exp $"; /** * @file @@ -48,6 +48,7 @@ static char UNUSED id[] = "$Id: parse.c,v 1.68 2007/08/02 10:14:26 fw Exp $"; #include "irc-oper.h" #include "irc-server.h" #include "irc-write.h" +#include "numeric.h" #include "exp.h" @@ -103,6 +104,13 @@ COMMAND My_Commands[] = { NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */ }; +NUMERIC My_Numerics[] = +{ + { 005, IRC_Num_ISUPPORT }, + { 376, IRC_Num_ENDOFMOTD }, + { 0, NULL } /* end marker */ +}; + static void Init_Request PARAMS(( REQUEST *Req )); @@ -349,6 +357,7 @@ Handle_Request( CONN_ID Idx, REQUEST *Req ) char str[LINE_LEN]; bool result; COMMAND *cmd; + NUMERIC *num; int i; assert( Idx >= 0 ); @@ -358,25 +367,45 @@ Handle_Request( CONN_ID Idx, REQUEST *Req ) client = Conn_GetClient( Idx ); assert( client != NULL ); - /* Statuscode? */ - if(( Client_Type( client ) == CLIENT_SERVER ) && ( strlen( Req->command ) == 3 ) && ( atoi( Req->command ) > 100 )) - { - /* Command is a status code from an other server */ + /* Numeric? */ + if ((Client_Type(client) == CLIENT_SERVER || + Client_Type(client) == CLIENT_UNKNOWNSERVER) + && strlen(Req->command) == 3 && atoi(Req->command) > 1) { + /* Command is a status code ("numeric") from an other server */ /* Determine target */ - if( Req->argc > 0 ) target = Client_Search( Req->argv[0] ); - else target = NULL; - if( ! target ) - { + if (Req->argc > 0) + target = Client_Search( Req->argv[0] ); + else + target = NULL; + if (!target) { /* Status code without target!? */ - if( Req->argc > 0 ) Log( LOG_WARNING, "Unknown target for status code %s: \"%s\"", Req->command, Req->argv[0] ); - else Log( LOG_WARNING, "Unknown target for status code %s!", Req->command ); + if (Req->argc > 0) + Log(LOG_WARNING, + "Unknown target for status code %s: \"%s\"", + Req->command, Req->argv[0]); + else + Log(LOG_WARNING, + "Unknown target for status code %s!", + Req->command); return true; } - if( target == Client_ThisServer( )) - { - /* This server is the target, ignore it */ - Log( LOG_DEBUG, "Ignored status code %s from \"%s\".", Req->command, Client_ID( client )); + if (target == Client_ThisServer()) { + /* This server is the target of the numeric */ + i = atoi(Req->command); + + num = My_Numerics; + while (num->numeric > 0) { + if (i != num->numeric) { + num++; + continue; + } + result = (num->function)(client, Req); + return result; + } + + LogDebug("Ignored status code %s from \"%s\".", + Req->command, Client_ID(client)); return true; } diff --git a/src/ngircd/parse.h b/src/ngircd/parse.h index b0956666..e7a00879 100644 --- a/src/ngircd/parse.h +++ b/src/ngircd/parse.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: parse.h,v 1.11 2005/03/19 18:43:49 fw Exp $ + * $Id: parse.h,v 1.12 2007/11/21 12:16:36 alex Exp $ * * IRC command parser and validator (header) */ @@ -33,11 +33,18 @@ typedef struct _COMMAND char *name; /* command name */ bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request )); CLIENT_TYPE type; /* valid client types (bit mask) */ - long lcount, rcount; /* number of local and remote calls */ - long bytes; /* number of bytes created */ + long lcount, rcount; /* number of local and remote calls */ + long bytes; /* number of bytes created */ } COMMAND; +typedef struct _NUMERIC +{ + int numeric; /* numeric */ + bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request )); +} NUMERIC; + + GLOBAL bool Parse_Request PARAMS((CONN_ID Idx, char *Request )); GLOBAL COMMAND *Parse_GetCommandStruct PARAMS(( void ));