]> arthur.barton.de Git - ngircd-alex.git/commitdiff
Introduce option to configure the maximum nick name lenth in ngircd.conf
authorAlexander Barton <alex@barton.de>
Wed, 21 Nov 2007 12:16:33 +0000 (12:16 +0000)
committerAlexander Barton <alex@barton.de>
Wed, 21 Nov 2007 12:16:33 +0000 (12:16 +0000)
- 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.

19 files changed:
ChangeLog
NEWS
contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj
doc/Protocol.txt
doc/sample-ngircd.conf
man/ngircd.conf.5.tmpl
src/ngircd/Makefile.am
src/ngircd/client.c
src/ngircd/conf.c
src/ngircd/conf.h
src/ngircd/defines.h
src/ngircd/irc-info.c
src/ngircd/irc-info.h
src/ngircd/irc-login.c
src/ngircd/irc-server.c
src/ngircd/irc-server.h
src/ngircd/ngircd.c
src/ngircd/parse.c
src/ngircd/parse.h

index fbc51766fe7a1bf0fa3839aeb499f81a8f7af661..d39fbd5177d5f57db24c45f21bea9648a634cf96 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
 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 2591b230dd7150d6b7f4ba11813b9db6bcbafda7..a604926bd4e0e41ac28943b87727ee6f214d79a3 100644 (file)
--- 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 $
index 1ca7140d69505e665de32cd8dbc852fd2b81047f..1a032a79f5121ce9506b8f6a9d4227035cb8860f 100644 (file)
@@ -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 */
                FA322DB10CEF7565001761B3 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
                FA322DBB0CEF773C001761B3 /* cvs-version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "cvs-version.h"; sourceTree = "<group>"; };
                FA322DC00CEF77CB001761B3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
+               FAE5CC2C0CF2308A007D69B6 /* numeric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = numeric.h; sourceTree = "<group>"; };
+               FAE5CC2D0CF2308A007D69B6 /* numeric.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = numeric.c; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                FA322D050CEF74B1001761B3 /* messages.h */,
                                FA322D060CEF74B1001761B3 /* ngircd.c */,
                                FA322D070CEF74B1001761B3 /* ngircd.h */,
+                               FAE5CC2D0CF2308A007D69B6 /* numeric.c */,
+                               FAE5CC2C0CF2308A007D69B6 /* numeric.h */,
                                FA322D080CEF74B1001761B3 /* parse.c */,
                                FA322D090CEF74B1001761B3 /* parse.h */,
                                FA322D0A0CEF74B1001761B3 /* rendezvous.c */,
                                FA322D4C0CEF74B1001761B3 /* rendezvous.c in Sources */,
                                FA322D4D0CEF74B1001761B3 /* resolve.c in Sources */,
                                FA322DBE0CEF7766001761B3 /* tool.c in Sources */,
+                               FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 14da84757493db2da0cad65be464120f2cf3ac23..c81143e335928e9a7b7acc249117ebc227525cad 100644 (file)
@@ -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 <serverflags> 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 <options> 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 <serverflags> 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 <serverflags>) 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: <key>=<value>,
+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 <http://www.irc.org/tech_docs/005.html> 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: <channel> +<modes> <key> <limit> [<topic>]
@@ -115,4 +161,4 @@ channel mode). In this case <limit> 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 $
index e17b0e60690dd5b46a886985391acc7a083c3b9d..924f0595450939600f516516f97bf5b063bca401 100644 (file)
@@ -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
        # 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.
index 8321900926d6218ec9ffb7ad34a3166a90f608dd..457a162caba1c71918304b67262f81ca0bfb8343 100644 (file)
@@ -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
index 52bd1615bd4fc5b9400e43ec5f96c8ac7e25829f..46513a8a54da042e4b74fbc21ef165ed23c20b4c 100644 (file)
@@ -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:
index 474ae4b6460c4be738b90e723065885ffa0a51ad..c7d6427f939b72be30a05c2405ed20074cbbc3c7 100644 (file)
@@ -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 <assert.h>
@@ -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 )
index c9643dad491d75c5abefb7af49a7431ef31f1991..c55aaf53a775f8945706a73305d3157ed277b623 100644 (file)
@@ -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 <assert.h>
@@ -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 ));
index ce09997c23ee8bffeb460c405a3791fa922b527c..371f94db64233155d2169f16093d93e5df470195 100644 (file)
@@ -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));
index 251a6997dd3c1e084525cc29ede57c8219735cc2..cccf48b43e5f719d3a19146f995956e36fd6803e 100644 (file)
@@ -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
index 4ed05b332b21f2506999886c564f02c70d00c2db..683f7d1b04b8a79f0f3ff04f2d94771c14270ee4 100644 (file)
@@ -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 <assert.h>
@@ -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 <http://www.irc.org/tech_docs/005.html> 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- */
index 24181e375e7c0396860ff68ff3ef8bb4866deb3d..41e3953d1cd5ffab5988acbf099f70d748409154 100644 (file)
@@ -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
index caa78a1f3822993c3e9190d7a1c15d8e0e149e3b..a095ddc00bbf45ca73b6ac553fbaff73e806756c 100644 (file)
@@ -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 <assert.h>
@@ -618,12 +618,7 @@ Hello_User( CLIENT *Client )
 
        /* Features supported by this server (005 numeric, ISUPPORT),
         * see <http://www.irc.org/tech_docs/005.html> 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 );
index 3fc0e2dc1e84f2032e1ad0aa4f1c70cc82b14e93..d342ffab754f463ce423f842c41f56e9f37c192c 100644 (file)
@@ -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 <assert.h>
@@ -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 <chan> +<modes>" */
-                                               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 <chan> +<modes> :<topic>" */
-                                               if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s :%s", Channel_Name( chan ), modes, topic )) return DISCONNECTED;
-                                       }
-                                       else
-                                       {
-                                               /* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */
-                                               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 */
 
 
index 6322b25368f74f1c849c3b44e1c128147ae128ef..9940d79117f98b5a9fc2ab2880f8aa7124678c0d 100644 (file)
@@ -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
 
index 1eb68b4c94f824950e6b239a5641bff22dbc8ae6..d2a6d7ea8faae860f0df893edef82969acf80a3b 100644 (file)
@@ -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 */
index b5e64a331ffd0a2c57b503e0d0ca2097d84747ec..5109169b72a068b8ff4655adda8bcb6637c093b1 100644 (file)
@@ -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;
                }
 
index b095666601ba7018284055dc8698232de88c9d4c..e7a00879b5b826f7bef0dd4d604314fc0114ca09 100644 (file)
@@ -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 ));