]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/conn.c
Conn_Write(): Make sure there is a client when detecting its type
[ngircd-alex.git] / src / ngircd / conn.c
index 397bc91586c7bcdf2ddb7a722c574bec374278b0..5f3c18afd0108fe8eb115c236257cc3c2879bcd7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
+ * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -9,6 +9,8 @@
  * Please read the file COPYING, README and AUTHORS for more information.
  */
 
+#undef DEBUG_BUFFER
+
 #define CONN_MODULE
 
 #include "portab.h"
@@ -63,6 +65,7 @@
 #include "ngircd.h"
 #include "array.h"
 #include "client.h"
+#include "class.h"
 #include "conf.h"
 #include "conn-ssl.h"
 #include "conn-zip.h"
@@ -367,7 +370,7 @@ cb_clientserver_ssl(int sock, short what)
 
 
 /**
- * Initialite connecion module.
+ * Initialize connecion module.
  */
 GLOBAL void
 Conn_Init( void )
@@ -433,12 +436,13 @@ Conn_Exit( void )
  * they don't hold connections open that the main process wants to close.
  */
 GLOBAL void
-Conn_CloseAllSockets(void)
+Conn_CloseAllSockets(int ExceptOf)
 {
        CONN_ID idx;
 
        for(idx = 0; idx < Pool_Size; idx++) {
-               if(My_Connections[idx].sock > NONE)
+               if(My_Connections[idx].sock > NONE &&
+                  My_Connections[idx].sock != ExceptOf)
                        close(My_Connections[idx].sock);
        }
 }
@@ -739,6 +743,9 @@ Conn_Handler(void)
                Check_Servers();
                Check_Connections();
 
+               /* Expire outdated class/list items */
+               Class_Expire();
+
                /* Look for non-empty read buffers ... */
                for (i = 0; i < Pool_Size; i++) {
                        if ((My_Connections[i].sock > NONE)
@@ -929,22 +936,25 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
        assert( Data != NULL );
        assert( Len > 0 );
 
-       c = Conn_GetClient(Idx);
-       assert( c != NULL);
-
-       /* Servers do get special write buffer limits, so they can generate
-        * all the messages that are required while peering. */
-       if (Client_Type(c) == CLIENT_SERVER)
-               writebuf_limit = WRITEBUFFER_SLINK_LEN;
-
        /* Is the socket still open? A previous call to Conn_Write()
         * may have closed the connection due to a fatal error.
         * In this case it is sufficient to return an error, as well. */
-       if( My_Connections[Idx].sock <= NONE ) {
+       if (My_Connections[Idx].sock <= NONE) {
                LogDebug("Skipped write on closed socket (connection %d).", Idx);
                return false;
        }
 
+       /* Make sure that there still exists a CLIENT structure associated
+        * with this connection and check if this is a server or not: */
+       c = Conn_GetClient(Idx);
+       if (c) {
+               /* Servers do get special write buffer limits, so they can
+                * generate all the messages that are required while peering. */
+               if (Client_Type(c) == CLIENT_SERVER)
+                       writebuf_limit = WRITEBUFFER_SLINK_LEN;
+       } else
+               LogDebug("Write on socket without client (connection %d)!?", Idx);
+
 #ifdef ZLIB
        if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
                /* Compressed link:
@@ -972,10 +982,10 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
                if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
                    writebuf_limit) {
                        Log(LOG_NOTICE,
-                           "Write buffer overflow (connection %d, limit is %lu bytes, %lu bytes new, %lu bytes pending)!",
+                           "Write buffer space exhausted (connection %d, limit is %lu bytes, %lu bytes new, %lu bytes pending)",
                            Idx, writebuf_limit, Len,
                            (unsigned long)array_bytes(&My_Connections[Idx].wbuf));
-                       Conn_Close(Idx, "Write buffer overflow!", NULL, false);
+                       Conn_Close(Idx, "Write buffer space exhausted", NULL, false);
                        return false;
                }
 
@@ -1007,7 +1017,7 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
 GLOBAL void
 Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
 {
-       /* Close connection. Open pipes of asyncronous resolver
+       /* Close connection. Open pipes of asynchronous resolver
         * sub-processes are closed down. */
 
        CLIENT *c;
@@ -1255,9 +1265,11 @@ Handle_Write( CONN_ID Idx )
                return true;
        }
 
+#ifdef DEBUG_BUFFER
        LogDebug
            ("Handle_Write() called for connection %d, %ld bytes pending ...",
             Idx, wdatalen);
+#endif
 
 #ifdef SSL_SUPPORT
        if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
@@ -1326,6 +1338,8 @@ New_Connection(int Sock)
 
        assert(Sock > NONE);
 
+       LogDebug("Accepting new connection on socket %d ...", Sock);
+
        new_sock_len = (int)sizeof(new_addr);
        new_sock = accept(Sock, (struct sockaddr *)&new_addr,
                          (socklen_t *)&new_sock_len);
@@ -1444,9 +1458,20 @@ New_Connection(int Sock)
        if (!Conf_Ident)
                identsock = -1;
 #endif
-       if (Conf_DNS)
+       if (Conf_DNS) {
+               if (Conf_NoticeAuth) {
+#ifdef IDENTAUTH
+                       if (Conf_Ident)
+                               (void)Conn_WriteStr(new_sock,
+                                       "NOTICE AUTH :*** Looking up your hostname and checking ident");
+                       else
+#endif
+                               (void)Conn_WriteStr(new_sock,
+                                       "NOTICE AUTH :*** Looking up your hostname");
+               }
                Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr,
                             identsock, cb_Read_Resolver_Result);
+       }
 
        Account_Connection();
        return new_sock;
@@ -1514,9 +1539,9 @@ Read_Request( CONN_ID Idx )
        {
                /* Read buffer is full */
                Log(LOG_ERR,
-                   "Receive buffer overflow (connection %d): %d bytes!",
+                   "Receive buffer space exhausted (connection %d): %d bytes",
                    Idx, array_bytes(&My_Connections[Idx].rbuf));
-               Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
+               Conn_Close(Idx, "Receive buffer space exhausted", NULL, false);
                return;
        }
 
@@ -1550,9 +1575,9 @@ Read_Request( CONN_ID Idx )
                if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
                                (size_t) len)) {
                        Log(LOG_ERR,
-                           "Could not append recieved data to zip input buffer (connn %d): %d bytes!",
+                           "Could not append recieved data to zip input buffer (connection %d): %d bytes!",
                            Idx, len);
-                       Conn_Close(Idx, "Receive buffer overflow!", NULL,
+                       Conn_Close(Idx, "Receive buffer space exhausted", NULL,
                                   false);
                        return;
                }
@@ -1560,8 +1585,10 @@ Read_Request( CONN_ID Idx )
 #endif
        {
                if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
-                       Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
-                       Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
+                       Log(LOG_ERR,
+                           "Could not append recieved data to input buffer (connection %d): %d bytes!",
+                           Idx, len);
+                       Conn_Close(Idx, "Receive buffer space exhausted", NULL, false );
                }
        }
 
