From: Alexander Barton Date: Wed, 2 Jan 2002 02:44:36 +0000 (+0000) Subject: - neue Defines fuer max. Anzahl Server und Operatoren. X-Git-Tag: rel-0-0-2~49 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=commitdiff_plain;h=03d971d99481244e7039bc960cfb962795fbe905 - neue Defines fuer max. Anzahl Server und Operatoren. --- diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index 5589e021..9d98ede3 100644 --- a/src/ngircd/conf.c +++ b/src/ngircd/conf.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: conf.c,v 1.7 2002/01/01 18:25:44 alex Exp $ + * $Id: conf.c,v 1.8 2002/01/02 02:44:36 alex Exp $ * * conf.h: Konfiguration des ngircd * * $Log: conf.c,v $ + * Revision 1.8 2002/01/02 02:44:36 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.7 2002/01/01 18:25:44 alex * - #include's fuer stdlib.h ergaenzt. * @@ -58,6 +61,11 @@ LOCAL VOID Read_Config( VOID ); + +GLOBAL VOID Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg ); +GLOBAL VOID Handle_OPERATOR( INT Line, CHAR *Var, CHAR *Arg ); +GLOBAL VOID Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg ); + LOCAL VOID Validate_Config( VOID ); @@ -71,9 +79,6 @@ GLOBAL VOID Conf_Init( VOID ) strcpy( Conf_ServerName, "" ); strcpy( Conf_ServerInfo, PACKAGE" "VERSION ); - strcpy( Conf_Oper, "" ); - strcpy( Conf_OperPwd, "" ); - strcpy( Conf_MotdFile, "/usr/local/etc/ngircd.motd" ); Conf_ListenPorts_Count = 0; @@ -81,6 +86,12 @@ GLOBAL VOID Conf_Init( VOID ) Conf_PingTimeout = 120; Conf_PongTimeout = 10; + Conf_ConnectRetry = 60; + + Conf_Oper_Count = 0; + + Conf_Server_Count = 0; + /* Konfigurationsdatei einlesen und validieren */ Read_Config( ); Validate_Config( ); @@ -97,9 +108,7 @@ LOCAL VOID Read_Config( VOID ) { /* Konfigurationsdatei einlesen. */ - CHAR str[LINE_LEN], *var, *arg, *ptr; - BOOLEAN ok; - INT32 port; + CHAR section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr; INT line; FILE *fd; @@ -113,10 +122,9 @@ LOCAL VOID Read_Config( VOID ) } line = 0; + strcpy( section, "" ); while( TRUE ) { - ok = FALSE; - if( ! fgets( str, LINE_LEN, fd )) break; ngt_TrimStr( str ); line++; @@ -124,6 +132,46 @@ LOCAL VOID Read_Config( VOID ) /* Kommentarzeilen und leere Zeilen ueberspringen */ if( str[0] == ';' || str[0] == '#' || str[0] == '\0' ) continue; + /* Anfang eines Abschnittes? */ + if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' )) + { + strcpy( section, str ); + if( strcasecmp( section, "[GLOBAL]" ) == 0 ) continue; + if( strcasecmp( section, "[OPERATOR]" ) == 0 ) + { + if( Conf_Oper_Count + 1 > MAX_OPERATORS ) Log( LOG_ERR, "Too many operators configured." ); + else + { + /* neuen Operator initialisieren */ + strcpy( Conf_Oper[Conf_Oper_Count].name, "" ); + strcpy( Conf_Oper[Conf_Oper_Count].pwd, "" ); + Conf_Oper_Count++; + } + continue; + } + if( strcasecmp( section, "[SERVER]" ) == 0 ) + { + if( Conf_Server_Count + 1 > MAX_SERVERS ) Log( LOG_ERR, "Too many servers configured." ); + else + { + /* neuen Server ("Peer") initialisieren */ + strcpy( Conf_Server[Conf_Server_Count].host, "" ); + strcpy( Conf_Server[Conf_Server_Count].ip, "" ); + strcpy( Conf_Server[Conf_Server_Count].name, "" ); + strcpy( Conf_Server[Conf_Server_Count].pwd, "" ); + Conf_Server[Conf_Server_Count].port = 0; + Conf_Server[Conf_Server_Count].lasttry = 0; + Conf_Server[Conf_Server_Count].res_stat = NULL; + Conf_Server_Count++; + } + continue; + } + Log( LOG_ERR, "%s, line %d: Unknown section \"%s\"!", Conf_File, line, section ); + section[0] = 0x1; + } + if( section[0] == 0x1 ) continue; + + /* In Variable und Argument zerlegen */ ptr = strchr( str, '=' ); if( ! ptr ) { @@ -131,81 +179,160 @@ LOCAL VOID Read_Config( VOID ) continue; } *ptr = '\0'; - var = str; ngt_TrimStr( var ); arg = ptr + 1; ngt_TrimStr( arg ); - - if( strcasecmp( str, "ServerName" ) == 0 ) - { - /* Der Server-Name */ - strncpy( Conf_ServerName, arg, CLIENT_ID_LEN ); - Conf_ServerName[CLIENT_ID_LEN - 1] = '\0'; - ok = TRUE; - } - else if( strcasecmp( str, "ServerInfo" ) == 0 ) - { - /* Server-Info-Text */ - strncpy( Conf_ServerInfo, arg, CLIENT_INFO_LEN ); - Conf_ServerInfo[CLIENT_INFO_LEN - 1] = '\0'; - ok = TRUE; - } - else if( strcasecmp( str, "Operator" ) == 0 ) - { - /* Name des IRC Operator */ - strncpy( Conf_Oper, arg, CLIENT_PASS_LEN ); - Conf_Oper[CLIENT_PASS_LEN - 1] = '\0'; - ok = TRUE; - } - else if( strcasecmp( str, "OperatorPwd" ) == 0 ) - { - /* Passwort des IRC Operator */ - strncpy( Conf_OperPwd, arg, CLIENT_PASS_LEN ); - Conf_OperPwd[CLIENT_PASS_LEN - 1] = '\0'; - ok = TRUE; - } - else if( strcasecmp( str, "ListenPorts" ) == 0 ) + + if( strcasecmp( section, "[GLOBAL]" ) == 0 ) Handle_GLOBAL( line, var, arg ); + else if( strcasecmp( section, "[OPERATOR]" ) == 0 ) Handle_OPERATOR( line, var, arg ); + else if( strcasecmp( section, "[SERVER]" ) == 0 ) Handle_SERVER( line, var, arg ); + else Log( LOG_ERR, "%s, line %d: Variable \"%s\" outside section!", Conf_File, line, var ); + } + + fclose( fd ); +} /* Read_Config */ + + +GLOBAL VOID Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg ) +{ + CHAR *ptr; + INT port; + + assert( Line > 0 ); + assert( Var != NULL ); + assert( Arg != NULL ); + + if( strcasecmp( Var, "Name" ) == 0 ) + { + /* Der Server-Name */ + strncpy( Conf_ServerName, Arg, CLIENT_ID_LEN ); + Conf_ServerName[CLIENT_ID_LEN - 1] = '\0'; + return; + } + if( strcasecmp( Var, "Info" ) == 0 ) + { + /* Server-Info-Text */ + strncpy( Conf_ServerInfo, Arg, CLIENT_INFO_LEN ); + Conf_ServerInfo[CLIENT_INFO_LEN - 1] = '\0'; + return; + } + if( strcasecmp( Var, "Ports" ) == 0 ) + { + /* Ports, durch "," getrennt, auf denen der Server + * Verbindungen annehmen soll */ + ptr = strtok( Arg, "," ); + while( ptr ) { - /* Ports, durch "," getrennt, auf denen der Server - * Verbindungen annehmen soll */ - ptr = strtok( arg, "," ); - while( ptr ) + ngt_TrimStr( ptr ); + port = atol( ptr ); + if( Conf_ListenPorts_Count + 1 > MAX_LISTEN_PORTS ) Log( LOG_ERR, "Too many listen ports configured. Port %ld ignored.", port ); + else { - ngt_TrimStr( ptr ); - port = atol( ptr ); - if( Conf_ListenPorts_Count + 1 > LISTEN_PORTS ) Log( LOG_ERR, "Too many listen ports configured. Port %ld ignored.", port ); if( port > 0 && port < 0xFFFF ) Conf_ListenPorts[Conf_ListenPorts_Count++] = port; - else Log( LOG_ERR, "Illegal port number: %ld. Ignored.", port ); - ptr = strtok( NULL, "," ); + else Log( LOG_ERR, "%s, line %d (section \"Global\"): Illegal port number %ld!", Conf_File, Line, port ); } - ok = TRUE; - } - else if( strcasecmp( str, "MotdFile" ) == 0 ) - { - /* Datei mit der "message of the day" (MOTD) */ - strncpy( Conf_MotdFile, arg, FNAME_LEN ); - Conf_MotdFile[FNAME_LEN - 1] = '\0'; - ok = TRUE; - } - else if( strcasecmp( str, "PingTimeout" ) == 0 ) - { - /* PING-Timeout */ - Conf_PingTimeout = atoi( arg ); - if(( Conf_PingTimeout ) < 5 ) Conf_PingTimeout = 5; - ok = TRUE; - } - else if( strcasecmp( str, "PongTimeout" ) == 0 ) - { - /* PONG-Timeout */ - Conf_PongTimeout = atoi( arg ); - if(( Conf_PongTimeout ) < 5 ) Conf_PongTimeout = 5; - ok = TRUE; + ptr = strtok( NULL, "," ); } + return; + } + if( strcasecmp( Var, "MotdFile" ) == 0 ) + { + /* Datei mit der "message of the day" (MOTD) */ + strncpy( Conf_MotdFile, Arg, FNAME_LEN ); + Conf_MotdFile[FNAME_LEN - 1] = '\0'; + return; + } + if( strcasecmp( Var, "PingTimeout" ) == 0 ) + { + /* PING-Timeout */ + Conf_PingTimeout = atoi( Arg ); + if(( Conf_PingTimeout ) < 5 ) Conf_PingTimeout = 5; + return; + } + if( strcasecmp( Var, "PongTimeout" ) == 0 ) + { + /* PONG-Timeout */ + Conf_PongTimeout = atoi( Arg ); + if(( Conf_PongTimeout ) < 5 ) Conf_PongTimeout = 5; + return; + } + if( strcasecmp( Var, "ConnectRetry" ) == 0 ) + { + /* Sekunden zwischen Verbindungsversuchen zu anderen Servern */ + Conf_ConnectRetry = atoi( Arg ); + if(( Conf_ConnectRetry ) < 5 ) Conf_ConnectRetry = 5; + return; + } - if( ! ok ) Log( LOG_ERR, "%s, line %d: Unknown variable \"%s\"!", Conf_File, line, var ); + Log( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!", Conf_File, Line, Var ); +} /* Handle_GLOBAL */ + + +GLOBAL VOID Handle_OPERATOR( INT Line, CHAR *Var, CHAR *Arg ) +{ + assert( Line > 0 ); + assert( Var != NULL ); + assert( Arg != NULL ); + assert( Conf_Oper_Count > 0 ); + + if( strcasecmp( Var, "Name" ) == 0 ) + { + /* Name des IRC Operator */ + strncpy( Conf_Oper[Conf_Oper_Count - 1].name, Arg, CLIENT_ID_LEN ); + Conf_Oper[Conf_Oper_Count - 1].name[CLIENT_ID_LEN - 1] = '\0'; + return; + } + if( strcasecmp( Var, "Password" ) == 0 ) + { + /* Passwort des IRC Operator */ + strncpy( Conf_Oper[Conf_Oper_Count - 1].pwd, Arg, CLIENT_PASS_LEN ); + Conf_Oper[Conf_Oper_Count - 1].pwd[CLIENT_PASS_LEN - 1] = '\0'; + return; } - fclose( fd ); -} /* Read_Config */ + Log( LOG_ERR, "%s, line %d (section \"Operator\"): Unknown variable \"%s\"!", Conf_File, Line, Var ); +} /* Handle_OPERATOR */ + + +GLOBAL VOID Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg ) +{ + INT port; + + assert( Line > 0 ); + assert( Var != NULL ); + assert( Arg != NULL ); + + if( strcasecmp( Var, "Host" ) == 0 ) + { + /* Hostname des Servers */ + strncpy( Conf_Server[Conf_Server_Count - 1].host, Arg, HOST_LEN ); + Conf_Server[Conf_Server_Count - 1].host[HOST_LEN - 1] = '\0'; + return; + } + if( strcasecmp( Var, "Name" ) == 0 ) + { + /* Name des Servers ("Nick") */ + strncpy( Conf_Server[Conf_Server_Count - 1].name, Arg, CLIENT_PASS_LEN ); + Conf_Server[Conf_Server_Count - 1].name[CLIENT_PASS_LEN - 1] = '\0'; + return; + } + if( strcasecmp( Var, "Password" ) == 0 ) + { + /* Passwort des Servers */ + strncpy( Conf_Server[Conf_Server_Count - 1].pwd, Arg, CLIENT_PASS_LEN ); + Conf_Server[Conf_Server_Count - 1].pwd[CLIENT_PASS_LEN - 1] = '\0'; + return; + } + if( strcasecmp( Var, "Port" ) == 0 ) + { + /* Port, zu dem Verbunden werden soll */ + port = atol( Arg ); + if( port > 0 && port < 0xFFFF ) Conf_Server[Conf_Server_Count - 1].port = port; + else Log( LOG_ERR, "%s, line %d (section \"Server\"): Illegal port number %ld!", Conf_File, Line, port ); + return; + } + + Log( LOG_ERR, "%s, line %d (section \"Server\"): Unknown variable \"%s\"!", Conf_File, Line, Var ); +} /* Handle_SERVER */ LOCAL VOID Validate_Config( VOID ) diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h index 60f4770b..04024e3a 100644 --- a/src/ngircd/conf.h +++ b/src/ngircd/conf.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: conf.h,v 1.6 2001/12/31 02:18:51 alex Exp $ + * $Id: conf.h,v 1.7 2002/01/02 02:44:36 alex Exp $ * * conf.h: Konfiguration des ngircd (Header) * * $Log: conf.h,v $ + * Revision 1.7 2002/01/02 02:44:36 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.6 2001/12/31 02:18:51 alex * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART), * - neuen Header "defines.h" mit (fast) allen Konstanten. @@ -39,22 +42,57 @@ #ifndef __conf_h__ #define __conf_h__ +#include + + +typedef struct _Conf_Oper +{ + CHAR name[CLIENT_PASS_LEN]; + CHAR pwd[CLIENT_PASS_LEN]; +} CONF_OPER; + +typedef struct _Conf_Server +{ + CHAR host[HOST_LEN]; + CHAR ip[16]; + CHAR name[CLIENT_ID_LEN]; + CHAR pwd[CLIENT_PASS_LEN]; + INT port; + time_t lasttry; + RES_STAT *res_stat; +} CONF_SERVER; + + +/* Konfigurationsdatei */ +GLOBAL CHAR Conf_File[FNAME_LEN]; + +/* Name ("Nick") des Servers */ +GLOBAL CHAR Conf_ServerName[CLIENT_ID_LEN]; + +/* Servers-Info-Text */ +GLOBAL CHAR Conf_ServerInfo[CLIENT_INFO_LEN]; -GLOBAL CHAR Conf_File[FNAME_LEN]; /* Konfigurationsdatei */ +/* Datei mit MOTD-Text */ +GLOBAL CHAR Conf_MotdFile[FNAME_LEN]; -GLOBAL CHAR Conf_ServerName[CLIENT_ID_LEN]; /* Name ("Nick") des Servers */ -GLOBAL CHAR Conf_ServerInfo[CLIENT_INFO_LEN]; /* Servers-Info-Text */ +/* Ports, auf denen der Server Verbindungen entgegen nimmt */ +GLOBAL INT Conf_ListenPorts[MAX_LISTEN_PORTS]; +GLOBAL INT Conf_ListenPorts_Count; -GLOBAL CHAR Conf_MotdFile[FNAME_LEN]; /* Datei mit MOTD-Text */ +/* Timeouts fuer PING und PONG */ +GLOBAL INT Conf_PingTimeout; +GLOBAL INT Conf_PongTimeout; -GLOBAL INT Conf_ListenPorts[LISTEN_PORTS]; /* Ports, auf denen der Server Verbindungen */ -GLOBAL INT Conf_ListenPorts_Count; /* entgegen nimmt sowie deren Anzahl */ +/* Sekunden zwischen Verbindungsversuchen zu anderen Servern */ +GLOBAL INT Conf_ConnectRetry; -GLOBAL CHAR Conf_Oper[CLIENT_PASS_LEN]; /* Operator Name */ -GLOBAL CHAR Conf_OperPwd[CLIENT_PASS_LEN]; /* Operator Passwort */ +/* Operatoren */ +GLOBAL CONF_OPER Conf_Oper[MAX_OPERATORS]; +GLOBAL INT Conf_Oper_Count; -GLOBAL INT Conf_PingTimeout; /* Ping Timeout */ -GLOBAL INT Conf_PongTimeout; /* Pong Timeout */ +/* Server */ +GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS]; +GLOBAL INT Conf_Server_Count; GLOBAL VOID Conf_Init( VOID ); diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c index 95e87885..e2ce03d6 100644 --- a/src/ngircd/conn.c +++ b/src/ngircd/conn.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: conn.c,v 1.24 2002/01/01 18:25:44 alex Exp $ + * $Id: conn.c,v 1.25 2002/01/02 02:44:36 alex Exp $ * * connect.h: Verwaltung aller Netz-Verbindungen ("connections") * * $Log: conn.c,v $ + * Revision 1.25 2002/01/02 02:44:36 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.24 2002/01/01 18:25:44 alex * - #include's fuer stdlib.h ergaenzt. * @@ -135,11 +138,7 @@ #include "conn.h" -typedef struct _Res_Stat -{ - INT pid; /* PID des Child-Prozess */ - INT pipe[2]; /* Pipe fuer IPC */ -} RES_STAT; +#define SERVER_WAIT NONE - 1 typedef struct _Connection @@ -152,6 +151,7 @@ typedef struct _Connection INT rdatalen; /* Laenge der Daten im Lesepuffer */ CHAR wbuf[WRITEBUFFER_LEN]; /* Schreibpuffer */ INT wdatalen; /* Laenge der Daten im Schreibpuffer */ + INT our_server; /* wenn von uns zu connectender Server: ID */ time_t lastdata; /* Letzte Aktivitaet */ time_t lastping; /* Letzter PING */ time_t lastprivmsg; /* Letzte PRIVMSG */ @@ -166,11 +166,16 @@ LOCAL VOID Read_Request( CONN_ID Idx ); LOCAL BOOLEAN Try_Write( CONN_ID Idx ); LOCAL VOID Handle_Buffer( CONN_ID Idx ); LOCAL VOID Check_Connections( VOID ); +LOCAL VOID Check_Servers( VOID ); LOCAL VOID Init_Conn_Struct( INT Idx ); +LOCAL VOID New_Server( INT Server, CONN_ID Idx ); -LOCAL RES_STAT *Resolve( struct sockaddr_in *Addr ); +LOCAL RES_STAT *ResolveAddr( struct sockaddr_in *Addr ); +LOCAL RES_STAT *ResolveName( CHAR *Host ); +LOCAL VOID Do_ResolveAddr( struct sockaddr_in *Addr, INT w_fd ); +LOCAL VOID Do_ResolveName( CHAR *Host, INT w_fd ); LOCAL VOID Read_Resolver_Result( INT r_fd ); -LOCAL VOID Do_Resolve( struct sockaddr_in *Addr, INT w_fd ); +LOCAL CHAR *Resolv_Error( INT H_Error ); LOCAL fd_set My_Listeners; @@ -303,6 +308,7 @@ GLOBAL VOID Conn_Handler( INT Timeout ) * Sekunden wird die Funktion verlassen. Folgende Aktionen * werden durchgefuehrt: * - neue Verbindungen annehmen, + * - Server-Verbindungen aufbauen, * - geschlossene Verbindungen loeschen, * - volle Schreibpuffer versuchen zu schreiben, * - volle Lesepuffer versuchen zu verarbeiten, @@ -317,6 +323,8 @@ GLOBAL VOID Conn_Handler( INT Timeout ) start = time( NULL ); while(( time( NULL ) - start < Timeout ) && ( ! NGIRCd_Quit )) { + Check_Servers( ); + Check_Connections( ); /* Timeout initialisieren */ @@ -326,7 +334,7 @@ GLOBAL VOID Conn_Handler( INT Timeout ) /* noch volle Lese-Buffer suchen */ for( i = 0; i < MAX_CONNECTIONS; i++ ) { - if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].rdatalen > 0 )) + if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].rdatalen > 0 )) { /* Kann aus dem Buffer noch ein Befehl extrahiert werden? */ Handle_Buffer( i ); @@ -337,7 +345,7 @@ GLOBAL VOID Conn_Handler( INT Timeout ) FD_ZERO( &write_sockets ); for( i = 0; i < MAX_CONNECTIONS; i++ ) { - if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].wdatalen > 0 )) + if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].wdatalen > 0 )) { /* Socket der Verbindung in Set aufnehmen */ FD_SET( My_Connections[i].sock, &write_sockets ); @@ -348,7 +356,7 @@ GLOBAL VOID Conn_Handler( INT Timeout ) read_sockets = My_Sockets; for( i = 0; i < MAX_CONNECTIONS; i++ ) { - if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].host[0] == '\0' )) + if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].host[0] == '\0' )) { /* Hier muss noch auf den Resolver Sub-Prozess gewartet werden */ FD_CLR( My_Connections[i].sock, &read_sockets ); @@ -421,7 +429,7 @@ GLOBAL BOOLEAN Conn_Write( CONN_ID Idx, CHAR *Data, INT Len ) * der Client disconnectiert und FALSE geliefert. */ assert( Idx >= 0 ); - assert( My_Connections[Idx].sock >= 0 ); + assert( My_Connections[Idx].sock > NONE ); assert( Data != NULL ); assert( Len > 0 ); @@ -460,22 +468,28 @@ GLOBAL VOID Conn_Close( CONN_ID Idx, CHAR *Msg ) /* Verbindung schliessen. Evtl. noch von Resolver * Sub-Prozessen offene Pipes werden geschlossen. */ + CLIENT *c; + assert( Idx >= 0 ); - assert( My_Connections[Idx].sock >= 0 ); + assert( My_Connections[Idx].sock > NONE ); - if( Msg ) Conn_WriteStr( Idx, "ERROR :%s", Msg ); + if( Msg ) + { + Conn_WriteStr( Idx, "ERROR :%s", Msg ); + if( My_Connections[Idx].sock == NONE ) return; + } if( close( My_Connections[Idx].sock ) != 0 ) { Log( LOG_ERR, "Error closing connection %d with %s:%d - %s!", Idx, inet_ntoa( My_Connections[Idx].addr.sin_addr ), ntohs( My_Connections[Idx].addr.sin_port), strerror( errno )); - return; } else { Log( LOG_NOTICE, "Connection %d with %s:%d closed.", Idx, inet_ntoa( My_Connections[Idx].addr.sin_addr ), ntohs( My_Connections[Idx].addr.sin_port )); } - Client_Destroy( Client_GetFromConn( Idx )); + c = Client_GetFromConn( Idx ); + if( c ) Client_Destroy( c ); if( My_Connections[Idx].res_stat ) { @@ -485,7 +499,10 @@ GLOBAL VOID Conn_Close( CONN_ID Idx, CHAR *Msg ) close( My_Connections[Idx].res_stat->pipe[1] ); free( My_Connections[Idx].res_stat ); } - + + /* Bei Server-Verbindungen lasttry-Zeitpunkt auf "jetzt" setzen */ + if( My_Connections[Idx].our_server >= 0 ) Conf_Server[My_Connections[Idx].our_server].lasttry = time( NULL ); + FD_CLR( My_Connections[Idx].sock, &My_Sockets ); My_Connections[Idx].sock = NONE; } /* Conn_Close */ @@ -517,7 +534,7 @@ LOCAL BOOLEAN Try_Write( CONN_ID Idx ) fd_set write_socket; assert( Idx >= 0 ); - assert( My_Connections[Idx].sock >= 0 ); + assert( My_Connections[Idx].sock > NONE ); assert( My_Connections[Idx].wdatalen > 0 ); FD_ZERO( &write_socket ); @@ -579,7 +596,7 @@ LOCAL BOOLEAN Handle_Write( CONN_ID Idx ) INT len; assert( Idx >= 0 ); - assert( My_Connections[Idx].sock >= 0 ); + assert( My_Connections[Idx].sock > NONE ); assert( My_Connections[Idx].wdatalen > 0 ); /* Daten schreiben */ @@ -621,7 +638,7 @@ LOCAL VOID New_Connection( INT Sock ) } /* Freie Connection-Struktur suschen */ - for( idx = 0; idx < MAX_CONNECTIONS; idx++ ) if( My_Connections[idx].sock < 0 ) break; + for( idx = 0; idx < MAX_CONNECTIONS; idx++ ) if( My_Connections[idx].sock == NONE ) break; if( idx >= MAX_CONNECTIONS ) { Log( LOG_ALERT, "Can't accept connection: limit reached (%d)!", MAX_CONNECTIONS ); @@ -649,7 +666,7 @@ LOCAL VOID New_Connection( INT Sock ) Log( LOG_NOTICE, "Accepted connection %d from %s:%d on socket %d.", idx, inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock ); /* Hostnamen ermitteln */ - s = Resolve( &new_addr ); + s = ResolveAddr( &new_addr ); if( s ) { /* Sub-Prozess wurde asyncron gestartet */ @@ -686,7 +703,7 @@ LOCAL VOID Read_Request( CONN_ID Idx ) INT len; assert( Idx >= 0 ); - assert( My_Connections[Idx].sock >= 0 ); + assert( My_Connections[Idx].sock > NONE ); len = recv( My_Connections[Idx].sock, My_Connections[Idx].rbuf + My_Connections[Idx].rdatalen, READBUFFER_LEN - My_Connections[Idx].rdatalen - 1, 0 ); My_Connections[Idx].rbuf[READBUFFER_LEN - 1] = '\0'; @@ -777,20 +794,25 @@ LOCAL VOID Check_Connections( VOID ) * nicht der Fall, zunaechst PING-PONG spielen und, wenn * auch das nicht "hilft", Client disconnectieren. */ + CLIENT *c; INT i; for( i = 0; i < MAX_CONNECTIONS; i++ ) { - if( My_Connections[i].sock != NONE ) + if( My_Connections[i].sock == NONE ) continue; + + c = Client_GetFromConn( i ); + if( c && (( c->type == CLIENT_USER ) || ( c->type == CLIENT_SERVER ) || ( c->type == CLIENT_SERVICE ))) { + /* verbundener User, Server oder Service */ if( My_Connections[i].lastping > My_Connections[i].lastdata ) { /* es wurde bereits ein PING gesendet */ if( My_Connections[i].lastping < time( NULL ) - Conf_PongTimeout ) { /* Timeout */ - Log( LOG_INFO, "Connection %d: Ping timeout.", i ); - Conn_Close( i, "Ping timeout" ); + Log( LOG_INFO, "Connection %d: PING timeout.", i ); + Conn_Close( i, "PING timeout" ); } } else if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout ) @@ -801,8 +823,151 @@ LOCAL VOID Check_Connections( VOID ) Conn_WriteStr( i, "PING :%s", This_Server->nick ); } } + else + { + /* noch nicht vollstaendig aufgebaute Verbindung */ + if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout ) + { + /* Timeout */ + Log( LOG_INFO, "Connection %d: Timeout.", i ); + Conn_Close( i, "Timeout" ); + } + } + } +} /* Check_Connections */ + + +LOCAL VOID Check_Servers( VOID ) +{ + /* Pruefen, ob Server-Verbindungen aufgebaut werden + * muessen bzw. koennen */ + + INT idx, i, n; + RES_STAT *s; + + for( i = 0; i < Conf_Server_Count; i++ ) + { + /* Ist ein Hostname und Port definiert? */ + if(( ! Conf_Server[i].host[0] ) || ( ! Conf_Server[i].port > 0 )) continue; + + /* Haben wir schon eine Verbindung? */ + for( n = 0; n < MAX_CONNECTIONS; n++ ) + { + if(( My_Connections[n].sock != NONE ) && ( My_Connections[n].our_server == i )) + { + /* Komplett aufgebaute Verbindung? */ + if( My_Connections[n].sock > NONE ) break; + + /* IP schon aufgeloest? */ + if( My_Connections[n].res_stat == NULL ) New_Server( i, n ); + } + } + if( n < MAX_CONNECTIONS ) continue; + + /* Wann war der letzte Connect-Versuch? */ + if( Conf_Server[i].lasttry > time( NULL ) - Conf_ConnectRetry ) continue; + + /* Okay, Verbindungsaufbau versuchen */ + Conf_Server[i].lasttry = time( NULL ); + + /* Freie Connection-Struktur suschen */ + for( idx = 0; idx < MAX_CONNECTIONS; idx++ ) if( My_Connections[idx].sock == NONE ) break; + if( idx >= MAX_CONNECTIONS ) + { + Log( LOG_ALERT, "Can't establist server connection: connection limit reached (%d)!", MAX_CONNECTIONS ); + return; + } + Log( LOG_DEBUG, "Preparing connection %d for \"%s\" ...", idx, Conf_Server[i].host ); + + /* Verbindungs-Struktur initialisieren */ + Init_Conn_Struct( idx ); + My_Connections[idx].sock = SERVER_WAIT; + My_Connections[idx].our_server = i; + + /* Hostnamen in IP aufloesen */ + s = ResolveName( Conf_Server[i].host ); + if( s ) + { + /* Sub-Prozess wurde asyncron gestartet */ + My_Connections[idx].res_stat = s; + } + else + { + /* kann Namen nicht aufloesen: Connection-Struktur freigeben */ + Init_Conn_Struct( idx ); + } + } +} /* Check_Servers */ + + +LOCAL VOID New_Server( INT Server, CONN_ID Idx ) +{ + /* Neue Server-Verbindung aufbauen */ + + struct sockaddr_in new_addr; + struct in_addr inaddr; + INT new_sock; + + assert( Server >= 0 ); + assert( Idx >= 0 ); + + /* Wurde eine gueltige IP-Adresse gefunden? */ + if( ! Conf_Server[Server].ip[0] ) + { + /* Nein. Verbindung wieder freigeben: */ + Init_Conn_Struct( Idx ); + Log( LOG_ERR, "Can't connect to \"%s\" (connection %d): ip address unknown!", Conf_Server[Server].host, Idx ); + return; + } + + Log( LOG_INFO, "Establishing connection to \"%s\", %s (connection %d) ... ", Conf_Server[Server].host, Conf_Server[Server].ip, Idx ); + + if( inet_aton( Conf_Server[Server].ip, &inaddr ) == 0 ) + { + /* Konnte Adresse nicht konvertieren */ + Init_Conn_Struct( Idx ); + Log( LOG_ERR, "Can't connect to \"%s\" (connection %d): can't convert ip address %s!", Conf_Server[Server].host, Idx, Conf_Server[Server].ip ); + return; + } + + memset( &new_addr, 0, sizeof( new_addr )); + new_addr.sin_family = AF_INET; + new_addr.sin_addr = inaddr; + new_addr.sin_port = htons( Conf_Server[Server].port ); + + new_sock = socket( PF_INET, SOCK_STREAM, 0 ); + if ( new_sock < 0 ) + { + Init_Conn_Struct( Idx ); + Log( LOG_ALERT, "Can't create socket: %s!", strerror( errno )); + return; } -} /* Conn_Check */ + if( connect( new_sock, (struct sockaddr *)&new_addr, sizeof( new_addr )) < 0) + { + close( new_sock ); + Init_Conn_Struct( Idx ); + Log( LOG_ALERT, "Can't connect socket: %s!", strerror( errno )); + return; + } + + /* Client-Struktur initialisieren */ + if( ! Client_NewLocal( Idx, inet_ntoa( new_addr.sin_addr ))) + { + close( new_sock ); + Init_Conn_Struct( Idx ); + Log( LOG_ALERT, "Can't establish connection: can't create client structure!" ); + return; + } + + /* Verbindung registrieren */ + My_Connections[Idx].sock = new_sock; + My_Connections[Idx].addr = new_addr; + strcpy( My_Connections[Idx].host, Conf_Server[Server].host ); + + /* Neuen Socket registrieren */ + FD_SET( new_sock, &My_Sockets ); + if( new_sock > My_Max_Fd ) My_Max_Fd = new_sock; +} /* New_Server */ LOCAL VOID Init_Conn_Struct( INT Idx ) @@ -816,15 +981,16 @@ LOCAL VOID Init_Conn_Struct( INT Idx ) My_Connections[Idx].rdatalen = 0; My_Connections[Idx].wbuf[0] = '\0'; My_Connections[Idx].wdatalen = 0; + My_Connections[Idx].our_server = -1; My_Connections[Idx].lastdata = time( NULL ); My_Connections[Idx].lastping = 0; My_Connections[Idx].lastprivmsg = time( NULL ); } /* Init_Conn_Struct */ -LOCAL RES_STAT *Resolve( struct sockaddr_in *Addr ) +LOCAL RES_STAT *ResolveAddr( struct sockaddr_in *Addr ) { - /* Hostnamen (asyncron!) aufloesen. Bei Fehler, z.B. wenn der + /* IP (asyncron!) aufloesen. Bei Fehler, z.B. wenn der * Child-Prozess nicht erzeugt werden kann, wird NULL geliefert. * Der Host kann dann nicht aufgeloest werden. */ @@ -862,7 +1028,61 @@ LOCAL RES_STAT *Resolve( struct sockaddr_in *Addr ) { /* Sub-Prozess */ Log_Init_Resolver( ); - Do_Resolve( Addr, s->pipe[1] ); + Do_ResolveAddr( Addr, s->pipe[1] ); + Log_Exit_Resolver( ); + exit( 0 ); + } + else + { + /* Fehler */ + free( s ); + Log( LOG_ALERT, "Resolver: Can't fork: %s!", strerror( errno )); + return NULL; + } +} /* ResolveAddr */ + + +LOCAL RES_STAT *ResolveName( CHAR *Host ) +{ + /* Hostnamen (asyncron!) aufloesen. Bei Fehler, z.B. wenn der + * Child-Prozess nicht erzeugt werden kann, wird NULL geliefert. + * Der Host kann dann nicht aufgeloest werden. */ + + RES_STAT *s; + INT pid; + + /* Speicher anfordern */ + s = malloc( sizeof( RES_STAT )); + if( ! s ) + { + Log( LOG_ALERT, "Resolver: Can't alloc memory!" ); + return NULL; + } + + /* Pipe fuer Antwort initialisieren */ + if( pipe( s->pipe ) != 0 ) + { + free( s ); + Log( LOG_ALERT, "Resolver: Can't create output pipe: %s!", strerror( errno )); + return NULL; + } + + /* Sub-Prozess erzeugen */ + pid = fork( ); + if( pid > 0 ) + { + /* Haupt-Prozess */ + Log( LOG_DEBUG, "Resolver for \"%s\" created (PID %d).", Host, pid ); + FD_SET( s->pipe[0], &My_Resolvers ); + if( s->pipe[0] > My_Max_Fd ) My_Max_Fd = s->pipe[0]; + s->pid = pid; + return s; + } + else if( pid == 0 ) + { + /* Sub-Prozess */ + Log_Init_Resolver( ); + Do_ResolveName( Host, s->pipe[1] ); Log_Exit_Resolver( ); exit( 0 ); } @@ -873,40 +1093,107 @@ LOCAL RES_STAT *Resolve( struct sockaddr_in *Addr ) Log( LOG_ALERT, "Resolver: Can't fork: %s!", strerror( errno )); return NULL; } -} /* Resolve */ +} /* ResolveName */ + + +LOCAL VOID Do_ResolveAddr( struct sockaddr_in *Addr, INT w_fd ) +{ + /* Resolver Sub-Prozess: IP aufloesen und Ergebnis in Pipe schreiben. */ + + CHAR hostname[HOST_LEN]; + struct hostent *h; + + Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr )); + + /* Namen aufloesen */ + h = gethostbyaddr( (CHAR *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET ); + if( h ) strcpy( hostname, h->h_name ); + else + { + Log_Resolver( LOG_WARNING, "Can't resolve address %s: code %s!", inet_ntoa( Addr->sin_addr ), Resolv_Error( h_errno )); + strcpy( hostname, inet_ntoa( Addr->sin_addr )); + } + + /* Antwort an Parent schreiben */ + if( write( w_fd, hostname, strlen( hostname ) + 1 ) != ( strlen( hostname ) + 1 )) + { + Log_Resolver( LOG_ALERT, "Resolver: Can't write to parent: %s!", strerror( errno )); + close( w_fd ); + return; + } + + Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname ); +} /* Do_ResolveAddr */ + + +LOCAL VOID Do_ResolveName( CHAR *Host, INT w_fd ) +{ + /* Resolver Sub-Prozess: Name aufloesen und Ergebnis in Pipe schreiben. */ + + CHAR ip[16]; + struct hostent *h; + struct in_addr *addr; + + Log_Resolver( LOG_DEBUG, "Now resolving \"%s\" ...", Host ); + + /* Namen aufloesen */ + h = gethostbyname( Host ); + if( h ) + { + addr = (struct in_addr *)h->h_addr; + strcpy( ip, inet_ntoa( *addr )); + } + else + { + Log_Resolver( LOG_WARNING, "Can't resolve \"%s\": %s!", Host, Resolv_Error( h_errno )); + strcpy( ip, "" ); + } + + /* Antwort an Parent schreiben */ + if( write( w_fd, ip, strlen( ip ) + 1 ) != ( strlen( ip ) + 1 )) + { + Log_Resolver( LOG_ALERT, "Resolver: Can't write to parent: %s!", strerror( errno )); + close( w_fd ); + return; + } + + if( ip[0] ) Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip ); +} /* Do_ResolveName */ LOCAL VOID Read_Resolver_Result( INT r_fd ) { /* Ergebnis von Resolver Sub-Prozess aus Pipe lesen - * und entsprechende Connection aktualisieren */ + * und entsprechende Connection aktualisieren */ - CHAR hostname[HOST_LEN]; + CHAR result[HOST_LEN]; CLIENT *c; - INT i; + INT len, i; FD_CLR( r_fd, &My_Resolvers ); /* Anfrage vom Parent lesen */ - if( read( r_fd, hostname, HOST_LEN) < 0 ) + len = read( r_fd, result, HOST_LEN); + if( len < 0 ) { /* Fehler beim Lesen aus der Pipe */ close( r_fd ); Log( LOG_ALERT, "Resolver: Can't read result: %s!", strerror( errno )); return; } + result[len] = '\0'; /* zugehoerige Connection suchen */ for( i = 0; i < MAX_CONNECTIONS; i++ ) { - if(( My_Connections[i].sock >= 0 ) && ( My_Connections[i].res_stat ) && ( My_Connections[i].res_stat->pipe[0] == r_fd )) break; + if(( My_Connections[i].sock != NONE ) && ( My_Connections[i].res_stat ) && ( My_Connections[i].res_stat->pipe[0] == r_fd )) break; } - if( i >= MAX_CONNECTIONS ) { - /* Opsa! Keine passende Connection gefunden!? */ + /* Opsa! Keine passende Connection gefunden!? Vermutlich + * wurde sie schon wieder geschlossen. */ close( r_fd ); - Log( LOG_ALERT, "Resolver: Got result for unknown connection!?" ); + Log( LOG_DEBUG, "Resolver: Got result for unknown connection!?" ); return; } @@ -915,43 +1202,41 @@ LOCAL VOID Read_Resolver_Result( INT r_fd ) close( My_Connections[i].res_stat->pipe[1] ); free( My_Connections[i].res_stat ); My_Connections[i].res_stat = NULL; - - /* Hostnamen setzen */ - strcpy( My_Connections[i].host, hostname ); - c = Client_GetFromConn( i ); - if( c ) Client_SetHostname( c, hostname ); -} /* Read_Resolver_Result */ - - -LOCAL VOID Do_Resolve( struct sockaddr_in *Addr, INT w_fd ) -{ - /* Resolver Sub-Prozess: aufzuloesenden Namen aus - * der Pipe lesen, Ergebnis in Pipe schreiben. */ - - CHAR hostname[HOST_LEN]; - struct hostent *h; - Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr )); - - /* Namen aufloesen */ - h = gethostbyaddr( (CHAR *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET ); - if( h ) strcpy( hostname, h->h_name ); + if( My_Connections[i].sock > NONE ) + { + /* Eingehende Verbindung: Hostnamen setzen */ + strcpy( My_Connections[i].host, result ); + c = Client_GetFromConn( i ); + if( c ) Client_SetHostname( c, result ); + } else { - Log_Resolver( LOG_WARNING, "Resolver: Can't resolve host name (code %d)!", h_errno ); - strcpy( hostname, inet_ntoa( Addr->sin_addr )); + /* Ausgehende Verbindung (=Server): IP setzen */ + assert( My_Connections[i].our_server >= 0 ); + strcpy( Conf_Server[My_Connections[i].our_server].ip, result ); } +} /* Read_Resolver_Result */ - /* Antwort an Parent schreiben */ - if( write( w_fd, hostname, strlen( hostname ) + 1 ) != ( strlen( hostname ) + 1 )) + +LOCAL CHAR *Resolv_Error( INT H_Error ) +{ + /* Fehlerbeschreibung fuer H_Error liefern */ + + switch( H_Error ) { - Log_Resolver( LOG_ALERT, "Resolver: Can't write to parent: %s!", strerror( errno )); - close( w_fd ); - return; + case HOST_NOT_FOUND: + return "host not found"; + case NO_ADDRESS: + return "name valid but no IP address defined"; + case NO_RECOVERY: + return "name server error"; + case TRY_AGAIN: + return "name server temporary not available"; + default: + return "unknown error"; } - - Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname ); -} /* Do_Resolve */ +} /* Resolv_Error */ /* -eof- */ diff --git a/src/ngircd/conn.h b/src/ngircd/conn.h index e76a862e..2e0ac8eb 100644 --- a/src/ngircd/conn.h +++ b/src/ngircd/conn.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: conn.h,v 1.8 2001/12/31 02:18:51 alex Exp $ + * $Id: conn.h,v 1.9 2002/01/02 02:44:36 alex Exp $ * * conn.h: Verwaltung aller Netz-Verbindungen ("connections") (Header) * * $Log: conn.h,v $ + * Revision 1.9 2002/01/02 02:44:36 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.8 2001/12/31 02:18:51 alex * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART), * - neuen Header "defines.h" mit (fast) allen Konstanten. @@ -48,6 +51,12 @@ typedef INT CONN_ID; +typedef struct _Res_Stat +{ + INT pid; /* PID des Child-Prozess */ + INT pipe[2]; /* Pipe fuer IPC */ +} RES_STAT; + GLOBAL VOID Conn_Init( VOID ); GLOBAL VOID Conn_Exit( VOID ); diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index c652506f..c2d5c991 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: defines.h,v 1.1 2001/12/31 02:18:51 alex Exp $ + * $Id: defines.h,v 1.2 2002/01/02 02:44:36 alex Exp $ * * defines.h: (globale) Konstanten * * $Log: defines.h,v $ + * Revision 1.2 2002/01/02 02:44:36 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.1 2001/12/31 02:18:51 alex * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART), * - neuen Header "defines.h" mit (fast) allen Konstanten. @@ -29,12 +32,16 @@ #define FNAME_LEN 256 /* max. Laenge eines Dateinamen */ -#define LISTEN_PORTS 16 /* max. Anzahl von Listen-Ports */ - #define LINE_LEN 256 /* max. Laenge einer Konfigurationszeile */ #define HOST_LEN 256 /* max. Laenge eines Hostnamen */ +#define MAX_LISTEN_PORTS 16 /* max. Anzahl von Listen-Ports */ + +#define MAX_OPERATORS 8 /* max. Anzahl konfigurierbarer Operatoren */ + +#define MAX_SERVERS 8 /* max. Anzahl konfigurierbarer Server ("Peers") */ + #define MAX_CONNECTIONS 100 /* max. Anzahl von Verbindungen an diesem Server */ #define MAX_CHANNELS 32 /* max. Anzahl Channels pro Nick */ diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index a33a9286..cbec071c 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: irc.c,v 1.17 2001/12/31 15:33:13 alex Exp $ + * $Id: irc.c,v 1.18 2002/01/02 02:44:36 alex Exp $ * * irc.c: IRC-Befehle * * $Log: irc.c,v $ + * Revision 1.18 2002/01/02 02:44:36 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.17 2001/12/31 15:33:13 alex * - neuer Befehl NAMES, kleinere Bugfixes. * - Bug bei PING behoben: war zu restriktiv implementiert :-) @@ -480,6 +483,8 @@ GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req ) GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req ) { + INT i; + assert( Client != NULL ); assert( Req != NULL ); @@ -487,12 +492,16 @@ GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req ) /* Falsche Anzahl Parameter? */ if( Req->argc != 2 ) return IRC_WriteStrClient( Client, This_Server, ERR_NEEDMOREPARAMS_MSG, Client_Nick( Client ), Req->command ); - - /* Ist ueberhaupt ein Operator gesetzt? */ - if(( ! Conf_Oper[0] ) || ( ! Conf_OperPwd[0] )) return IRC_WriteStrClient( Client, This_Server, ERR_PASSWDMISMATCH_MSG, Client_Nick( Client )); + + /* Operator suchen */ + for( i = 0; i < Conf_Oper_Count; i++) + { + if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break; + } + if( i >= Conf_Oper_Count ) return IRC_WriteStrClient( Client, This_Server, ERR_PASSWDMISMATCH_MSG, Client_Nick( Client )); /* Stimmt der Name und das Passwort? */ - if(( strcmp( Conf_Oper, Req->argv[0] ) != 0 ) || ( strcmp( Conf_OperPwd, Req->argv[1] ) != 0 )) return IRC_WriteStrClient( Client, This_Server, ERR_PASSWDMISMATCH_MSG, Client_Nick( Client )); + if(( strcmp( Conf_Oper[i].name, Req->argv[0] ) != 0 ) || ( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 )) return IRC_WriteStrClient( Client, This_Server, ERR_PASSWDMISMATCH_MSG, Client_Nick( Client )); if( ! strchr( Client->modes, 'o' )) { @@ -704,7 +713,19 @@ GLOBAL BOOLEAN IRC_USERHOST( CLIENT *Client, REQUEST *Req ) if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0'; return IRC_WriteStrClient( Client, This_Server, rpl, Client->nick ); -} /* IRC_USERHOST */ +} /* IRC_USERHOST */ + + +GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req ) +{ + assert( Client != NULL ); + assert( Req != NULL ); + + if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s!%s@%s\"!", Client_Nick( Client ), Client->user, Client->host ); + else Log( LOG_NOTICE, "Got ERROR from \"%s!%s@%s\": %s!", Client_Nick( Client ), Client->user, Client->host, Req->argv[0] ); + + return CONNECTED; +} /* IRC_ERROR */ LOCAL BOOLEAN Check_Valid_User( CLIENT *Client ) diff --git a/src/ngircd/irc.h b/src/ngircd/irc.h index 0576b01e..ff0572cf 100644 --- a/src/ngircd/irc.h +++ b/src/ngircd/irc.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: irc.h,v 1.11 2001/12/31 15:33:13 alex Exp $ + * $Id: irc.h,v 1.12 2002/01/02 02:44:37 alex Exp $ * * irc.h: IRC-Befehle (Header) * * $Log: irc.h,v $ + * Revision 1.12 2002/01/02 02:44:37 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.11 2001/12/31 15:33:13 alex * - neuer Befehl NAMES, kleinere Bugfixes. * - Bug bei PING behoben: war zu restriktiv implementiert :-) @@ -90,6 +93,8 @@ GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req ); GLOBAL BOOLEAN IRC_DIE( CLIENT *Client, REQUEST *Req ); GLOBAL BOOLEAN IRC_RESTART( CLIENT *Client, REQUEST *Req ); +GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req ); + #endif diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c index eb40e7e3..10aa1a06 100644 --- a/src/ngircd/ngircd.c +++ b/src/ngircd/ngircd.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: ngircd.c,v 1.15 2001/12/31 02:18:51 alex Exp $ + * $Id: ngircd.c,v 1.16 2002/01/02 02:44:37 alex Exp $ * * ngircd.c: Hier beginnt alles ;-) * * $Log: ngircd.c,v $ + * Revision 1.16 2002/01/02 02:44:37 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.15 2001/12/31 02:18:51 alex * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART), * - neuen Header "defines.h" mit (fast) allen Konstanten. @@ -79,6 +82,8 @@ #include #include #include +#include +#include #include #include "channel.h" @@ -162,6 +167,7 @@ LOCAL VOID Initialize_Signal_Handler( VOID ) sigaction( SIGINT, &saction, NULL ); sigaction( SIGQUIT, &saction, NULL ); sigaction( SIGTERM, &saction, NULL); + sigaction( SIGCHLD, &saction, NULL); /* einige Signale ignorieren */ saction.sa_handler = SIG_IGN; @@ -184,6 +190,10 @@ LOCAL VOID Signal_Handler( INT Signal ) Log( LOG_WARNING, "Got signal %d, terminating now ...", Signal ); NGIRCd_Quit = TRUE; break; + case SIGCHLD: + /* Child-Prozess wurde beendet. Zombies vermeiden: */ + while( waitpid( -1, NULL, WNOHANG ) > 0); + break; default: /* unbekanntes bzw. unbehandeltes Signal */ Log( LOG_NOTICE, "Got signal %d! Ignored.", Signal ); diff --git a/src/ngircd/ngircd.h b/src/ngircd/ngircd.h index 35849c6a..2fc8494f 100644 --- a/src/ngircd/ngircd.h +++ b/src/ngircd/ngircd.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen * der GNU General Public License (GPL), wie von der Free Software Foundation @@ -9,11 +9,14 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: ngircd.h,v 1.5 2001/12/31 03:06:03 alex Exp $ + * $Id: ngircd.h,v 1.6 2002/01/02 02:44:37 alex Exp $ * * ngircd.h: Prototypen aus dem "Haupt-Modul" * * $Log: ngircd.h,v $ + * Revision 1.6 2002/01/02 02:44:37 alex + * - neue Defines fuer max. Anzahl Server und Operatoren. + * * Revision 1.5 2001/12/31 03:06:03 alex * - das #include fuer time.h hat noch gefehlt. *