X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fconn.c;h=9daca8531b34bef97a30d63290fdd1eee7df4498;hp=4367754061ab7779423af62dcefcc66f25b9a649;hb=79ca5fe04d0081468aa09cf0a7caca45a45b9864;hpb=73fd26e9fa708727e3f870052df0cc32e295bfc0 diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c index 43677540..9daca853 100644 --- a/src/ngircd/conn.c +++ b/src/ngircd/conn.c @@ -21,9 +21,9 @@ #include "imp.h" #include #ifdef PROTOTYPES -# include +# include #else -# include +# include #endif #include #include @@ -53,20 +53,22 @@ #include "array.h" #include "defines.h" -#include "resolve.h" #include "exp.h" #include "conn.h" #include "imp.h" #include "ngircd.h" +#include "array.h" #include "client.h" #include "conf.h" #include "conn-ssl.h" #include "conn-zip.h" #include "conn-func.h" #include "log.h" +#include "ng_ipaddr.h" #include "parse.h" +#include "resolve.h" #include "tool.h" #ifdef ZEROCONF @@ -205,7 +207,7 @@ cb_connserver(int sock, UNUSED short what) if (ng_ipaddr_af(&Conf_Server[server].dst_addr[0])) { /* more addresses to try... */ - New_Server(res, &Conf_Server[server].dst_addr[0]); + New_Server(server, &Conf_Server[server].dst_addr[0]); /* connection to dst_addr[0] is now in progress, so * remove this address... */ Conf_Server[server].dst_addr[0] = @@ -342,7 +344,7 @@ cb_clientserver_ssl(int sock, short what) case 0: return; /* EAGAIN: callback will be invoked again by IO layer */ default: - Conn_Close(idx, "Socket closed!", "SSL accept error", false); + Conn_Close(idx, "SSL accept error, closing socket", "SSL accept error", false); return; } if (what & IO_WANTREAD) @@ -417,6 +419,23 @@ Conn_Exit( void ) } /* Conn_Exit */ +/** + * Close all sockets (file descriptors) of open connections. + * This is useful in forked child processes, for example, to make sure that + * they don't hold connections open that the main process wants to close. + */ +GLOBAL void +Conn_CloseAllSockets(void) +{ + CONN_ID idx; + + for(idx = 0; idx < Pool_Size; idx++) { + if(My_Connections[idx].sock > NONE) + close(My_Connections[idx].sock); + } +} + + static unsigned int ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short)) { @@ -458,11 +477,6 @@ Conn_InitListeners( void ) unsigned int created = 0; char *copy, *listen_addr; - if (!io_library_init(CONNECTION_POOL)) { - Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno)); - return -1; - } - assert(Conf_ListenAddress); /* can't use Conf_ListenAddress directly, see below */ @@ -667,9 +681,11 @@ SSL_WantWrite(const CONNECTION *c) } #else static inline bool -SSL_WantRead(UNUSED const CONNECTION *c) { return false; } +SSL_WantRead(UNUSED const CONNECTION *c) +{ return false; } static inline bool -SSL_WantWrite(UNUSED const CONNECTION *c) { return false; } +SSL_WantWrite(UNUSED const CONNECTION *c) +{ return false; } #endif @@ -696,10 +712,6 @@ Conn_Handler(void) Rendezvous_Handler(); #endif - /* Should the configuration be reloaded? */ - if (NGIRCd_SignalRehash) - NGIRCd_Rehash(); - /* Check configured servers and established links */ Check_Servers(); Check_Connections(); @@ -752,8 +764,9 @@ Conn_Handler(void) if (SSL_WantWrite(&My_Connections[i])) continue; /* TLS/SSL layer needs to write data; deal with this first */ #endif - if (Resolve_INPROGRESS(&My_Connections[i].res_stat)) { - /* Wait for completion of resolver sub-process ... */ + if (Proc_InProgress(&My_Connections[i].proc_stat)) { + /* Wait for completion of forked subprocess + * and ignore the socket in the meantime ... */ io_event_del(My_Connections[i].sock, IO_WANTREAD); continue; @@ -769,6 +782,7 @@ Conn_Handler(void) IO_WANTREAD); continue; } + io_event_add(My_Connections[i].sock, IO_WANTREAD); } @@ -809,12 +823,12 @@ Conn_Handler(void) */ #ifdef PROTOTYPES GLOBAL bool -Conn_WriteStr( CONN_ID Idx, char *Format, ... ) +Conn_WriteStr(CONN_ID Idx, const char *Format, ...) #else GLOBAL bool -Conn_WriteStr( Idx, Format, va_alist ) +Conn_WriteStr(Idx, Format, va_alist) CONN_ID Idx; -char *Format; +const char *Format; va_dcl #endif { @@ -1070,10 +1084,6 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie in_k, out_k); } - /* cancel running resolver */ - if (Resolve_INPROGRESS(&My_Connections[Idx].res_stat)) - Resolve_Shutdown(&My_Connections[Idx].res_stat); - /* Servers: Modify time of next connect attempt? */ Conf_UnsetServer( Idx ); @@ -1122,32 +1132,32 @@ Conn_CountAccepted(void) } /* Conn_CountAccepted */ +/** + * Synchronize established connections and configured server structures + * after a configuration update and store the correct connection IDs, if any. + */ GLOBAL void -Conn_SyncServerStruct( void ) +Conn_SyncServerStruct(void) { - /* Synchronize server structures (connection IDs): - * connections <-> configuration */ - CLIENT *client; CONN_ID i; int c; - for( i = 0; i < Pool_Size; i++ ) { - /* Established connection? */ - if (My_Connections[i].sock < 0) + for (i = 0; i < Pool_Size; i++) { + if (My_Connections[i].sock == NONE) continue; - /* Server connection? */ - client = Conn_GetClient( i ); - if(( ! client ) || ( Client_Type( client ) != CLIENT_SERVER )) continue; + /* Server link? */ + client = Conn_GetClient(i); + if (!client || Client_Type(client) != CLIENT_SERVER) + continue; - for( c = 0; c < MAX_SERVERS; c++ ) - { + for (c = 0; c < MAX_SERVERS; c++) { /* Configured server? */ - if( ! Conf_Server[c].host[0] ) continue; + if (!Conf_Server[c].host[0]) + continue; - /* Duplicate? */ - if( strcmp( Conf_Server[c].name, Client_ID( client )) == 0 ) + if (strcasecmp(Conf_Server[c].name, Client_ID(client)) == 0) Conf_Server[c].conn_id = i; } } @@ -1374,14 +1384,9 @@ New_Connection(int Sock) identsock = -1; #endif if (!Conf_NoDNS) - Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr, + Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr, identsock, cb_Read_Resolver_Result); - /* ngIRCd waits up to 4 seconds for the result of the asynchronous - * DNS and IDENT resolver subprocess using the "penalty" mechanism. - * If there are results earlier, the delay is aborted. */ - Conn_SetPenalty(new_sock, 4); - Account_Connection(); return new_sock; } /* New_Connection */ @@ -1495,7 +1500,7 @@ Read_Request( CONN_ID Idx ) * 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(). - * Set "lastping", too, so we can handle time shifts backwards ... */ + * Update "lastping", too, if time shifted backwards ... */ c = Conn_GetClient(Idx); if (c && (Client_Type(c) == CLIENT_USER || Client_Type(c) == CLIENT_SERVER @@ -1505,7 +1510,8 @@ Read_Request( CONN_ID Idx ) My_Connections[Idx].bps = 0; My_Connections[Idx].lastdata = t; - My_Connections[Idx].lastping = My_Connections[Idx].lastdata; + if (My_Connections[Idx].lastping > t) + My_Connections[Idx].lastping = t; } /* Look at the data in the (read-) buffer of this connection */ @@ -1673,11 +1679,14 @@ Handle_Buffer(CONN_ID Idx) } /* Handle_Buffer */ +/** + * Check whether established connections are still alive or not. + * If not, play PING-PONG first; and if that doesn't help either, + * disconnect the respective peer. + */ static void Check_Connections(void) { - /* check if connections are alive. if not, play PING-PONG first. - * if this doesn't help either, disconnect client. */ CLIENT *c; CONN_ID i; char msg[64]; @@ -1729,42 +1738,50 @@ Check_Connections(void) } /* Check_Connections */ +/** + * Check if further server links should be established. + */ static void -Check_Servers( void ) +Check_Servers(void) { - /* Check if we can establish further server links */ - int i, n; time_t time_now; + time_now = time(NULL); + /* Check all configured servers */ - for( i = 0; i < MAX_SERVERS; i++ ) { - /* Valid outgoing server which isn't already connected or disabled? */ - if(( ! Conf_Server[i].host[0] ) || ( ! Conf_Server[i].port > 0 ) || - ( Conf_Server[i].conn_id > NONE ) || ( Conf_Server[i].flags & CONF_SFLAG_DISABLED )) - continue; + for (i = 0; i < MAX_SERVERS; i++) { + if (Conf_Server[i].conn_id != NONE) + continue; /* Already establishing or connected */ + if (!Conf_Server[i].host[0] || !Conf_Server[i].port > 0) + continue; /* No host and/or port configured */ + if (Conf_Server[i].flags & CONF_SFLAG_DISABLED) + continue; /* Disabled configuration entry */ + if (Conf_Server[i].lasttry > (time_now - Conf_ConnectRetry)) + continue; /* We have to wait a little bit ... */ /* Is there already a connection in this group? */ - if( Conf_Server[i].group > NONE ) { + if (Conf_Server[i].group > NONE) { for (n = 0; n < MAX_SERVERS; n++) { - if (n == i) continue; + if (n == i) + continue; if ((Conf_Server[n].conn_id != NONE) && - (Conf_Server[n].group == Conf_Server[i].group)) - break; + (Conf_Server[n].group == Conf_Server[i].group)) + break; } - if (n < MAX_SERVERS) continue; + if (n < MAX_SERVERS) + continue; } - /* Check last connect attempt? */ - time_now = time(NULL); - if( Conf_Server[i].lasttry > (time_now - Conf_ConnectRetry)) - continue; - /* Okay, try to connect now */ + Log(LOG_NOTICE, + "Preparing to establish a new server link for \"%s\" ...", + Conf_Server[i].name); Conf_Server[i].lasttry = time_now; Conf_Server[i].conn_id = SERVER_WAIT; - assert(Resolve_Getfd(&Conf_Server[i].res_stat) < 0); - Resolve_Name(&Conf_Server[i].res_stat, Conf_Server[i].host, cb_Connect_to_Server); + assert(Proc_GetPipeFd(&Conf_Server[i].res_stat) < 0); + Resolve_Name(&Conf_Server[i].res_stat, Conf_Server[i].host, + cb_Connect_to_Server); } } /* Check_Servers */ @@ -1784,8 +1801,9 @@ New_Server( int Server , ng_ipaddr_t *dest) return; } - Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ", - Conf_Server[Server].host, ip_str, Conf_Server[Server].port ); + Log(LOG_INFO, "Establishing connection for \"%s\" to \"%s\" (%s) port %d ... ", + Conf_Server[Server].name, Conf_Server[Server].host, ip_str, + Conf_Server[Server].port); af_dest = ng_ipaddr_af(dest); new_sock = socket(af_dest, SOCK_STREAM, 0); @@ -1886,7 +1904,7 @@ Init_Conn_Struct(CONN_ID Idx) My_Connections[Idx].signon = now; My_Connections[Idx].lastdata = now; My_Connections[Idx].lastprivmsg = now; - Resolve_Init(&My_Connections[Idx].res_stat); + Proc_InitStruct(&My_Connections[Idx].proc_stat); } /* Init_Conn_Struct */ @@ -1917,8 +1935,8 @@ Init_Socket( int Sock ) LogDebug("Setting IP_TOS on socket %d to IPTOS_LOWDELAY.", Sock); if (setsockopt(Sock, IPPROTO_IP, IP_TOS, &value, (socklen_t) sizeof(value))) { - Log(LOG_ERR, "Can't set socket option IP_TOS: %s!", - strerror(errno)); + LogDebug("Can't set socket option IP_TOS: %s!", + strerror(errno)); /* ignore this error */ } #endif @@ -1941,7 +1959,7 @@ cb_Connect_to_Server(int fd, UNUSED short events) LogDebug("Resolver: Got forward lookup callback on fd %d, events %d", fd, events); for (i=0; i < MAX_SERVERS; i++) { - if (Resolve_Getfd(&Conf_Server[i].res_stat) == fd ) + if (Proc_GetPipeFd(&Conf_Server[i].res_stat) == fd ) break; } @@ -1953,9 +1971,12 @@ cb_Connect_to_Server(int fd, UNUSED short events) } /* Read result from pipe */ - len = Resolve_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs)); - if (len == 0) + len = Proc_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs)); + if (len == 0) { + /* Error resolving hostname: reset server structure */ + Conf_Server[i].conn_id = NONE; return; + } assert((len % sizeof(ng_ipaddr_t)) == 0); @@ -1986,7 +2007,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) * IDENT user name.*/ CLIENT *c; - int i; + CONN_ID i; size_t len; char *identptr; #ifdef IDENTAUTH @@ -1996,14 +2017,8 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) #endif LogDebug("Resolver: Got callback on fd %d, events %d", r_fd, events ); - - /* Search associated connection ... */ - for( i = 0; i < Pool_Size; i++ ) { - if(( My_Connections[i].sock != NONE ) - && ( Resolve_Getfd(&My_Connections[i].res_stat) == r_fd )) - break; - } - if( i >= Pool_Size ) { + i = Conn_GetFromProc(r_fd); + if (i == NONE) { /* Ops, none found? Probably the connection has already * been closed!? We'll ignore that ... */ io_close( r_fd ); @@ -2012,7 +2027,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) } /* Read result from pipe */ - len = Resolve_Read(&My_Connections[i].res_stat, readbuf, sizeof readbuf -1); + len = Proc_Read(&My_Connections[i].proc_stat, readbuf, sizeof readbuf -1); if (len == 0) return; @@ -2055,8 +2070,6 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) #ifdef DEBUG else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i ); #endif - /* Reset penalty time */ - Conn_ResetPenalty( i ); } /* cb_Read_Resolver_Result */ @@ -2107,6 +2120,42 @@ Conn_GetClient( CONN_ID Idx ) return c ? c->client : NULL; } +/** + * Get PROC_STAT sub-process structure of a connection. + * @param Idx Connection index number + * @return PROC_STAT structure + */ +GLOBAL PROC_STAT * +Conn_GetProcStat(CONN_ID Idx) +{ + CONNECTION *c; + + assert(Idx >= 0); + c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx); + assert(c != NULL); + return &c->proc_stat; +} /* Conn_GetProcStat */ + + +/** + * Get CONN_ID from file descriptor associated to a subprocess structure. + * @param fd File descriptor + * @return CONN_ID or NONE (-1) + */ +GLOBAL CONN_ID +Conn_GetFromProc(int fd) +{ + int i; + + assert(fd > 0); + for (i = 0; i < Pool_Size; i++) { + if ((My_Connections[i].sock != NONE) + && (Proc_GetPipeFd(&My_Connections[i].proc_stat) == fd)) + return i; + } + return NONE; +} /* Conn_GetFromProc */ + #ifdef SSL_SUPPORT @@ -2144,4 +2193,28 @@ Conn_UsesSSL(CONN_ID Idx) #endif +#ifdef DEBUG + +GLOBAL void +Conn_DebugDump(void) +{ + int i; + + Log(LOG_DEBUG, "Connection status:"); + for (i = 0; i < Pool_Size; i++) { + if (My_Connections[i].sock == NONE) + continue; + Log(LOG_DEBUG, + " - %d: host=%s, lastdata=%ld, lastping=%ld, delaytime=%ld, flag=%d, options=%d, bps=%d, client=%s", + My_Connections[i].sock, My_Connections[i].host, + My_Connections[i].lastdata, My_Connections[i].lastping, + My_Connections[i].delaytime, My_Connections[i].flag, + My_Connections[i].options, My_Connections[i].bps, + My_Connections[i].client ? Client_ID(My_Connections[i].client) : "-"); + } +} /* Conn_DumpClients */ + +#endif + + /* -eof- */