summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShane Kerr <shane@isc.org>2007-08-15 12:53:21 +0000
committerShane Kerr <shane@isc.org>2007-08-15 12:53:21 +0000
commitc954ba15a0a21d53bad70f8efb6898911699ab7d (patch)
treedc684861b1f79882ae3ae889dc1dcaae02245c57
parente3f1360aa9656150f992cd75ca95b0a9fffb51e0 (diff)
downloadisc-dhcp-c954ba15a0a21d53bad70f8efb6898911699ab7d.tar.gz
Fix file descriptor leak on listen failure.
See RT ticket #16993 for more.
-rw-r--r--RELNOTES5
-rw-r--r--omapip/listener.c77
2 files changed, 50 insertions, 32 deletions
diff --git a/RELNOTES b/RELNOTES
index 00219e88..b40b4112 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -37,6 +37,10 @@ For information on how to install, configure and run this software,
as well as how to find documentation and report bugs, please consult
the README file.
+ Changes since 3.1.0
+
+- Fixed file descriptor leak on listen failure. Thanks to Tom Clark.
+
Changes since 3.1.0rc1
- The parse warning that 'deny dyanmic bootp;' must be configured for
@@ -1402,7 +1406,6 @@ the README file.
- Fix some bugs and omissions in omshell.
-
Changes since 3.0 Release Candidate 5
- Fix a bug in omapi_object_dereference that prevented objects in
diff --git a/omapip/listener.c b/omapip/listener.c
index 973f7d18..06797efe 100644
--- a/omapip/listener.c
+++ b/omapip/listener.c
@@ -75,28 +75,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);
@@ -119,19 +116,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
@@ -140,9 +137,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
@@ -151,23 +147,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,
@@ -176,8 +173,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