/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2006 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "portab.h"
-static char UNUSED id[] = "$Id: irc-server.c,v 1.40 2006/10/01 19:05:02 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>
#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"
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 );
if (Client_Type(Client) == CLIENT_GOTPASS) {
/* We got a PASS command from the peer, and now a SERVER
* command: the peer tries to register itself as a server. */
- Log(LOG_DEBUG,
- "Connection %d: got SERVER command (new server link) ...",
- Client_Conn(Client));
+ LogDebug("Connection %d: got SERVER command (new server link) ...",
+ Client_Conn(Client));
/* Falsche Anzahl Parameter? */
if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
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 */
}
#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;
- }
-
- /* Den neuen Server ueber den alten informieren */
- if( ! IRC_WriteStrClientPrefix( Client, Client_Hops( c ) == 1 ? Client_ThisServer( ) : Client_Introducer( 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 %ld :%s", Channel_Name( chan ), modes, strchr( Channel_Modes( chan ), 'k' ) ? Channel_Key( chan ) : "*", strchr( Channel_Modes( chan ), 'l' ) ? Channel_MaxUsers( chan ) : 0L, 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 (! Lists_SendInvites(Client))
- return DISCONNECTED;
- if (! Lists_SendBans(Client))
- return DISCONNECTED;
}
#endif
- return CONNECTED;
+ return IRC_Num_ENDOFMOTD(Client, Req);
}
else if( Client_Type( Client ) == CLIENT_SERVER )
{
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 */