]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Fixed file descriptor leak on failure in initializing OMAPI listener.
authorShane Kerr <shane@isc.org>
Thu, 12 Jul 2007 13:11:02 +0000 (13:11 +0000)
committerShane Kerr <shane@isc.org>
Thu, 12 Jul 2007 13:11:02 +0000 (13:11 +0000)
See RT ticket #16993 for more.

RELNOTES
omapip/listener.c

index 42c4f90c9b08de5f633243942695a19b315d8cea..91c092e4d00a6d8ccf39b6a523cd3ae2f6da800b 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -51,6 +51,9 @@ The system has only been tested on Linux, FreeBSD, and Solaris, and
 may not work on other platforms. Please report any problems and 
 suggested fixes to <dhcp-users@isc.org>.
 
+                       Changes since 4.0.0a2
+
+- Fixed file descriptor leak on listen failure. Thanks to Tom Clark.
 
                        Changes since 4.0.0a2
 
index 115f817064362bac76252aa92ee809ab5549b015..cf4ebddca7dd482b72cbc4136e532c3d23054b4d 100644 (file)
@@ -78,28 +78,25 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
        int i;
        struct in_addr ia;
 
+       /* Currently only support IPv4 addresses. */
+       if (addr->addrtype != AF_INET)
+               return ISC_R_INVALIDARG;
+
        /* Get the handle. */
        obj = (omapi_listener_object_t *)0;
        status = omapi_listener_allocate (&obj, MDL);
        if (status != ISC_R_SUCCESS)
                return status;
+       obj->socket = -1;
 
        /* Connect this object to the inner object. */
        status = omapi_object_reference (&h -> outer,
                                         (omapi_object_t *)obj, MDL);
-       if (status != ISC_R_SUCCESS) {
-               omapi_listener_dereference (&obj, MDL);
-               return status;
-       }
+       if (status != ISC_R_SUCCESS)
+               goto error_exit;
        status = omapi_object_reference (&obj -> inner, h, MDL);
-       if (status != ISC_R_SUCCESS) {
-               omapi_listener_dereference (&obj, MDL);
-               return status;
-       }
-
-       /* Currently only support TCPv4 addresses. */
-       if (addr -> addrtype != AF_INET)
-               return ISC_R_INVALIDARG;
+       if (status != ISC_R_SUCCESS)
+               goto error_exit;
 
        /* Set up the address on which we will listen... */
        obj -> address.sin_port = htons (addr -> port);
@@ -122,19 +119,19 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
 #endif
                /* Create a socket on which to listen. */
                obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
-               if (!obj -> socket) {
-                       omapi_listener_dereference (&obj, MDL);
+               if (obj->socket == -1) {
                        if (errno == EMFILE
                            || errno == ENFILE || errno == ENOBUFS)
-                               return ISC_R_NORESOURCES;
-                       return ISC_R_UNEXPECTED;
+                               status = ISC_R_NORESOURCES;
+                       else
+                               status = ISC_R_UNEXPECTED;
+                       goto error_exit;
                }
        
 #if defined (HAVE_SETFD)
                if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
-                       close (obj -> socket);
-                       omapi_listener_dereference (&obj, MDL);
-                       return ISC_R_UNEXPECTED;
+                       status = ISC_R_UNEXPECTED;
+                       goto error_exit;
                }
 #endif
 
@@ -143,9 +140,8 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
                i = 1;
                if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
                                (char *)&i, sizeof i) < 0) {
-                       close (obj -> socket);
-                       omapi_listener_dereference (&obj, MDL);
-                       return ISC_R_UNEXPECTED;
+                       status = ISC_R_UNEXPECTED;
+                       goto error_exit;
                }
                
                /* Try to bind to the wildcard address using the port number
@@ -154,23 +150,24 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
                          (struct sockaddr *)&obj -> address,
                          sizeof obj -> address);
                if (i < 0) {
-                       omapi_listener_dereference (&obj, MDL);
                        if (errno == EADDRINUSE)
-                               return ISC_R_ADDRNOTAVAIL;
-                       if (errno == EPERM)
-                               return ISC_R_NOPERM;
-                       return ISC_R_UNEXPECTED;
+                               status = ISC_R_ADDRNOTAVAIL;
+                       else if (errno == EPERM)
+                               status = ISC_R_NOPERM;
+                       else
+                               status = ISC_R_UNEXPECTED;
+                       goto error_exit;
                }
 
                /* Now tell the kernel to listen for connections. */
                if (listen (obj -> socket, max)) {
-                       omapi_listener_dereference (&obj, MDL);
-                       return ISC_R_UNEXPECTED;
+                       status = ISC_R_UNEXPECTED;
+                       goto error_exit;
                }
 
                if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
-                       omapi_listener_dereference (&obj, MDL);
-                       return ISC_R_UNEXPECTED;
+                       status = ISC_R_UNEXPECTED;
+                       goto error_exit;
                }
 
                status = omapi_register_io_object ((omapi_object_t *)obj,
@@ -179,8 +176,26 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
 #if defined (TRACING)
        }
 #endif
+
        omapi_listener_dereference (&obj, MDL);
        return status;
+
+error_exit:
+       if (obj != NULL) {
+               if (h->outer == (omapi_object_t *)obj) {
+                       omapi_object_dereference((omapi_object_t **)&h->outer, 
+                                                MDL);
+               }
+               if (obj->inner == h) {
+                       omapi_object_dereference((omapi_object_t **)&obj->inner,
+                                                MDL);
+               }
+               if (obj->socket != -1) {
+                       close(obj->socket);
+               }
+               omapi_listener_dereference(&obj, MDL);
+       }
+       return status;
 }
 
 /* Return the socket on which the dispatcher should wait for readiness