@@ -1629,18 +1656,25 @@ Handle_Buffer(CONN_ID Idx)
        CLIENT *c;
 
        c = Conn_GetClient(Idx);
-       assert( c != NULL);
+       starttime = time(NULL);
+
+       assert(c != NULL);
 
        /* Servers do get special command limits, so they can process
         * all the messages that are required while peering. */
        switch (Client_Type(c)) {
            case CLIENT_SERVER:
-               maxcmd = MAX_COMMANDS_SERVER; break;
+               /* Allow servers to send more commands in the first 10 secods
+                * to speed up server login and network synchronisation. */
+               if (starttime - Client_StartTime(c) < 10)
+                       maxcmd = MAX_COMMANDS_SERVER * 5;
+               else
+                       maxcmd = MAX_COMMANDS_SERVER;
+               break;
            case CLIENT_SERVICE:
                maxcmd = MAX_COMMANDS_SERVICE; break;
        }
 
-       starttime = time(NULL);
        for (i=0; i < maxcmd; i++) {
                /* Check penalty */
                if (My_Connections[Idx].delaytime > starttime)
@@ -1735,8 +1769,10 @@ Handle_Buffer(CONN_ID Idx)
                        return 0; /* error -> connection has been closed */
 
                array_moveleft(&My_Connections[Idx].rbuf, 1, len);
+#ifdef DEBUG_BUFFER
                LogDebug("Connection %d: %d bytes left in read buffer.",
                         Idx, 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)) {
@@ -1933,6 +1969,12 @@ New_Server( int Server , ng_ipaddr_t *dest)
                return;
        }
 
