X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fconn.c;h=378509f96f09bc35eb9e3ebc2eb12140c24509fb;hp=f4511642c7c7b309c0e302de58cd7e184c172166;hb=8ab097afb743061c6c9b865bdb401ba51285c347;hpb=74c7d7131f6754e1afa9b1ec7b95e95824475c97 diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c index f4511642..378509f9 100644 --- a/src/ngircd/conn.c +++ b/src/ngircd/conn.c @@ -63,6 +63,7 @@ #include "client.h" #include "class.h" #include "conf.h" +#include "conn-encoding.h" #include "conn-ssl.h" #include "conn-zip.h" #include "conn-func.h" @@ -81,6 +82,8 @@ #define MAX_COMMANDS_SERVER_MIN 10 #define MAX_COMMANDS_SERVICE 10 +#define SD_LISTEN_FDS_START 3 + static bool Handle_Write PARAMS(( CONN_ID Idx )); static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len )); @@ -119,6 +122,40 @@ static void cb_Connect_to_Server PARAMS((int sock, UNUSED short what)); static void cb_clientserver PARAMS((int sock, short what)); +/** + * Get number of sockets available from systemd(8). + * + * ngIRCd needs to implement its own sd_listen_fds(3) function and can't + * use the one provided by systemd itself, becaus the sockets will be + * used in a forked child process with a new PID, and this would trigger + * an error in the standard implementation. + * + * @return Number of sockets available, -1 if sockets have already been + * initialized, or 0 when no sockets have been passed. + */ +static int +my_sd_listen_fds(void) +{ + const char *e; + long count; + + /* Check if LISTEN_PID exists; but we ignore the result, because + * normally ngircd forks a child before checking this, and therefore + * the PID set in the environment is always wrong ... */ + e = getenv("LISTEN_PID"); + if (!e || !*e) + return 0; + + e = getenv("LISTEN_FDS"); + if (!e || !*e) + return -1; + count = atol(e); + unsetenv("LISTEN_FDS"); + + return count; +} + + /** * IO callback for listening sockets: handle new connections. This callback * gets called when a new non-SSL connection should be accepted. @@ -204,7 +241,7 @@ cb_connserver(int sock, UNUSED short what) My_Connections[idx].host, Conf_Server[server].port, idx, strerror(err)); - Conn_Close(idx, "Can't connect!", NULL, false); + Conn_Close(idx, "Can't connect", NULL, false); if (ng_ipaddr_af(&Conf_Server[server].dst_addr[0])) { /* more addresses to try... */ @@ -281,7 +318,7 @@ cb_connserver_login_ssl(int sock, short unused) return; case -1: Log(LOG_ERR, "SSL connection on socket %d failed!", sock); - Conn_Close(idx, "Can't connect!", NULL, false); + Conn_Close(idx, "Can't connect", NULL, false); return; } @@ -453,7 +490,7 @@ Conn_CloseAllSockets(int ExceptOf) * @returns Number of listening sockets created. */ static unsigned int -ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short)) +Init_Listeners(array *a, const char *listen_addr, void (*func)(int,short)) { unsigned int created = 0; size_t len; @@ -469,8 +506,9 @@ ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short)) 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)); + Log(LOG_ERR, + "io_event_create(): Can't add fd %d (port %u): %s!", + fd, (unsigned int) *port, strerror(errno)); close(fd); port++; continue; @@ -493,13 +531,43 @@ Conn_InitListeners( void ) /* Initialize ports on which the server should accept connections */ unsigned int created = 0; char *copy, *listen_addr; + int count, fd, i; assert(Conf_ListenAddress); + count = my_sd_listen_fds(); + if (count < 0) { + Log(LOG_INFO, + "Not re-initializing listening sockets of systemd(8) ..."); + return 0; + } + if (count > 0) { + /* systemd(8) passed sockets to us, so don't try to initialize + * listening sockets on our own but use the passed ones */ + LogDebug("Initializing %d systemd sockets ...", count); + for (i = 0; i < count; i++) { + fd = SD_LISTEN_FDS_START + i; + Init_Socket(fd); + if (!io_event_create(fd, IO_WANTREAD, cb_listen)) { + Log(LOG_ERR, + "io_event_create(): Can't add fd %d: %s!", + fd, strerror(errno)); + continue; + } + Log(LOG_INFO, + "Initialized socket %d from systemd.", fd); + created++; + } + return created; + } + + /* not using systemd socket activation, initialize listening sockets: */ + /* can't use Conf_ListenAddress directly, see below */ copy = strdup(Conf_ListenAddress); if (!copy) { - Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, strerror(errno)); + Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, + strerror(errno)); return 0; } listen_addr = strtok(copy, ","); @@ -507,9 +575,11 @@ Conn_InitListeners( void ) while (listen_addr) { ngt_TrimStr(listen_addr); if (*listen_addr) { - created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen); + created += Init_Listeners(&Conf_ListenPorts, + listen_addr, cb_listen); #ifdef SSL_SUPPORT - created += ports_initlisteners(&Conf_SSLOptions.ListenPorts, listen_addr, cb_listen_ssl); + created += Init_Listeners(&Conf_SSLOptions.ListenPorts, + listen_addr, cb_listen_ssl); #endif } @@ -536,7 +606,12 @@ Conn_ExitListeners( void ) int *fd; size_t arraylen; + /* Get number of listening sockets to shut down. There can be none + * if ngIRCd has been "socket activated" by systemd. */ arraylen = array_length(&My_Listeners, sizeof (int)); + if (arraylen < 1) + return; + Log(LOG_INFO, "Shutting down all listening sockets (%d total) ...", arraylen); fd = array_start(&My_Listeners); @@ -567,7 +642,7 @@ InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port ret = ng_ipaddr_init(addr, listen_addrstr, Port); if (!ret) { assert(listen_addrstr); - Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"", + Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"!", listen_addrstr, Port, listen_addrstr); } return ret; @@ -619,8 +694,9 @@ NewListener(const char *listen_addr, UINT16 Port) af = ng_ipaddr_af(&addr); sock = socket(af, SOCK_STREAM, 0); - if( sock < 0 ) { - Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, strerror(errno)); + if (sock < 0) { + Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, + strerror(errno)); return -1; } @@ -630,22 +706,23 @@ NewListener(const char *listen_addr, UINT16 Port) return -1; if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) { - Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s", - ng_ipaddr_tostr(&addr), Port, strerror(errno)); + Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s!", + ng_ipaddr_tostr(&addr), Port, strerror(errno)); close(sock); return -1; } - if( listen( sock, 10 ) != 0 ) { - Log( LOG_CRIT, "Can't listen on socket: %s!", strerror( errno )); - close( sock ); + if (listen(sock, 10) != 0) { + Log(LOG_CRIT, "Can't listen on socket: %s!", strerror(errno)); + close(sock); return -1; } /* keep fd in list so we can close it when ngircd restarts/shuts down */ - if (!array_catb( &My_Listeners,(char*) &sock, sizeof(int) )) { - Log( LOG_CRIT, "Can't add socket to My_Listeners array: %s!", strerror( errno )); - close( sock ); + if (!array_catb(&My_Listeners, (char *)&sock, sizeof(int))) { + Log(LOG_CRIT, "Can't add socket to My_Listeners array: %s!", + strerror(errno)); + close(sock); return -1; } @@ -861,6 +938,9 @@ va_dcl #endif { char buffer[COMMAND_LEN]; +#ifdef ICONV + char *ptr, *message; +#endif size_t len; bool ok; va_list ap; @@ -901,6 +981,16 @@ va_dcl CUT_TXTSUFFIX); } +#ifdef ICONV + ptr = strchr(buffer + 1, ':'); + if (ptr) { + ptr++; + message = Conn_EncodingTo(Idx, ptr); + if (message != ptr) + strlcpy(ptr, message, sizeof(buffer) - (ptr - buffer)); + } +#endif + #ifdef SNIFFER if (NGIRCd_Sniffer) Log(LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer); @@ -1064,7 +1154,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING ); port = ng_ipaddr_getport(&My_Connections[Idx].addr); - Log(LOG_INFO, "Shutting down connection %d (%s) with %s:%d ...", Idx, + Log(LOG_INFO, "Shutting down connection %d (%s) with \"%s:%d\" ...", Idx, LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, port); /* Search client, if any */ @@ -1138,7 +1228,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie in_p = (int)(( in_k * 100 ) / in_z_k ); out_p = (int)(( out_k * 100 ) / out_z_k ); Log(LOG_INFO, - "Connection %d with %s:%d closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).", + "Connection %d with \"%s:%d\" closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).", Idx, My_Connections[Idx].host, port, in_k, in_z_k, in_p, out_k, out_z_k, out_p); } @@ -1146,7 +1236,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie #endif { Log(LOG_INFO, - "Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).", + "Connection %d with \"%s:%d\" closed (in: %.1fk, out: %.1fk).", Idx, My_Connections[Idx].host, port, in_k, out_k); } @@ -1486,7 +1576,7 @@ New_Connection(int Sock, UNUSED bool IsSSL) Client_SetHostname(c, My_Connections[new_sock].host); - Log(LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", + Log(LOG_INFO, "Accepted connection %d from \"%s:%d\" on socket %d.", new_sock, My_Connections[new_sock].host, ng_ipaddr_getport(&new_addr), Sock); Account_Connection(); @@ -1615,13 +1705,10 @@ Read_Request( CONN_ID Idx ) #endif len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf)); if (len == 0) { - Log(LOG_INFO, "%s:%u (%s) is closing the connection ...", - My_Connections[Idx].host, - (unsigned int) ng_ipaddr_getport(&My_Connections[Idx].addr), - ng_ipaddr_tostr(&My_Connections[Idx].addr)); - Conn_Close(Idx, - "Socket closed!", "Client closed connection", - false); + LogDebug("Client \"%s:%u\" is closing connection %d ...", + My_Connections[Idx].host, + ng_ipaddr_tostr(&My_Connections[Idx].addr), Idx); + Conn_Close(Idx, NULL, "Client closed connection", false); return; } @@ -1629,7 +1716,7 @@ Read_Request( CONN_ID Idx ) if( errno == EAGAIN ) return; Log(LOG_ERR, "Read error on connection %d (socket %d): %s!", Idx, My_Connections[Idx].sock, strerror(errno)); - Conn_Close(Idx, "Read error!", "Client closed connection", + Conn_Close(Idx, "Read error", "Client closed connection", false); return; } @@ -2065,7 +2152,8 @@ New_Server( int Server , ng_ipaddr_t *dest) Client_SetToken( c, TOKEN_OUTBOUND ); /* Register connection */ - Conf_SetServer(Server, new_sock); + if (!Conf_SetServer(Server, new_sock)) + return; My_Connections[new_sock].sock = new_sock; My_Connections[new_sock].addr = *dest; My_Connections[new_sock].client = c; @@ -2105,6 +2193,11 @@ Init_Conn_Struct(CONN_ID Idx) My_Connections[Idx].lastdata = now; My_Connections[Idx].lastprivmsg = now; Proc_InitStruct(&My_Connections[Idx].proc_stat); + +#ifdef ICONV + My_Connections[Idx].iconv_from = (iconv_t)(-1); + My_Connections[Idx].iconv_to = (iconv_t)(-1); +#endif } /* Init_Conn_Struct */