X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fconn.c;h=165d4678b472d41b729f90a09113055fda87bd97;hp=e9f1223e77ee522da8906784e0b53561c2adcf58;hb=c12dc45f17336141bb947275e12125e5736cf0b3;hpb=4715b17106a3cf4181833670e713be2a307c6a62 diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c index e9f1223e..165d4678 100644 --- a/src/ngircd/conn.c +++ b/src/ngircd/conn.c @@ -17,7 +17,7 @@ #include "portab.h" #include "io.h" -static char UNUSED id[] = "$Id: conn.c,v 1.161 2005/07/11 14:56:38 fw Exp $"; +static char UNUSED id[] = "$Id: conn.c,v 1.175 2005/08/29 11:11:15 alex Exp $"; #include "imp.h" #include @@ -82,19 +82,19 @@ static char UNUSED id[] = "$Id: conn.c,v 1.161 2005/07/11 14:56:38 fw Exp $"; #define SERVER_WAIT (NONE - 1) -LOCAL bool Handle_Write PARAMS(( CONN_ID Idx )); -LOCAL void New_Connection PARAMS(( int Sock )); -LOCAL CONN_ID Socket2Index PARAMS(( int Sock )); -LOCAL void Read_Request PARAMS(( CONN_ID Idx )); -LOCAL bool Handle_Buffer PARAMS(( CONN_ID Idx )); -LOCAL void Check_Connections PARAMS(( void )); -LOCAL void Check_Servers PARAMS(( void )); -LOCAL void Init_Conn_Struct PARAMS(( CONN_ID Idx )); -LOCAL bool Init_Socket PARAMS(( int Sock )); -LOCAL void New_Server PARAMS(( int Server, CONN_ID Idx )); -LOCAL void Simple_Message PARAMS(( int Sock, char *Msg )); -LOCAL int Count_Connections PARAMS(( struct sockaddr_in addr )); -LOCAL int NewListener PARAMS(( const UINT16 Port )); +static bool Handle_Write PARAMS(( CONN_ID Idx )); +static int New_Connection PARAMS(( int Sock )); +static CONN_ID Socket2Index PARAMS(( int Sock )); +static void Read_Request PARAMS(( CONN_ID Idx )); +static bool Handle_Buffer PARAMS(( CONN_ID Idx )); +static void Check_Connections PARAMS(( void )); +static void Check_Servers PARAMS(( void )); +static void Init_Conn_Struct PARAMS(( CONN_ID Idx )); +static bool Init_Socket PARAMS(( int Sock )); +static void New_Server PARAMS(( int Server, CONN_ID Idx )); +static void Simple_Message PARAMS(( int Sock, char *Msg )); +static int Count_Connections PARAMS(( struct sockaddr_in addr )); +static int NewListener PARAMS(( const UINT16 Port )); static array My_Listeners; @@ -103,6 +103,7 @@ int allow_severity = LOG_INFO; int deny_severity = LOG_ERR; #endif +static void server_login PARAMS((CONN_ID idx)); static void cb_clientserver PARAMS((int sock, short what)); @@ -115,7 +116,7 @@ cb_listen(int sock, short irrelevant) static void -cb_connserver(int sock, short what) +cb_connserver(int sock, UNUSED short what) { int res, err; socklen_t sock_len; @@ -158,7 +159,13 @@ cb_connserver(int sock, short what) } Conn_OPTION_DEL( &My_Connections[idx], CONN_ISCONNECTING ); + server_login(idx); +} + +static void +server_login(CONN_ID idx) +{ Log( LOG_INFO, "Connection %d with \"%s:%d\" established. Now logging in ...", idx, My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port ); @@ -191,7 +198,7 @@ cb_clientserver(int sock, short what) } -LOCAL void +static void FreeRes_stat( CONNECTION *c ) { assert( c != NULL ); @@ -201,6 +208,7 @@ FreeRes_stat( CONNECTION *c ) io_close( c->res_stat->pipe[0] ); + array_free(&c->res_stat->buffer); free( c->res_stat ); c->res_stat = NULL; } @@ -274,34 +282,50 @@ Conn_Exit( void ) } /* Conn_Exit */ +static unsigned int +ports_initlisteners(array *a, void (*func)(int,short)) +{ + unsigned int created = 0, len; + int fd; + UINT16 *port; + + len = array_length(a, sizeof (UINT16)); + port = array_start(a); + while(len--) { + fd = NewListener( *port ); + if (fd < 0) { + port++; + continue; + } + if (!io_event_create( fd, IO_WANTREAD, func )) { + Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!", + fd, (unsigned int) *port, strerror(errno)); + close(fd); + port++; + continue; + } + created++; + port++; + } + + return created; +} + + GLOBAL int Conn_InitListeners( void ) { /* Initialize ports on which the server should accept connections */ - int created, fd; - unsigned int i; + unsigned int created; if (!io_library_init(CONNECTION_POOL)) { Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno)); return -1; } - created = 0; - for( i = 0; i < Conf_ListenPorts_Count; i++ ) { - fd = NewListener( Conf_ListenPorts[i] ); - if (fd < 0) { - Log( LOG_ERR, "Can't listen on port %u!", (unsigned int) Conf_ListenPorts[i] ); - continue; - } - if (!io_event_create( fd, IO_WANTREAD, cb_listen )) { - Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!", - fd, (unsigned int) Conf_ListenPorts[i], strerror(errno)); - close(fd); - continue; - } - created++; - } + created = ports_initlisteners(&Conf_ListenPorts, cb_listen); + return created; } /* Conn_InitListeners */ @@ -333,7 +357,8 @@ Conn_ExitListeners( void ) } /* Conn_ExitListeners */ -LOCAL int +/* return new listening port file descriptor or -1 on failure */ +static int NewListener( const UINT16 Port ) { /* Create new listening socket on specified port */ @@ -436,16 +461,11 @@ NewListener( const UINT16 Port ) GLOBAL void Conn_Handler( void ) { - /* "Hauptschleife": Aktive Verbindungen ueberwachen. Folgende Aktionen - * werden dabei durchgefuehrt, bis der Server terminieren oder neu - * starten soll: - * - * - neue Verbindungen annehmen, - * - Server-Verbindungen aufbauen, - * - geschlossene Verbindungen loeschen, - * - volle Schreibpuffer versuchen zu schreiben, - * - volle Lesepuffer versuchen zu verarbeiten, - * - Antworten von Resolver Sub-Prozessen annehmen. + /* "Main Loop.": Loop until a signal (for shutdown or restart) arrives. + * Call io_dispatch() to check for read/writeable sockets every second + * Wait for status change on pending connections (e.g: when the hostname has been resolved) + * check for penalty/timeouts + * handle input buffers */ int i; unsigned int wdatalen; @@ -486,7 +506,7 @@ Conn_Handler( void ) for( i = 0; i < Pool_Size; i++ ) { if ( My_Connections[i].sock <= NONE ) continue; - + wdatalen = array_bytes(&My_Connections[i].wbuf); #ifdef ZLIB @@ -716,24 +736,29 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) c = Client_GetFromConn( Idx ); /* Should the client be informed? */ - if( InformClient ) - { + if (InformClient) { #ifndef STRICT_RFC /* Send statistics to client if registered as user: */ - if(( c != NULL ) && ( Client_Type( c ) == CLIENT_USER )) - { - Conn_WriteStr( Idx, "NOTICE %s :%sConnection statistics: client %.1f kb, server %.1f kb.", Client_ThisServer( ), NOTICE_TXTPREFIX, (double)My_Connections[Idx].bytes_in / 1024, (double)My_Connections[Idx].bytes_out / 1024 ); + if ((c != NULL) && (Client_Type(c) == CLIENT_USER)) { + Conn_WriteStr( Idx, + ":%s NOTICE %s :%sConnection statistics: client %.1f kb, server %.1f kb.", + Client_ID(Client_ThisServer()), Client_ID(c), + NOTICE_TXTPREFIX, + (double)My_Connections[Idx].bytes_in / 1024, + (double)My_Connections[Idx].bytes_out / 1024); } #endif /* Send ERROR to client (see RFC!) */ - if( FwdMsg ) Conn_WriteStr( Idx, "ERROR :%s", FwdMsg ); - else Conn_WriteStr( Idx, "ERROR :Closing connection." ); + if (FwdMsg) + Conn_WriteStr(Idx, "ERROR :%s", FwdMsg); + else + Conn_WriteStr(Idx, "ERROR :Closing connection."); } /* Try to write out the write buffer */ (void)Handle_Write( Idx ); - + /* Shut down socket */ if( ! io_close( My_Connections[Idx].sock )) { @@ -823,7 +848,7 @@ Conn_SyncServerStruct( void ) } /* SyncServerStruct */ -LOCAL bool +static bool Handle_Write( CONN_ID Idx ) { /* Daten aus Schreibpuffer versenden bzw. Connection aufbauen */ @@ -839,7 +864,6 @@ Handle_Write( CONN_ID Idx ) } assert( My_Connections[Idx].sock > NONE ); - wdatalen = array_bytes(&My_Connections[Idx].wbuf ); #ifdef ZLIB if(( wdatalen == 0 ) && ( ! array_bytes(&My_Connections[Idx].zip.wbuf))) { @@ -875,7 +899,7 @@ Handle_Write( CONN_ID Idx ) } /* Handle_Write */ -LOCAL void +static int New_Connection( int Sock ) { /* Neue Client-Verbindung von Listen-Socket annehmen und @@ -899,7 +923,7 @@ New_Connection( int Sock ) if( new_sock < 0 ) { Log( LOG_CRIT, "Can't accept connection: %s!", strerror( errno )); - return; + return -1; } #ifdef TCPWRAP @@ -912,7 +936,7 @@ New_Connection( int Sock ) Log( deny_severity, "Refused connection from %s (by TCP Wrappers)!", inet_ntoa( new_addr.sin_addr )); Simple_Message( new_sock, "ERROR :Connection refused" ); close( new_sock ); - return; + return -1; } #endif @@ -927,7 +951,7 @@ New_Connection( int Sock ) Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP address!", inet_ntoa( new_addr.sin_addr ), cnt); Simple_Message( new_sock, "ERROR :Connection refused, too many connections from your IP address!" ); close( new_sock ); - return; + return -1; } /* Freie Connection-Struktur suchen */ @@ -948,7 +972,7 @@ New_Connection( int Sock ) Log( LOG_ALERT, "Can't accept connection: limit (%d) reached!", Pool_Size ); Simple_Message( new_sock, "ERROR :Connection limit reached" ); close( new_sock ); - return; + return -1; } if( new_size > Conf_MaxConnections ) new_size = Conf_MaxConnections; } @@ -957,16 +981,15 @@ New_Connection( int Sock ) Log( LOG_ALERT, "Can't accept connection: limit (%d) reached -- overflow!", Pool_Size ); Simple_Message( new_sock, "ERROR :Connection limit reached" ); close( new_sock ); - return; + return -1; } ptr = (POINTER *)realloc( My_Connections, sizeof( CONNECTION ) * new_size ); - if( ! ptr ) - { + if( ! ptr ) { Log( LOG_EMERG, "Can't allocate memory! [New_Connection]" ); Simple_Message( new_sock, "ERROR: Internal error" ); close( new_sock ); - return; + return -1; } #ifdef DEBUG @@ -986,12 +1009,11 @@ New_Connection( int Sock ) /* Client-Struktur initialisieren */ c = Client_NewLocal( idx, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWN, false ); - if( ! c ) - { + if( ! c ) { Log( LOG_ALERT, "Can't accept connection: can't create client structure!" ); Simple_Message( new_sock, "ERROR :Internal error" ); close( new_sock ); - return; + return -1; } /* Verbindung registrieren */ @@ -1000,7 +1022,11 @@ New_Connection( int Sock ) My_Connections[idx].addr = new_addr; /* Neuen Socket registrieren */ - io_event_create( new_sock, IO_WANTREAD, cb_clientserver); + if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) { + Simple_Message( new_sock, "ERROR :Internal error" ); + Conn_Close( idx, "io_event_create() failed", NULL, false ); + return -1; + } Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", idx, inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock ); @@ -1017,10 +1043,11 @@ New_Connection( int Sock ) /* Penalty-Zeit setzen */ Conn_SetPenalty( idx, 4 ); + return new_sock; } /* New_Connection */ -LOCAL CONN_ID +static CONN_ID Socket2Index( int Sock ) { /* zum Socket passende Connection suchen */ @@ -1044,32 +1071,20 @@ Socket2Index( int Sock ) } /* Socket2Index */ -LOCAL void +static void Read_Request( CONN_ID Idx ) { /* Daten von Socket einlesen und entsprechend behandeln. * Tritt ein Fehler auf, so wird der Socket geschlossen. */ - unsigned int bsize; int len; char readbuf[1024]; -#ifdef ZLIB CLIENT *c; -#endif assert( Idx > NONE ); assert( My_Connections[Idx].sock > NONE ); - /* wenn noch nicht registriert: maximal mit ZREADBUFFER_LEN arbeiten, - * ansonsten koennen Daten ggf. nicht umkopiert werden. */ - bsize = READBUFFER_LEN; #ifdef ZLIB - c = Client_GetFromConn( Idx ); - - if(( Client_Type( c ) != CLIENT_USER ) && ( Client_Type( c ) != CLIENT_SERVER ) && - ( Client_Type( c ) != CLIENT_SERVICE ) && ( bsize > ZREADBUFFER_LEN )) - bsize = ZREADBUFFER_LEN; - if (( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN ) || ( array_bytes(&My_Connections[Idx].zip.rbuf) >= ZREADBUFFER_LEN )) #else @@ -1083,14 +1098,15 @@ Read_Request( CONN_ID Idx ) return; } - len = read( My_Connections[Idx].sock, readbuf, sizeof readbuf ); + len = read( My_Connections[Idx].sock, readbuf, sizeof readbuf -1 ); if( len == 0 ) { Log( LOG_INFO, "%s:%d (%s) is closing the connection ...", - My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port), - inet_ntoa( My_Connections[Idx].addr.sin_addr )); + My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port), + inet_ntoa( My_Connections[Idx].addr.sin_addr )); Conn_Close( Idx, "Socket closed!", "Client closed connection", false ); return; } + if( len < 0 ) { if( errno == EAGAIN ) return; Log( LOG_ERR, "Read error on connection %d (socket %d): %s!", Idx, @@ -1115,17 +1131,25 @@ Read_Request( CONN_ID Idx ) } } - /* Connection-Statistik aktualisieren */ + /* Update connection statistics */ My_Connections[Idx].bytes_in += len; - /* Timestamp aktualisieren */ - My_Connections[Idx].lastdata = time( NULL ); - - Handle_Buffer( Idx ); + /* Update timestamp of last data received if this connection is + * registered as a user, server or service connection. Don't update + * otherwise, so users have at least Conf_PongTimeout seconds time to + * register with the IRC server -- see Check_Connections(). */ + c = Client_GetFromConn(Idx); + if (c && (Client_Type(c) == CLIENT_USER + || Client_Type(c) == CLIENT_SERVER + || Client_Type(c) == CLIENT_SERVICE)) + My_Connections[Idx].lastdata = time(NULL); + + /* Look at the data in the (read-) buffer of this connection */ + Handle_Buffer(Idx); } /* Read_Request */ -LOCAL bool +static bool Handle_Buffer( CONN_ID Idx ) { /* Handle Data in Connections Read-Buffer. @@ -1135,14 +1159,13 @@ Handle_Buffer( CONN_ID Idx ) #endif char *ptr; int len, delta; - unsigned int arraylen; - bool action, result; + bool result; #ifdef ZLIB bool old_z; #endif result = false; - do { + for (;;) { /* Check penalty */ if( My_Connections[Idx].delaytime > time( NULL )) return result; #ifdef ZLIB @@ -1151,16 +1174,12 @@ Handle_Buffer( CONN_ID Idx ) if( ! Unzip_Buffer( Idx )) return false; #endif - arraylen = array_bytes(&My_Connections[Idx].rbuf); - if (arraylen == 0) + if (0 == array_bytes(&My_Connections[Idx].rbuf)) break; - if (!array_cat0(&My_Connections[Idx].rbuf)) /* make sure buf is NULL terminated */ + if (!array_cat0_temporary(&My_Connections[Idx].rbuf)) /* make sure buf is NULL terminated */ return false; - array_truncate(&My_Connections[Idx].rbuf, 1, arraylen); /* do not count trailing NULL */ - - /* A Complete Request end with CR+LF, see RFC 2812. */ ptr = strstr( array_start(&My_Connections[Idx].rbuf), "\r\n" ); @@ -1178,7 +1197,6 @@ Handle_Buffer( CONN_ID Idx ) } #endif - action = false; if( ! ptr ) break; @@ -1196,33 +1214,36 @@ Handle_Buffer( CONN_ID Idx ) return false; } + if (len <= 2) { /* request was empty (only '\r\n') */ + array_moveleft(&My_Connections[Idx].rbuf, 1, delta); /* delta is either 1 or 2 */ + break; + } #ifdef ZLIB /* remember if stream is already compressed */ old_z = My_Connections[Idx].options & CONN_ZIP; #endif - if( len > delta ) - { - /* A Request was read */ - My_Connections[Idx].msg_in++; - if( ! Parse_Request( Idx, (char*)array_start(&My_Connections[Idx].rbuf) )) return false; - else action = true; - - array_moveleft(&My_Connections[Idx].rbuf, 1, len); + My_Connections[Idx].msg_in++; + if (!Parse_Request(Idx, (char*)array_start(&My_Connections[Idx].rbuf) )) + return false; + + result = true; + + array_moveleft(&My_Connections[Idx].rbuf, 1, len); #ifdef DEBUG - Log(LOG_DEBUG, "%d byte left in rbuf", array_bytes(&My_Connections[Idx].rbuf)); + Log(LOG_DEBUG, "%u byte left in rbuf", array_bytes(&My_Connections[Idx].rbuf)); #endif - } #ifdef ZLIB - if(( ! old_z ) && ( My_Connections[Idx].options & CONN_ZIP ) && ( array_bytes(&My_Connections[Idx].rbuf) > 0 )) + if(( ! old_z ) && ( My_Connections[Idx].options & CONN_ZIP ) && + ( array_bytes(&My_Connections[Idx].rbuf) > 0 )) { /* The last Command activated Socket-Compression. * Data that was read after that needs to be copied to Unzip-buf * for decompression */ if( array_bytes(&My_Connections[Idx].rbuf)> ZREADBUFFER_LEN ) { - /* No space left */ - Log( LOG_ALERT, "Can't move receive buffer: No space left in unzip buffer (need %d bytes)!", array_bytes(&My_Connections[Idx].rbuf )); + Log( LOG_ALERT, "Connection %d: No space left in unzip buf (need %u bytes)!", + Idx, array_bytes(&My_Connections[Idx].rbuf )); return false; } if (!array_copy( &My_Connections[Idx].zip.rbuf, &My_Connections[Idx].rbuf )) @@ -1230,18 +1251,18 @@ Handle_Buffer( CONN_ID Idx ) array_trunc(&My_Connections[Idx].rbuf); #ifdef DEBUG - Log( LOG_DEBUG, "Moved already received data (%d bytes) to uncompression buffer.", array_bytes(&My_Connections[Idx].zip.rbuf)); + Log( LOG_DEBUG, "Moved already received data (%u bytes) to uncompression buffer.", + array_bytes(&My_Connections[Idx].zip.rbuf)); #endif /* DEBUG */ } #endif /* ZLIB */ - if( action ) result = true; - } while( action ); + } return result; } /* Handle_Buffer */ -LOCAL void +static void Check_Connections( void ) { /* check if connections are alive. if not, play PING-PONG first. @@ -1277,21 +1298,26 @@ Check_Connections( void ) } else { - /* connection is not fully established yet */ - if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout ) - { - /* Timeout */ + /* The connection is not fully established yet, so + * we don't do the PING-PONG game here but instead + * disconnect the client after "a short time" if it's + * still not registered. */ + + if (My_Connections[i].lastdata < + time(NULL) - Conf_PongTimeout) { #ifdef DEBUG - Log( LOG_DEBUG, "Connection %d timed out ...", i ); + Log(LOG_DEBUG, + "Unregistered connection %d timed out ...", + i); #endif - Conn_Close( i, NULL, "Timeout", false ); + Conn_Close(i, NULL, "Timeout", false); } } } } /* Check_Connections */ -LOCAL void +static void Check_Servers( void ) { /* Check if we can establish further server links */ @@ -1359,7 +1385,7 @@ Check_Servers( void ) } /* Check_Servers */ -LOCAL void +static void New_Server( int Server, CONN_ID Idx ) { /* Establish new server link */ @@ -1373,13 +1399,10 @@ New_Server( int Server, CONN_ID Idx ) assert( Idx > NONE ); /* Did we get a valid IP address? */ - if( ! Conf_Server[Server].ip[0] ) - { + if( ! Conf_Server[Server].ip[0] ) { /* No. Free connection structure and abort: */ - Init_Conn_Struct( Idx ); - Conf_Server[Server].conn_id = NONE; Log( LOG_ERR, "Can't connect to \"%s\" (connection %d): ip address unknown!", Conf_Server[Server].host, Idx ); - return; + goto out; } Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d (connection %d) ... ", Conf_Server[Server].host, Conf_Server[Server].ip, Conf_Server[Server].port, Idx ); @@ -1393,10 +1416,8 @@ New_Server( int Server, CONN_ID Idx ) #endif { /* Can't convert IP address */ - Init_Conn_Struct( Idx ); - Conf_Server[Server].conn_id = NONE; 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; + goto out; } memset( &new_addr, 0, sizeof( new_addr )); @@ -1405,39 +1426,31 @@ New_Server( int Server, CONN_ID Idx ) new_addr.sin_port = htons( Conf_Server[Server].port ); new_sock = socket( PF_INET, SOCK_STREAM, 0 ); - if ( new_sock < 0 ) - { + if ( new_sock < 0 ) { /* Can't create socket */ - Init_Conn_Struct( Idx ); - Conf_Server[Server].conn_id = NONE; Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno )); - return; + goto out; } if( ! Init_Socket( new_sock )) return; res = connect( new_sock, (struct sockaddr *)&new_addr, sizeof( new_addr )); - if(( res != 0 ) && ( errno != EINPROGRESS )) - { + if(( res != 0 ) && ( errno != EINPROGRESS )) { /* Can't connect socket */ Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno )); close( new_sock ); - Init_Conn_Struct( Idx ); - Conf_Server[Server].conn_id = NONE; - return; + goto out; } /* Client-Struktur initialisieren */ c = Client_NewLocal( Idx, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWNSERVER, false ); - if( ! c ) - { + if( ! c ) { /* Can't create new client structure */ - close( new_sock ); - Init_Conn_Struct( Idx ); - Conf_Server[Server].conn_id = NONE; Log( LOG_ALERT, "Can't establish connection: can't create client structure!" ); - return; + close( new_sock ); + goto out; } + Client_SetIntroducer( c, c ); Client_SetToken( c, TOKEN_OUTBOUND ); @@ -1447,16 +1460,24 @@ New_Server( int Server, CONN_ID Idx ) strlcpy( My_Connections[Idx].host, Conf_Server[Server].host, sizeof( My_Connections[Idx].host )); /* Register new socket */ - io_event_create( new_sock, IO_WANTWRITE, cb_connserver); - Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCONNECTING ); + if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) { + Log( LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno)); + Conn_Close( Idx, "io_event_create() failed", NULL, false ); + goto out; + } #ifdef DEBUG Log( LOG_DEBUG, "Registered new connection %d on socket %d.", Idx, My_Connections[Idx].sock ); #endif + Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCONNECTING ); + return; +out: + Init_Conn_Struct( Idx ); + Conf_Server[Server].conn_id = NONE; } /* New_Server */ -LOCAL void +static void Init_Conn_Struct( CONN_ID Idx ) { time_t now = time( NULL ); @@ -1469,7 +1490,7 @@ Init_Conn_Struct( CONN_ID Idx ) } /* Init_Conn_Struct */ -LOCAL bool +static bool Init_Socket( int Sock ) { /* Initialize socket (set options) */ @@ -1515,11 +1536,14 @@ void Read_Resolver_Result( int r_fd ) * IDENT user name.*/ CLIENT *c; - int len, i, n; + int bytes_read, i, n; + unsigned int len; RES_STAT *s; char *ptr; + char *bufptr; + char readbuf[HOST_LEN]; - Log( LOG_DEBUG, "Resolver: started, fd %d\n", r_fd ); + Log( LOG_DEBUG, "Resolver: started, fd %d", r_fd ); /* Search associated connection ... */ for( i = 0; i < Pool_Size; i++ ) { @@ -1544,28 +1568,40 @@ void Read_Resolver_Result( int r_fd ) assert( s != NULL ); /* Read result from pipe */ - len = read( r_fd, s->buffer + s->bufpos, sizeof( s->buffer ) - s->bufpos - 1 ); - if( len < 0 ) - { + bytes_read = read( r_fd, readbuf, sizeof readbuf -1 ); + if( bytes_read < 0 ) { /* Error! */ Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror( errno )); FreeRes_stat( &My_Connections[i] ); return; } - s->bufpos += len; - s->buffer[s->bufpos] = '\0'; + len = (unsigned int) bytes_read; + readbuf[len] = '\0'; + if (!array_catb(&s->buffer, readbuf, len)) { + Log( LOG_CRIT, "Resolver: Can't append result %s to buffer: %s", readbuf, strerror( errno )); + FreeRes_stat(&My_Connections[i]); + return; + } + + if (!array_cat0_temporary(&s->buffer)) { + Log( LOG_CRIT, "Resolver: Can't append result %s to buffer: %s", readbuf, strerror( errno )); + FreeRes_stat(&My_Connections[i]); + return; + } /* If the result string is incomplete, return to main loop and * wait until we can read in more bytes. */ #ifdef IDENTAUTH try_resolve: #endif - ptr = strchr( s->buffer, '\n' ); + bufptr = (char*) array_start(&s->buffer); + assert(bufptr != NULL); + ptr = strchr( bufptr, '\n' ); if( ! ptr ) return; *ptr = '\0'; #ifdef DEBUG - Log( LOG_DEBUG, "Got result from resolver: \"%s\" (%d bytes), stage %d.", s->buffer, len, s->stage ); + Log( LOG_DEBUG, "Got result from resolver: \"%s\" (%u bytes read), stage %d.", bufptr, len, s->stage); #endif /* Okay, we got a complete result: this is a host name for outgoing @@ -1582,15 +1618,14 @@ try_resolve: { switch(s->stage) { case 0: /* host name */ - strlcpy( My_Connections[i].host, s->buffer, sizeof( My_Connections[i].host )); - Client_SetHostname( c, s->buffer ); + strlcpy( My_Connections[i].host, bufptr, sizeof( My_Connections[i].host)); + + Client_SetHostname( c, bufptr); #ifdef IDENTAUTH /* clean up buffer for IDENT result */ - len = strlen( s->buffer ) + 1; - assert((size_t) len <= sizeof( s->buffer )); - memmove( s->buffer, s->buffer + len, sizeof( s->buffer ) - len ); - assert(len <= s->bufpos ); - s->bufpos -= len; + len = strlen(bufptr) + 1; + assert(len <= array_bytes(&s->buffer)); + array_moveleft(&s->buffer, 1, len); /* Don't close pipe and clean up, but * instead wait for IDENT result */ @@ -1598,10 +1633,10 @@ try_resolve: goto try_resolve; case 1: /* IDENT user name */ - if( s->buffer[0] ) - { - Log( LOG_INFO, "IDENT lookup for connection %ld: \"%s\".", i, s->buffer ); - Client_SetUser( c, s->buffer, true ); + if (array_bytes(&s->buffer)) { + bufptr = (char*) array_start(&s->buffer); + Log( LOG_INFO, "IDENT lookup for connection %ld: \"%s\".", i, bufptr); + Client_SetUser( c, bufptr, true ); } else Log( LOG_INFO, "IDENT lookup for connection %ld: no result.", i ); #endif @@ -1623,7 +1658,8 @@ try_resolve: n = Conf_GetServer( i ); assert( n > NONE ); - strlcpy( Conf_Server[n].ip, s->buffer, sizeof( Conf_Server[n].ip )); + bufptr = (char*) array_start(&s->buffer); + strlcpy( Conf_Server[n].ip, bufptr, sizeof( Conf_Server[n].ip )); } /* Clean up ... */ @@ -1634,7 +1670,7 @@ try_resolve: } /* Read_Resolver_Result */ -LOCAL void +static void Simple_Message( int Sock, char *Msg ) { char buf[COMMAND_LEN]; @@ -1650,7 +1686,7 @@ Simple_Message( int Sock, char *Msg ) } /* Simple_Error */ -LOCAL int +static int Count_Connections( struct sockaddr_in addr_in ) { int i, cnt;