+       if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
+               Log(LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
+               close(new_sock);
+               return;
+       }
+
        My_Connections = array_start(&My_ConnArray);
 
        assert(My_Connections[new_sock].sock <= 0);
@@ -1943,7 +1985,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
        c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false);
        if (!c) {
                Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
-               close( new_sock );
+               io_close(new_sock);
                return;
        }
 
@@ -1960,13 +2002,6 @@ New_Server( int Server , ng_ipaddr_t *dest)
        strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host,
                                sizeof(My_Connections[new_sock].host ));
 
-       /* Register new socket */
-       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( new_sock, "io_event_create() failed", NULL, false );
-               Init_Conn_Struct( new_sock );
-               Conf_Server[Server].conn_id = NONE;
-       }
 #ifdef SSL_SUPPORT
        if (Conf_Server[Server].SSLConnect && !ConnSSL_PrepareConnect( &My_Connections[new_sock],
                                                                &Conf_Server[Server] ))
@@ -2007,9 +2042,10 @@ Init_Conn_Struct(CONN_ID Idx)
  * Initialize options of a new socket.
  *
  * For example, we try to set socket options SO_REUSEADDR and IPTOS_LOWDELAY.
- * Errors shouldn't be fatal and therefore are ignored.
+ * The socket is automatically closed if a fatal error is encountered.
  *
  * @param Sock Socket handle.
+ * @returns false if socket was closed due to fatal error.
  */
 static bool
 Init_Socket( int Sock )
@@ -2033,13 +2069,14 @@ Init_Socket( int Sock )
        /* Set type of service (TOS) */
 #if defined(IPPROTO_IP) && defined(IPTOS_LOWDELAY)
        value = IPTOS_LOWDELAY;
-       LogDebug("Setting IP_TOS on socket %d to IPTOS_LOWDELAY.", Sock);
        if (setsockopt(Sock, IPPROTO_IP, IP_TOS, &value,
                       (socklen_t) sizeof(value))) {
                LogDebug("Can't set socket option IP_TOS: %s!",
                         strerror(errno));
                /* ignore this error */
-       }
+       } else
+               LogDebug("IP_TOS on socket %d has been set to IPTOS_LOWDELAY.",
+                        Sock);
 #endif
 
        return true;
@@ -2080,6 +2117,7 @@ cb_Connect_to_Server(int fd, UNUSED short events)
 
        /* Read result from pipe */
        len = Proc_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs));
+       Proc_Close(&Conf_Server[i].res_stat);
        if (len == 0) {
                /* Error resolving hostname: reset server structure */
                Conf_Server[i].conn_id = NONE;
@@ -2139,6 +2177,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
 
        /* Read result from pipe */
        len = Proc_Read(&My_Connections[i].proc_stat, readbuf, sizeof readbuf -1);
+       Proc_Close(&My_Connections[i].proc_stat);
        if (len == 0)
                return;
 
@@ -2168,13 +2207,22 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
                strlcpy(My_Connections[i].host, readbuf,
                        sizeof(My_Connections[i].host));
                Client_SetHostname(c, readbuf);
+               if (Conf_NoticeAuth)
+                       (void)Conn_WriteStr(i,
+                                       "NOTICE AUTH :*** Found your hostname");
 #ifdef IDENTAUTH
                ++identptr;
                if (*identptr) {
                        Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
                        Client_SetUser(c, identptr, true);
+                       if (Conf_NoticeAuth)
+                               (void)Conn_WriteStr(i,
+                                       "NOTICE AUTH :*** Got ident response");
                } else {
                        Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
+                       if (Conf_NoticeAuth && Conf_Ident)
+                               (void)Conn_WriteStr(i,
+                                       "NOTICE AUTH :*** No ident response");
                }
 #endif
        }
@@ -2276,6 +2324,25 @@ Conn_GetFromProc(int fd)
 } /* Conn_GetFromProc */
 
 
+#ifndef STRICT_RFC
+
+GLOBAL long
+Conn_GetAuthPing(CONN_ID Idx)
+{
+       assert (Idx != NONE);
+       return My_Connections[Idx].auth_ping;
+} /* Conn_GetAuthPing */
+
+GLOBAL void
+Conn_SetAuthPing(CONN_ID Idx, long ID)
+{
+       assert (Idx != NONE);
+       My_Connections[Idx].auth_ping = ID;
+} /* Conn_SetAuthPing */
+
+#endif
+
+
 #ifdef SSL_SUPPORT
 
 /**