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.
This commit is contained in:
Alexander Barton 2007-11-21 12:16:33 +00:00
parent 12db0bdc4f
commit 47ca178a21
19 changed files with 241 additions and 243 deletions

View File

@ -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 $

4
NEWS
View File

@ -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 $

View 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 */
@ -198,6 +199,8 @@
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 */
@ -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;
};

View 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 $

View 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
@ -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.

View 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

View 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:

View 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 )

View 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 ));

View 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));

View 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

View 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- */

View 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

View 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 );

View 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;
}
}
}
}
#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);
}
#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))
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
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
}
#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 */

View 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

View 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 */

View 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;
}

View 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 ));