summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bind/lib/isc/unix/socket.c
diff options
context:
space:
mode:
authorjakob <jakob@openbsd.org>2004-09-28 17:14:01 +0000
committerjakob <jakob@openbsd.org>2004-09-28 17:14:01 +0000
commitb2d2683558b03d82a0e27c5ba2cc4a8587a76bb9 (patch)
tree46d872038a60738a8adb1c055a5cff3127d790b1 /usr.sbin/bind/lib/isc/unix/socket.c
parentUse ETHER_MIN_LEN/ETHER_MAX_DIX_LEN (diff)
downloadwireguard-openbsd-b2d2683558b03d82a0e27c5ba2cc4a8587a76bb9.tar.xz
wireguard-openbsd-b2d2683558b03d82a0e27c5ba2cc4a8587a76bb9.zip
resolve conflicts
Diffstat (limited to 'usr.sbin/bind/lib/isc/unix/socket.c')
-rw-r--r--usr.sbin/bind/lib/isc/unix/socket.c371
1 files changed, 245 insertions, 126 deletions
diff --git a/usr.sbin/bind/lib/isc/unix/socket.c b/usr.sbin/bind/lib/isc/unix/socket.c
index 3cfc215e735..9005d145154 100644
--- a/usr.sbin/bind/lib/isc/unix/socket.c
+++ b/usr.sbin/bind/lib/isc/unix/socket.c
@@ -1,21 +1,21 @@
/*
+ * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
- * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
- * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
-/* $ISC: socket.c,v 1.207.2.19 2003/07/23 06:57:54 marka Exp $ */
+/* $ISC: socket.c,v 1.207.2.19.2.13 2004/07/01 04:51:15 marka Exp $ */
#include <config.h>
@@ -63,8 +63,12 @@
* some as socklen_t. This is here so it can be easily changed if needed.
*/
#ifndef ISC_SOCKADDR_LEN_T
+#ifdef _BSD_SOCKLEN_T_
+#define ISC_SOCKADDR_LEN_T _BSD_SOCKLEN_T_
+#else
#define ISC_SOCKADDR_LEN_T unsigned int
#endif
+#endif
/*
* Define what the possible "soft" errors can be. These are non-fatal returns
@@ -128,35 +132,6 @@ typedef isc_event_t intev_t;
#endif
/*
- * Check to see if we have even basic support for cracking messages from
- * the control data returned from/sent via recvmsg()/sendmsg().
- */
-#if defined(USE_CMSG) && (!defined(CMSG_LEN) || !defined(CMSG_SPACE))
-#undef USE_CMSG
-#endif
-
-/*
- * Determine the size of the control data buffer.
- */
-#if USE_CMSG
-
-#ifdef ISC_PLATFORM_HAVEIPV6
-#define CMSG_BUF_V6_SIZE (CMSG_SPACE(sizeof(struct in6_pktinfo)))
-#else
-#define CMSG_BUF_V6_SIZE 0
-#endif
-
-#ifdef SO_TIMESTAMP
-#define CMSG_BUF_TS_SIZE (CMSG_SPACE(sizeof(struct timeval)))
-#else
-#define CMSG_BUF_TS_SIZE 0
-#endif
-
-#define CMSG_BUF_SIZE (CMSG_BUF_V6_SIZE + CMSG_BUF_TS_SIZE)
-
-#endif /* USE_CMSG */
-
-/*
* The number of times a send operation is repeated if the result is EINTR.
*/
#define NRETRIES 10
@@ -200,6 +175,11 @@ struct isc_socket {
#ifdef ISC_NET_RECVOVERFLOW
unsigned char overflow; /* used for MSG_TRUNC fake */
#endif
+
+ char *recvcmsgbuf;
+ ISC_SOCKADDR_LEN_T recvcmsgbuflen;
+ char *sendcmsgbuf;
+ ISC_SOCKADDR_LEN_T sendcmsgbuflen;
};
#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
@@ -258,11 +238,9 @@ static void internal_recv(isc_task_t *, isc_event_t *);
static void internal_send(isc_task_t *, isc_event_t *);
static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *);
static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
- struct msghdr *, char *cmsg,
- struct iovec *, size_t *);
+ struct msghdr *, struct iovec *, size_t *);
static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
- struct msghdr *, char *cmsg,
- struct iovec *, size_t *);
+ struct msghdr *, struct iovec *, size_t *);
#define SELECT_POKE_SHUTDOWN (-1)
#define SELECT_POKE_NOTHING (-2)
@@ -324,7 +302,7 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
msgcat, msgset, message,
"socket %p: %s", sock, msgbuf);
} else {
- isc_sockaddr_format(address, peerbuf, sizeof peerbuf);
+ isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
isc_log_iwrite(isc_lctx, category, module, level,
msgcat, msgset, message,
"socket %p %s: %s", sock, peerbuf, msgbuf);
@@ -347,7 +325,7 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
manager->fdstate[fd] = CLOSED;
FD_CLR(fd, &manager->read_fds);
FD_CLR(fd, &manager->write_fds);
- close(fd);
+ (void)close(fd);
return;
}
if (manager->fdstate[fd] != MANAGED)
@@ -475,6 +453,55 @@ make_nonblock(int fd) {
return (ISC_R_SUCCESS);
}
+#ifdef USE_CMSG
+/*
+ * Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE.
+ * In order to ensure as much portability as possible, we provide wrapper
+ * functions of these macros.
+ * Note that cmsg_space() could run slow on OSes that do not have
+ * CMSG_SPACE.
+ */
+static inline ISC_SOCKADDR_LEN_T
+cmsg_len(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_LEN
+ return (CMSG_LEN(len));
+#else
+ ISC_SOCKADDR_LEN_T hdrlen;
+
+ hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(NULL); /* XXX */
+ return (hdrlen + len);
+#endif
+}
+
+static inline ISC_SOCKADDR_LEN_T
+cmsg_space(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_SPACE
+ return (CMSG_SPACE(len));
+#else
+ struct msghdr msg;
+ struct cmsghdr *cmsgp;
+ /*
+ * XXX: The buffer length is an ad-hoc value, but should be enough
+ * in a practical sense.
+ */
+ char dummybuf[sizeof(struct cmsghdr) + 1024];
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = dummybuf;
+ msg.msg_controllen = sizeof(dummybuf);
+
+ cmsgp = (struct cmsghdr *)dummybuf;
+ cmsgp->cmsg_len = cmsg_len(len);
+
+ cmsgp = CMSG_NXTHDR(&msg, cmsgp);
+ if (cmsgp != NULL)
+ return ((char *)cmsgp - (char *)msg.msg_control);
+ else
+ return (0);
+#endif
+}
+#endif /* USE_CMSG */
+
/*
* Process control messages received on a socket.
*/
@@ -515,7 +542,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
#ifndef USE_CMSG
return;
#else
- if (msg->msg_controllen == 0 || msg->msg_control == NULL)
+ if (msg->msg_controllen == 0U || msg->msg_control == NULL)
return;
#ifdef SO_TIMESTAMP
@@ -583,8 +610,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
*/
static void
build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
- struct msghdr *msg, char *cmsg,
- struct iovec *iov, size_t *write_countp)
+ struct msghdr *msg, struct iovec *iov, size_t *write_countp)
{
unsigned int iovcount;
isc_buffer_t *buffer;
@@ -592,11 +618,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
size_t write_count;
size_t skip_count;
-#ifndef USE_CMSG
- UNUSED(cmsg);
-#endif
-
- memset(msg, 0, sizeof (*msg));
+ memset(msg, 0, sizeof(*msg));
if (sock->type == isc_sockettype_udp) {
msg->msg_name = (void *)&dev->address.type.sa;
@@ -672,13 +694,14 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
"sendto pktinfo data, ifindex %u",
dev->pktinfo.ipi6_ifindex);
- msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
- msg->msg_control = (void *)cmsg;
+ msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo));
+ INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
+ msg->msg_control = (void *)sock->sendcmsgbuf;
- cmsgp = (struct cmsghdr *)cmsg;
+ cmsgp = (struct cmsghdr *)sock->sendcmsgbuf;
cmsgp->cmsg_level = IPPROTO_IPV6;
cmsgp->cmsg_type = IPV6_PKTINFO;
- cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
}
@@ -706,19 +729,14 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
*/
static void
build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
- struct msghdr *msg, char *cmsg,
- struct iovec *iov, size_t *read_countp)
+ struct msghdr *msg, struct iovec *iov, size_t *read_countp)
{
unsigned int iovcount;
isc_buffer_t *buffer;
isc_region_t available;
size_t read_count;
-#ifndef USE_CMSG
- UNUSED(cmsg);
-#endif
-
- memset(msg, 0, sizeof (struct msghdr));
+ memset(msg, 0, sizeof(struct msghdr));
if (sock->type == isc_sockettype_udp) {
memset(&dev->address, 0, sizeof(dev->address));
@@ -799,8 +817,8 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
msg->msg_flags = 0;
#if defined(USE_CMSG)
if (sock->type == isc_sockettype_udp) {
- msg->msg_control = cmsg;
- msg->msg_controllen = CMSG_BUF_SIZE;
+ msg->msg_control = sock->recvcmsgbuf;
+ msg->msg_controllen = sock->recvcmsgbuflen;
}
#endif /* USE_CMSG */
#else /* ISC_NET_BSD44MSGHDR */
@@ -836,7 +854,7 @@ allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
sock, eventtype,
action, arg,
- sizeof (*ev));
+ sizeof(*ev));
if (ev == NULL)
return (NULL);
@@ -860,7 +878,7 @@ dump_msg(struct msghdr *msg) {
printf("MSGHDR %p\n", msg);
printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen);
printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen);
- for (i = 0 ; i < (unsigned int)msg->msg_iovlen ; i++)
+ for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
printf("\t\t%d\tbase %p, len %d\n", i,
msg->msg_iov[i].iov_base,
msg->msg_iov[i].iov_len);
@@ -885,14 +903,9 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
struct msghdr msghdr;
isc_buffer_t *buffer;
int recv_errno;
-#if USE_CMSG
- char cmsg[CMSG_BUF_SIZE];
-#else
- char *cmsg = NULL;
-#endif
char strbuf[ISC_STRERRORSIZE];
- build_msghdr_recv(sock, dev, &msghdr, cmsg, iov, &read_count);
+ build_msghdr_recv(sock, dev, &msghdr, iov, &read_count);
#if defined(ISC_SOCKET_DEBUG)
dump_msg(&msghdr);
@@ -1044,16 +1057,11 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
size_t write_count;
struct msghdr msghdr;
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
-#if USE_CMSG
- char cmsg[CMSG_BUF_SIZE];
-#else
- char *cmsg = NULL;
-#endif
int attempts = 0;
int send_errno;
char strbuf[ISC_STRERRORSIZE];
- build_msghdr_send(sock, dev, &msghdr, cmsg, iov, &write_count);
+ build_msghdr_send(sock, dev, &msghdr, iov, &write_count);
resend:
cc = sendmsg(sock->fd, &msghdr, 0);
@@ -1189,8 +1197,9 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
{
isc_socket_t *sock;
isc_result_t ret;
+ ISC_SOCKADDR_LEN_T cmsgbuflen;
- sock = isc_mem_get(manager->mctx, sizeof *sock);
+ sock = isc_mem_get(manager->mctx, sizeof(*sock));
if (sock == NULL)
return (ISC_R_NOMEMORY);
@@ -1206,6 +1215,37 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
ISC_LINK_INIT(sock, link);
+ sock->recvcmsgbuf = NULL;
+ sock->sendcmsgbuf = NULL;
+
+ /*
+ * set up cmsg buffers
+ */
+ cmsgbuflen = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6)
+ cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+#endif
+#if defined(USE_CMSG) && defined(SO_TIMESTAMP)
+ cmsgbuflen += cmsg_space(sizeof(struct timeval));
+#endif
+ sock->recvcmsgbuflen = cmsgbuflen;
+ if (sock->recvcmsgbuflen != 0) {
+ sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
+ if (sock->recvcmsgbuf == NULL)
+ goto error;
+ }
+
+ cmsgbuflen = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6)
+ cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+#endif
+ sock->sendcmsgbuflen = cmsgbuflen;
+ if (sock->sendcmsgbuflen != 0) {
+ sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
+ if (sock->sendcmsgbuf == NULL)
+ goto error;
+ }
+
/*
* set up list of readers and writers to be initially empty
*/
@@ -1249,7 +1289,14 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
return (ISC_R_SUCCESS);
- error: /* socket allocated */
+ error:
+ if (sock->recvcmsgbuf != NULL)
+ isc_mem_put(manager->mctx, sock->recvcmsgbuf,
+ sock->recvcmsgbuflen);
+ if (sock->sendcmsgbuf != NULL)
+ isc_mem_put(manager->mctx, sock->sendcmsgbuf,
+ sock->sendcmsgbuflen);
+ isc_mem_put(manager->mctx, sock, sizeof(*sock));
return (ret);
}
@@ -1276,11 +1323,18 @@ free_socket(isc_socket_t **socketp) {
INSIST(ISC_LIST_EMPTY(sock->accept_list));
INSIST(!ISC_LINK_LINKED(sock, link));
+ if (sock->recvcmsgbuf != NULL)
+ isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf,
+ sock->recvcmsgbuflen);
+ if (sock->sendcmsgbuf != NULL)
+ isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
+ sock->sendcmsgbuflen);
+
sock->magic = 0;
DESTROYLOCK(&sock->lock);
- isc_mem_put(sock->manager->mctx, sock, sizeof *sock);
+ isc_mem_put(sock->manager->mctx, sock, sizeof(*sock));
*socketp = NULL;
}
@@ -1384,7 +1438,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#ifdef SO_BSDCOMPAT
if (setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT,
- (void *)&on, sizeof on) < 0) {
+ (void *)&on, sizeof(on)) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, SO_BSDCOMPAT) %s: %s",
@@ -1401,7 +1455,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#if defined(SO_TIMESTAMP)
if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP,
- (void *)&on, sizeof on) < 0
+ (void *)&on, sizeof(on)) < 0
&& errno != ENOPROTOOPT) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -1417,11 +1471,20 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#endif /* SO_TIMESTAMP */
#if defined(ISC_PLATFORM_HAVEIPV6)
+ if (pf == AF_INET6 && sock->recvcmsgbuflen == 0) {
+ /*
+ * Warn explicitly because this anomaly can be hidden
+ * in usual operation (and unexpectedly appear later).
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "No buffer available to receive "
+ "IPv6 destination");
+ }
#ifdef IPV6_RECVPKTINFO
/* 2292bis */
if ((pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
- (void *)&on, sizeof (on)) < 0)) {
+ (void *)&on, sizeof(on)) < 0)) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, IPV6_RECVPKTINFO) "
@@ -1436,7 +1499,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
/* 2292 */
if ((pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
- (void *)&on, sizeof (on)) < 0)) {
+ (void *)&on, sizeof(on)) < 0)) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, IPV6_PKTINFO) %s: %s",
@@ -1453,7 +1516,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
if (pf == AF_INET6) {
(void)setsockopt(sock->fd, IPPROTO_IPV6,
IPV6_USE_MIN_MTU,
- (void *)&on, sizeof (on));
+ (void *)&on, sizeof(on));
}
#endif
#endif /* ISC_PLATFORM_HAVEIPV6 */
@@ -1753,7 +1816,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
* deamons such as BIND 8 and Apache.
*/
- addrlen = sizeof dev->newsocket->address.type;
+ addrlen = sizeof(dev->newsocket->address.type);
memset(&dev->newsocket->address.type.sa, 0, addrlen);
fd = accept(sock->fd, &dev->newsocket->address.type.sa,
(void *)&addrlen);
@@ -1858,7 +1921,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
UNLOCK(&sock->lock);
if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) {
- close(fd);
+ (void)close(fd);
fd = -1;
result = ISC_R_UNEXPECTED;
}
@@ -1902,7 +1965,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
task = dev->ev_sender;
dev->ev_sender = sock;
- isc_task_sendanddetach(&task, (isc_event_t **)&dev);
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
return;
soft_error:
@@ -2045,7 +2108,7 @@ process_fds(isc_socketmgr_t *manager, int maxfd,
* Process read/writes on other fds here. Avoid locking
* and unlocking twice if both reads and writes are possible.
*/
- for (i = 0 ; i < maxfd ; i++) {
+ for (i = 0; i < maxfd; i++) {
#ifdef ISC_PLATFORM_USETHREADS
if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
continue;
@@ -2056,7 +2119,7 @@ process_fds(isc_socketmgr_t *manager, int maxfd,
FD_CLR(i, &manager->read_fds);
FD_CLR(i, &manager->write_fds);
- close(i);
+ (void)close(i);
continue;
}
@@ -2229,7 +2292,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
}
#endif /* ISC_PLATFORM_USETHREADS */
- manager = isc_mem_get(mctx, sizeof *manager);
+ manager = isc_mem_get(mctx, sizeof(*manager));
if (manager == NULL)
return (ISC_R_NOMEMORY);
@@ -2238,7 +2301,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
memset(manager->fds, 0, sizeof(manager->fds));
ISC_LIST_INIT(manager->socklist);
if (isc_mutex_init(&manager->lock) != ISC_R_SUCCESS) {
- isc_mem_put(mctx, manager, sizeof *manager);
+ isc_mem_put(mctx, manager, sizeof(*manager));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_mutex_init() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
@@ -2248,7 +2311,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
#ifdef ISC_PLATFORM_USETHREADS
if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
DESTROYLOCK(&manager->lock);
- isc_mem_put(mctx, manager, sizeof *manager);
+ isc_mem_put(mctx, manager, sizeof(*manager));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_condition_init() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
@@ -2262,7 +2325,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
*/
if (pipe(manager->pipe_fds) != 0) {
DESTROYLOCK(&manager->lock);
- isc_mem_put(mctx, manager, sizeof *manager);
+ isc_mem_put(mctx, manager, sizeof(*manager));
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"pipe() %s: %s",
@@ -2300,10 +2363,10 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
*/
if (isc_thread_create(watcher, manager, &manager->watcher) !=
ISC_R_SUCCESS) {
- close(manager->pipe_fds[0]);
- close(manager->pipe_fds[1]);
+ (void)close(manager->pipe_fds[0]);
+ (void)close(manager->pipe_fds[1]);
DESTROYLOCK(&manager->lock);
- isc_mem_put(mctx, manager, sizeof *manager);
+ isc_mem_put(mctx, manager, sizeof(*manager));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_thread_create() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
@@ -2393,19 +2456,19 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
* Clean up.
*/
#ifdef ISC_PLATFORM_USETHREADS
- close(manager->pipe_fds[0]);
- close(manager->pipe_fds[1]);
+ (void)close(manager->pipe_fds[0]);
+ (void)close(manager->pipe_fds[1]);
(void)isc_condition_destroy(&manager->shutdown_ok);
#endif /* ISC_PLATFORM_USETHREADS */
- for (i = 0 ; i < (int)FD_SETSIZE ; i++)
+ for (i = 0; i < (int)FD_SETSIZE; i++)
if (manager->fdstate[i] == CLOSE_PENDING)
- close(i);
+ (void)close(i);
DESTROYLOCK(&manager->lock);
manager->magic = 0;
mctx= manager->mctx;
- isc_mem_put(mctx, manager, sizeof *manager);
+ isc_mem_put(mctx, manager, sizeof(*manager));
isc_mem_detach(&mctx);
@@ -2602,18 +2665,22 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
set_dev_address(address, sock, dev);
if (pktinfo != NULL) {
- socket_log(sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
- ISC_MSG_PKTINFOPROVIDED,
- "pktinfo structure provided, ifindex %u (set to 0)",
- pktinfo->ipi6_ifindex);
-
dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
dev->pktinfo = *pktinfo;
- /*
- * Set the pktinfo index to 0 here, to let the kernel decide
- * what interface it should send on.
- */
- dev->pktinfo.ipi6_ifindex = 0;
+
+ if (!isc_sockaddr_issitelocal(address) &&
+ !isc_sockaddr_islinklocal(address)) {
+ socket_log(sock, NULL, TRACE, isc_msgcat,
+ ISC_MSGSET_SOCKET, ISC_MSG_PKTINFOPROVIDED,
+ "pktinfo structure provided, ifindex %u "
+ "(set to 0)", pktinfo->ipi6_ifindex);
+
+ /*
+ * Set the pktinfo index to 0 here, to let the
+ * kernel decide what interface it should send on.
+ */
+ dev->pktinfo.ipi6_ifindex = 0;
+ }
}
if (sock->type == isc_sockettype_udp)
@@ -2795,8 +2862,12 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) {
UNLOCK(&sock->lock);
return (ISC_R_FAMILYMISMATCH);
}
- if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
- sizeof on) < 0) {
+ /*
+ * Only set SO_REUSEADDR when we want a specific port.
+ */
+ if (isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
+ setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
+ sizeof(on)) < 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d) %s", sock->fd,
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
@@ -2838,6 +2909,35 @@ isc_socket_privsep(int flag) {
return (ISC_R_SUCCESS);
}
+isc_result_t
+isc_socket_filter(isc_socket_t *sock, const char *filter) {
+#ifdef SO_ACCEPTFILTER
+ char strbuf[ISC_STRERRORSIZE];
+ struct accept_filter_arg afa;
+#else
+ UNUSED(sock);
+ UNUSED(filter);
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+#ifdef SO_ACCEPTFILTER
+ bzero(&afa, sizeof(afa));
+ strlcpy(afa.af_name, filter, sizeof(afa.af_name));
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_ACCEPTFILTER,
+ &afa, sizeof(afa)) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FILTER, "setsockopt(SO_ACCEPTFILTER): %s",
+ strbuf);
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+#else
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
/*
* Set up to listen on a given socket. We do this by creating an internal
* event that will be dispatched when the socket has read activity. The
@@ -2907,7 +3007,7 @@ isc_socket_accept(isc_socket_t *sock,
*/
dev = (isc_socket_newconnev_t *)
isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN,
- action, arg, sizeof (*dev));
+ action, arg, sizeof(*dev));
if (dev == NULL) {
UNLOCK(&sock->lock);
return (ISC_R_NOMEMORY);
@@ -2916,7 +3016,7 @@ isc_socket_accept(isc_socket_t *sock,
ret = allocate_socket(manager, sock->type, &nsock);
if (ret != ISC_R_SUCCESS) {
- isc_event_free((isc_event_t **)&dev);
+ isc_event_free(ISC_EVENT_PTR(&dev));
UNLOCK(&sock->lock);
return (ret);
}
@@ -2976,7 +3076,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
dev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
ISC_SOCKEVENT_CONNECT,
action, arg,
- sizeof (*dev));
+ sizeof(*dev));
if (dev == NULL) {
UNLOCK(&sock->lock);
return (ISC_R_NOMEMORY);
@@ -3016,12 +3116,12 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s", errno, strbuf);
UNLOCK(&sock->lock);
- isc_event_free((isc_event_t **)&dev);
+ isc_event_free(ISC_EVENT_PTR(&dev));
return (ISC_R_UNEXPECTED);
err_exit:
sock->connected = 0;
- isc_task_send(task, (isc_event_t **)&dev);
+ isc_task_send(task, ISC_EVENT_PTR(&dev));
UNLOCK(&sock->lock);
return (ISC_R_SUCCESS);
@@ -3034,7 +3134,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
sock->connected = 1;
sock->bound = 1;
dev->result = ISC_R_SUCCESS;
- isc_task_send(task, (isc_event_t **)&dev);
+ isc_task_send(task, ISC_EVENT_PTR(&dev));
UNLOCK(&sock->lock);
return (ISC_R_SUCCESS);
@@ -3172,7 +3272,7 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
task = dev->ev_sender;
dev->ev_sender = sock;
- isc_task_sendanddetach(&task, (isc_event_t **)&dev);
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
}
isc_result_t
@@ -3214,7 +3314,7 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
ret = ISC_R_SUCCESS;
- len = sizeof addressp->type;
+ len = sizeof(addressp->type);
if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
@@ -3320,7 +3420,7 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
dev->result = ISC_R_CANCELED;
dev->ev_sender = sock;
isc_task_sendanddetach(&current_task,
- (isc_event_t **)&dev);
+ ISC_EVENT_PTR(&dev));
}
dev = next;
@@ -3347,7 +3447,7 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
dev->result = ISC_R_CANCELED;
dev->ev_sender = sock;
isc_task_sendanddetach(&current_task,
- (isc_event_t **)&dev);
+ ISC_EVENT_PTR(&dev));
}
}
@@ -3372,6 +3472,25 @@ isc_socket_isbound(isc_socket_t *sock) {
return (val);
}
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+#if defined(IPV6_V6ONLY)
+ int onoff = yes ? 1 : 0;
+#else
+ UNUSED(yes);
+ UNUSED(sock);
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IPV6_V6ONLY
+ if (sock->pf == AF_INET6) {
+ (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (void *)&onoff, sizeof(onoff));
+ }
+#endif
+}
+
#ifndef ISC_PLATFORM_USETHREADS
void
isc__socketmgr_getfdsets(fd_set *readset, fd_set *writeset, int *maxfd) {