summary refs log tree commit diff
path: root/src/ngircd/irc-server.c
diff options
context:
space:
mode:
authorAlexander Barton <alex@barton.de>2007-11-21 12:16:33 +0000
committerAlexander Barton <alex@barton.de>2007-11-21 12:16:33 +0000
commit47ca178a219d682c589b27e64ee1a4e936cc7bdc (patch)
tree463071b075abe6d73ca0bf8e3d284e1a174fd8e7 /src/ngircd/irc-server.c
parent12db0bdc4fb2d4bf40d6961406400a248bac123c (diff)
downloadngircd-47ca178a219d682c589b27e64ee1a4e936cc7bdc.tar.gz
ngircd-47ca178a219d682c589b27e64ee1a4e936cc7bdc.zip
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.
Diffstat (limited to 'src/ngircd/irc-server.c')
-rw-r--r--src/ngircd/irc-server.c211
1 files changed, 24 insertions, 187 deletions
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 <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 */