summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bind/lib/isc/unix/socket.c
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2008-08-04 16:34:20 +0000
committermillert <millert@openbsd.org>2008-08-04 16:34:20 +0000
commit58d09879b74dcca641851384ab35dfd9de33145c (patch)
tree9df9d4faaf3aa74153e7f664d80916894230226b /usr.sbin/bind/lib/isc/unix/socket.c
parentfix extended partition support by handling chained EBRs correctly (diff)
downloadwireguard-openbsd-58d09879b74dcca641851384ab35dfd9de33145c.tar.xz
wireguard-openbsd-58d09879b74dcca641851384ab35dfd9de33145c.zip
Update to BIND 9.4.2-P2 and adapt our dynamic select changes. OK deraadt@
Diffstat (limited to 'usr.sbin/bind/lib/isc/unix/socket.c')
-rw-r--r--usr.sbin/bind/lib/isc/unix/socket.c436
1 files changed, 302 insertions, 134 deletions
diff --git a/usr.sbin/bind/lib/isc/unix/socket.c b/usr.sbin/bind/lib/isc/unix/socket.c
index 2537e1f0f05..fc300ba1e92 100644
--- a/usr.sbin/bind/lib/isc/unix/socket.c
+++ b/usr.sbin/bind/lib/isc/unix/socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $ISC: socket.c,v 1.237.18.29 2007/08/28 07:20:06 tbox Exp $ */
+/* $ISC: socket.c,v 1.237.18.29.10.6 2008/07/29 04:47:31 each Exp $ */
/*! \file */
@@ -66,6 +66,34 @@
#endif /* ISC_PLATFORM_USETHREADS */
/*%
+ * Max number of open sockets. In the vast majority of cases the default size
+ * of FD_SETSIZE should be fine, and this constant should be increased only
+ * when absolutely necessary and possible, i.e., the server is exhausting all
+ * available file descriptors (up to FD_SETSIZE) and the select() function
+ * and FD_xxx macros support larger values than FD_SETSIZE (which may not
+ * always by true, but we keep using some of them to ensure as much
+ * portability as possible). Note also that overall server performance
+ * may be rather worsened with a larger value of this constant due to
+ * inherent scalability problems of select().
+ *
+ * As a special note, this value shouldn't have to be touched if
+ * this is a build for an authoritative only DNS server.
+ */
+
+#ifndef ISC_SOCKET_FDSETSIZE
+#define ISC_SOCKET_FDSETSIZE FD_SETSIZE
+#endif
+
+/*%
+ * Mac OS X needs a special definition to support larger values in select()
+ */
+#if ISC_SOCKET_FDSETSIZE > FD_SETSIZE
+#ifdef __APPLE__
+#define _DARWIN_UNLIMITED_SELECT
+#endif /* __APPLE__ */
+#endif
+
+/*%
* Some systems define the socket length argument as an int, some as size_t,
* some as socklen_t. This is here so it can be easily changed if needed.
*/
@@ -203,14 +231,18 @@ struct isc_socketmgr {
unsigned int magic;
isc_mem_t *mctx;
isc_mutex_t lock;
+ int fd_bufsize;
+ int fdsize;
/* Locked by manager lock. */
ISC_LIST(isc_socket_t) socklist;
- fd_set *read_fds, *read_fds_copy;
- fd_set *write_fds, *write_fds_copy;
- isc_socket_t **fds;
- int *fdstate;
+ fd_set *read_fds;
+ fd_set *read_fds_copy;
+ fd_set *write_fds;
+ fd_set *write_fds_copy;
+ isc_socket_t **fds;
+ int *fdstate;
int maxfd;
- int fdsize;
+ int reserved; /* unlocked */
#ifdef ISC_PLATFORM_USETHREADS
isc_thread_t watcher;
isc_condition_t shutdown_ok;
@@ -255,7 +287,9 @@ static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
struct msghdr *, struct iovec *, size_t *);
static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
struct msghdr *, struct iovec *, size_t *);
-static void expand_fdsets(isc_socketmgr_t *, int, isc_mem_t *);
+static void cleanup_fdsets(isc_socketmgr_t *, isc_mem_t *);
+static isc_result_t create_fdsets(isc_socketmgr_t *, isc_mem_t *);
+static isc_result_t expand_fdsets(isc_socketmgr_t *, int, isc_mem_t *);
#define SELECT_POKE_SHUTDOWN (-1)
#define SELECT_POKE_NOTHING (-2)
@@ -1397,78 +1431,6 @@ free_socket(isc_socket_t **socketp) {
*socketp = NULL;
}
-static void
-expand_fdsets(isc_socketmgr_t *manager, int maxfd, isc_mem_t *mctx) {
- void *tmp;
- int newsize = manager->fdsize;
-
- if (mctx == NULL)
- mctx = manager->mctx;
-
- do {
- newsize += FD_SETSIZE;
- } while (newsize <= maxfd);
-
- tmp = isc_mem_get(mctx, sizeof(manager->fds[0]) * newsize);
- memset(tmp, 0, sizeof(manager->fds[0]) * newsize);
- if (manager->fdsize) {
- memcpy(tmp, manager->fds,
- sizeof(manager->fds[0]) * manager->fdsize);
- isc_mem_put(mctx, manager->fds,
- sizeof(manager->fds[0]) * manager->fdsize);
- }
- manager->fds = tmp;
-
- tmp = isc_mem_get(mctx, sizeof(manager->fdstate[0]) * newsize);
- memset(tmp, 0, sizeof(manager->fdstate[0]) * newsize);
- if (manager->fdsize) {
- memcpy(tmp, manager->fdstate,
- sizeof(manager->fdstate[0]) * manager->fdsize);
- isc_mem_put(mctx, manager->fdstate,
- sizeof(manager->fdstate[0]) * manager->fdsize);
- }
- manager->fdstate = tmp;
-
- tmp = isc_mem_get(mctx, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- memset(tmp, 0, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- if (manager->fdsize) {
- memcpy(tmp, manager->read_fds,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- isc_mem_put(mctx, manager->read_fds,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- }
- manager->read_fds = tmp;
-
- tmp = isc_mem_get(mctx, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- memset(tmp, 0, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- if (manager->fdsize) {
- memcpy(tmp, manager->write_fds,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- isc_mem_put(mctx, manager->write_fds,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- }
- manager->write_fds = tmp;
-
- /* Don't bother copying these, they are copied before use */
- tmp = isc_mem_get(mctx, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- memset(tmp, 0, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- if (manager->fdsize) {
- isc_mem_put(mctx, manager->read_fds_copy,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- }
- manager->read_fds_copy = tmp;
-
- tmp = isc_mem_get(mctx, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- memset(tmp, 0, howmany(newsize, NFDBITS) * sizeof(fd_mask));
- if (manager->fdsize) {
- isc_mem_put(mctx, manager->write_fds_copy,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- }
- manager->write_fds_copy = tmp;
-
- manager->fdsize = newsize;
-}
-
#ifdef SO_BSDCOMPAT
/*
* This really should not be necessary to do. Having to workout
@@ -1555,9 +1517,18 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#ifdef F_DUPFD
/*
- * Leave a space for stdio to work in.
+ * Leave a space for stdio and TCP to work in.
*/
- if (sock->fd >= 0 && sock->fd < 20) {
+ if (manager->reserved != 0 && type == isc_sockettype_udp &&
+ sock->fd >= 0 && sock->fd < manager->reserved) {
+ int new, tmp;
+ new = fcntl(sock->fd, F_DUPFD, manager->reserved);
+ tmp = errno;
+ (void)close(sock->fd);
+ errno = tmp;
+ sock->fd = new;
+ err = "isc_socket_create: fcntl/reserved";
+ } else if (sock->fd >= 0 && sock->fd < 20) {
int new, tmp;
new = fcntl(sock->fd, F_DUPFD, 20);
tmp = errno;
@@ -1568,8 +1539,17 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
}
#endif
- if (sock->fd >= sock->manager->fdsize)
- expand_fdsets(sock->manager, sock->fd, NULL);
+ if (sock->fd >= manager->fdsize &&
+ expand_fdsets(sock->manager, sock->fd, NULL) != ISC_R_SUCCESS) {
+ (void)close(sock->fd);
+ isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYFDS,
+ "%s: too many open file descriptors", "socket");
+ free_socket(&sock);
+ return (ISC_R_NORESOURCES);
+ }
if (sock->fd < 0) {
free_socket(&sock);
@@ -2033,7 +2013,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
(void)close(fd);
errno = tmp;
fd = new;
- err = "fcntl";
+ err = "accept/fcntl";
}
#endif
@@ -2041,8 +2021,17 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
if (SOFT_ERROR(errno))
goto soft_error;
switch (errno) {
- case ENOBUFS:
case ENFILE:
+ case EMFILE:
+ isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYFDS,
+ "%s: too many open file descriptors",
+ err);
+ goto soft_error;
+
+ case ENOBUFS:
case ENOMEM:
case ECONNRESET:
case ECONNABORTED:
@@ -2092,8 +2081,16 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
sock->pf);
(void)close(fd);
goto soft_error;
- } else if (fd >= sock->manager->fdsize) {
- expand_fdsets(sock->manager, fd, NULL);
+ } else if (fd >= manager->fdsize &&
+ expand_fdsets(sock->manager, fd, NULL) != ISC_R_SUCCESS) {
+ isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYFDS,
+ "%s: too many open file descriptors",
+ "accept");
+ (void)close(fd);
+ goto soft_error;
}
}
@@ -2137,13 +2134,10 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
*/
dev->address = dev->newsocket->address;
- if (manager->maxfd < fd)
- manager->maxfd = fd;
- if (manager->maxfd >= manager->fdsize)
- expand_fdsets(manager, manager->maxfd, NULL);
-
manager->fds[fd] = dev->newsocket;
manager->fdstate[fd] = MANAGED;
+ if (manager->maxfd < fd)
+ manager->maxfd = fd;
socket_log(sock, &dev->newsocket->address, CREATION,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
@@ -2376,8 +2370,6 @@ watcher(void *uap) {
isc_boolean_t done;
int ctlfd;
int cc;
- fd_set readfds;
- fd_set writefds;
int msg, fd;
int maxfd;
char strbuf[ISC_STRERRORSIZE];
@@ -2391,13 +2383,16 @@ watcher(void *uap) {
done = ISC_FALSE;
while (!done) {
do {
- readfds = manager->read_fds;
- writefds = manager->write_fds;
+ memcpy(manager->read_fds_copy, manager->read_fds,
+ manager->fd_bufsize);
+ memcpy(manager->write_fds_copy, manager->write_fds,
+ manager->fd_bufsize);
maxfd = manager->maxfd + 1;
UNLOCK(&manager->lock);
- cc = select(maxfd, &readfds, &writefds, NULL, NULL);
+ cc = select(maxfd, manager->read_fds_copy,
+ manager->write_fds_copy, NULL, NULL);
if (cc < 0) {
if (!SOFT_ERROR(errno)) {
isc__strerror(errno, strbuf,
@@ -2419,7 +2414,7 @@ watcher(void *uap) {
/*
* Process reads on internal, control fd.
*/
- if (FD_ISSET(ctlfd, &readfds)) {
+ if (FD_ISSET(ctlfd, manager->read_fds_copy)) {
for (;;) {
select_readmsg(manager, &fd, &msg);
@@ -2458,7 +2453,8 @@ watcher(void *uap) {
}
}
- process_fds(manager, maxfd, &readfds, &writefds);
+ process_fds(manager, maxfd, manager->read_fds_copy,
+ manager->write_fds_copy);
}
manager_log(manager, TRACE,
@@ -2470,6 +2466,184 @@ watcher(void *uap) {
}
#endif /* ISC_PLATFORM_USETHREADS */
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ manager->reserved = reserved;
+}
+
+/*
+ * Initialize fdsets in socketmgr structure.
+ */
+static isc_result_t
+create_fdsets(isc_socketmgr_t *manager, isc_mem_t *mctx) {
+#if ISC_SOCKET_FDSETSIZE > FD_SETSIZE
+ manager->fdsize = ISC_SOCKET_FDSETSIZE;
+ manager->fd_bufsize = howmany(ISC_SOCKET_FDSETSIZE, NFDBITS) *
+ sizeof(fd_mask);
+#else
+ manager->fdsize = FD_SETSIZE;
+ manager->fd_bufsize = sizeof(fd_set);
+#endif
+
+ manager->fds = NULL;
+ manager->fdstate = NULL;
+ manager->read_fds = NULL;
+ manager->read_fds_copy = NULL;
+ manager->write_fds = NULL;
+ manager->write_fds_copy = NULL;
+
+ manager->fds = isc_mem_get(mctx,
+ manager->fdsize * sizeof(manager->fds[0]));
+ if (manager->fds == NULL)
+ goto fail;
+
+ manager->fdstate = isc_mem_get(mctx, manager->fdsize *
+ sizeof(manager->fdstate[0]));
+ if (manager->fdstate == NULL)
+ goto fail;
+
+ manager->read_fds = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->read_fds == NULL)
+ goto fail;
+ manager->read_fds_copy = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->read_fds_copy == NULL)
+ goto fail;
+ manager->write_fds = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->write_fds == NULL)
+ goto fail;
+ manager->write_fds_copy = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->write_fds_copy == NULL)
+ goto fail;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ cleanup_fdsets(manager, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+/*
+ * Clean up fdsets in socketmgr structure.
+ */
+static void
+cleanup_fdsets(isc_socketmgr_t *manager, isc_mem_t *mctx) {
+ if (manager->fds != NULL) {
+ isc_mem_put(mctx, manager->fds,
+ manager->fdsize * sizeof(manager->fds[0]));
+ }
+ if (manager->fdstate != NULL) {
+ isc_mem_put(mctx, manager->fdstate,
+ manager->fdsize * sizeof(manager->fdstate[0]));
+ }
+ if (manager->read_fds != NULL)
+ isc_mem_put(mctx, manager->read_fds, manager->fd_bufsize);
+ if (manager->read_fds_copy != NULL)
+ isc_mem_put(mctx, manager->read_fds_copy, manager->fd_bufsize);
+ if (manager->write_fds != NULL)
+ isc_mem_put(mctx, manager->write_fds, manager->fd_bufsize);
+ if (manager->write_fds_copy != NULL)
+ isc_mem_put(mctx, manager->write_fds_copy, manager->fd_bufsize);
+}
+
+/*
+ * Expand fdsets in socketmgr structure.
+ */
+static isc_result_t
+expand_fdsets(isc_socketmgr_t *manager, int maxfd, isc_mem_t *mctx) {
+ fd_set *read_fds = NULL, *read_fds_copy = NULL;
+ fd_set *write_fds = NULL, *write_fds_copy = NULL;
+ isc_socket_t **fds = NULL;
+ int *fdstate = NULL, fdsize, fd_bufsize;
+
+ if (mctx == NULL)
+ mctx = manager->mctx;
+
+ fdsize = manager->fdsize;
+ do {
+ fdsize <<= 1;
+ } while (fdsize <= maxfd);
+ fd_bufsize = howmany(fdsize, NFDBITS) * sizeof(fd_mask);
+
+ fds = isc_mem_get(mctx, sizeof(manager->fds[0]) * fdsize);
+ fdstate = isc_mem_get(mctx, sizeof(manager->fdstate[0]) * fdsize);
+ read_fds = isc_mem_get(mctx, fd_bufsize);
+ write_fds = isc_mem_get(mctx, fd_bufsize);
+ read_fds_copy = isc_mem_get(mctx, fd_bufsize);
+ write_fds_copy = isc_mem_get(mctx, fd_bufsize);
+ if (fds == NULL || fdstate == NULL || read_fds == NULL ||
+ write_fds == NULL || read_fds_copy == NULL || write_fds_copy == NULL)
+ goto fail;
+
+ /* Copy old values. */
+ memset(fds, 0, sizeof(manager->fds[0]) * fdsize);
+ if (manager->fdsize) {
+ memcpy(fds, manager->fds,
+ sizeof(manager->fds[0]) * manager->fdsize);
+ isc_mem_put(mctx, manager->fds,
+ sizeof(manager->fds[0]) * manager->fdsize);
+ }
+ manager->fds = fds;
+
+ memset(fdstate, 0, sizeof(manager->fdstate[0]) * fdsize);
+ if (manager->fdsize) {
+ memcpy(fdstate, manager->fdstate,
+ sizeof(manager->fdstate[0]) * manager->fdsize);
+ isc_mem_put(mctx, manager->fdstate,
+ sizeof(manager->fdstate[0]) * manager->fdsize);
+ }
+ manager->fdstate = fdstate;
+
+ memset(read_fds, 0, fd_bufsize);
+ if (manager->fdsize) {
+ memcpy(read_fds, manager->read_fds, manager->fd_bufsize);
+ isc_mem_put(mctx, manager->read_fds, manager->fd_bufsize);
+ }
+ manager->read_fds = read_fds;
+
+ memset(write_fds, 0, fd_bufsize);
+ if (manager->fdsize) {
+ memcpy(write_fds, manager->write_fds, manager->fd_bufsize);
+ isc_mem_put(mctx, manager->write_fds, manager->fd_bufsize);
+ }
+ manager->write_fds = write_fds;
+
+ /* Don't bother copying these, they are copied before use */
+ memset(read_fds_copy, 0, howmany(fdsize, NFDBITS) * sizeof(fd_mask));
+ if (manager->fdsize)
+ isc_mem_put(mctx, manager->read_fds_copy, manager->fd_bufsize);
+ manager->read_fds_copy = read_fds_copy;
+
+ memset(write_fds_copy, 0, howmany(fdsize, NFDBITS) * sizeof(fd_mask));
+ if (manager->fdsize)
+ isc_mem_put(mctx, manager->write_fds_copy, manager->fd_bufsize);
+ manager->write_fds_copy = write_fds_copy;
+
+ manager->fdsize = fdsize;
+ manager->fd_bufsize = fd_bufsize;
+
+ return (ISC_R_SUCCESS);
+ fail:
+ if (fds != NULL) {
+ isc_mem_put(mctx, fds,
+ howmany(fdsize, NFDBITS) * sizeof(fd_mask));
+ }
+ if (fdstate != NULL)
+ isc_mem_put(mctx, fdstate, sizeof(fdstate[0]) * fdsize);
+ if (read_fds != NULL)
+ isc_mem_put(mctx, read_fds, fd_bufsize);
+ if (write_fds != NULL)
+ isc_mem_put(mctx, write_fds, fd_bufsize);
+ if (read_fds_copy != NULL)
+ isc_mem_put(mctx, read_fds_copy, fd_bufsize);
+ if (write_fds_copy != NULL)
+ isc_mem_put(mctx, write_fds_copy, fd_bufsize);
+ return (ISC_R_NOMEMORY);
+}
+
+
/*
* Create a new socket manager.
*/
@@ -2495,21 +2669,26 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
if (manager == NULL)
return (ISC_R_NOMEMORY);
+ result = create_fdsets(manager, mctx);
+ if (result != ISC_R_SUCCESS) {
+ cleanup_fdsets(manager, mctx);
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ return (result);
+ }
+
manager->magic = SOCKET_MANAGER_MAGIC;
manager->mctx = NULL;
- manager->read_fds = NULL;
- manager->write_fds = NULL;
- manager->fds = NULL;
- manager->fdstate = NULL;
- manager->fdsize = NULL;
+ memset(manager->fds, 0, sizeof(manager->fds[0]) * manager->fdsize);
ISC_LIST_INIT(manager->socklist);
result = isc_mutex_init(&manager->lock);
if (result != ISC_R_SUCCESS) {
+ cleanup_fdsets(manager, mctx);
isc_mem_put(mctx, manager, sizeof(*manager));
return (result);
}
#ifdef ISC_PLATFORM_USETHREADS
if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
+ cleanup_fdsets(manager, mctx);
DESTROYLOCK(&manager->lock);
isc_mem_put(mctx, manager, sizeof(*manager));
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -2524,6 +2703,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
* select/poll loop when something internal needs to be done.
*/
if (pipe(manager->pipe_fds) != 0) {
+ cleanup_fdsets(manager, mctx);
DESTROYLOCK(&manager->lock);
isc_mem_put(mctx, manager, sizeof(*manager));
isc__strerror(errno, strbuf, sizeof(strbuf));
@@ -2547,13 +2727,17 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
/*
* Set up initial state for the select loop
*/
+ memset(manager->read_fds, 0, manager->fd_bufsize);
+ memset(manager->write_fds, 0, manager->fd_bufsize);
#ifdef ISC_PLATFORM_USETHREADS
FD_SET(manager->pipe_fds[0], manager->read_fds);
manager->maxfd = manager->pipe_fds[0];
#else /* ISC_PLATFORM_USETHREADS */
manager->maxfd = 0;
#endif /* ISC_PLATFORM_USETHREADS */
- expand_fdsets(manager, manager->maxfd, mctx);
+ manager->reserved = 0;
+ memset(manager->fdstate, 0,
+ manager->fdsize * sizeof(manager->fdstate[0]));
#ifdef ISC_PLATFORM_USETHREADS
/*
@@ -2659,25 +2843,12 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
(void)isc_condition_destroy(&manager->shutdown_ok);
#endif /* ISC_PLATFORM_USETHREADS */
- if (manager->fdsize) {
- for (i = 0; i < manager->fdsize; i++)
- if (manager->fdstate[i] == CLOSE_PENDING)
- (void)close(i);
- isc_mem_put(manager->mctx, manager->fds,
- sizeof(manager->fds[0]) * manager->fdsize);
- isc_mem_put(manager->mctx, manager->fdstate,
- sizeof(manager->fdstate[0]) * manager->fdsize);
- isc_mem_put(manager->mctx, manager->read_fds,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- isc_mem_put(manager->mctx, manager->write_fds,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- isc_mem_put(manager->mctx, manager->read_fds_copy,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- isc_mem_put(manager->mctx, manager->write_fds_copy,
- howmany(manager->fdsize, NFDBITS) * sizeof(fd_mask));
- }
+ for (i = 0; i < manager->fdsize; i++)
+ if (manager->fdstate[i] == CLOSE_PENDING)
+ (void)close(i);
DESTROYLOCK(&manager->lock);
+ cleanup_fdsets(manager, manager->mctx);
manager->magic = 0;
mctx= manager->mctx;
isc_mem_put(mctx, manager, sizeof(*manager));
@@ -3246,7 +3417,8 @@ isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
}
isc_result_t
-isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) {
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options) {
char strbuf[ISC_STRERRORSIZE];
int on = 1;
@@ -3265,7 +3437,8 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) {
if (sock->pf == AF_UNIX)
goto bind_socket;
#endif
- if (isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
+ if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
+ isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
sizeof(on)) < 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -3906,16 +4079,11 @@ isc__socketmgr_getfdsets(fd_set **readset, fd_set **writeset, int *maxfd) {
if (socketmgr == NULL)
*maxfd = 0;
else {
-
/* Prepare duplicates of fd_sets, as select() will modify */
- if (socketmgr->fdsize) {
- memcpy(socketmgr->read_fds_copy, socketmgr->read_fds,
- howmany(socketmgr->fdsize, NFDBITS) *
- sizeof(fd_mask));
- memcpy(socketmgr->write_fds_copy, socketmgr->write_fds,
- howmany(socketmgr->fdsize, NFDBITS) *
- sizeof(fd_mask));
- }
+ memcpy(socketmgr->read_fds_copy, socketmgr->read_fds,
+ socketmgr->fd_bufsize);
+ memcpy(socketmgr->write_fds_copy, socketmgr->write_fds,
+ socketmgr->fd_bufsize);
*readset = socketmgr->read_fds_copy;
*writeset = socketmgr->write_fds_copy;
*maxfd = socketmgr->maxfd + 1;