aboutsummaryrefslogtreecommitdiff
path: root/lib/isc/unix/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isc/unix/socket.c')
-rw-r--r--lib/isc/unix/socket.c58
1 files changed, 46 insertions, 12 deletions
diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index 055e8837684c..18a94c4d40f7 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 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.
*/
-/* $Id: socket.c,v 1.308.12.17 2010-12-22 03:28:13 marka Exp $ */
+/* $Id: socket.c,v 1.308.12.22 2011-07-21 23:46:12 tbox Exp $ */
/*! \file */
@@ -1206,6 +1206,9 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
if ((sock->type == isc_sockettype_udp)
&& ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) {
+#if defined(IPV6_USE_MIN_MTU)
+ int use_min_mtu = 1; /* -1, 0, 1 */
+#endif
struct cmsghdr *cmsgp;
struct in6_pktinfo *pktinfop;
@@ -1224,6 +1227,22 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
+#if defined(IPV6_USE_MIN_MTU)
+ /*
+ * Set IPV6_USE_MIN_MTU as a per packet option as FreeBSD
+ * ignores setsockopt(IPV6_USE_MIN_MTU) when IPV6_PKTINFO
+ * is used.
+ */
+ cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf +
+ msg->msg_controllen);
+ msg->msg_controllen += cmsg_space(sizeof(use_min_mtu));
+ INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
+
+ cmsgp->cmsg_level = IPPROTO_IPV6;
+ cmsgp->cmsg_type = IPV6_USE_MIN_MTU;
+ cmsgp->cmsg_len = cmsg_len(sizeof(use_min_mtu));
+ memcpy(CMSG_DATA(cmsgp), &use_min_mtu, sizeof(use_min_mtu));
+#endif
}
#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */
#else /* ISC_NET_BSD44MSGHDR */
@@ -1594,6 +1613,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
} else {
isc_buffer_add(buffer, actual_count);
actual_count = 0;
+ POST(actual_count);
break;
}
buffer = ISC_LIST_NEXT(buffer, link);
@@ -1833,9 +1853,10 @@ destroy(isc_socket_t **sockp) {
SIGNAL(&manager->shutdown_ok);
#endif /* ISC_PLATFORM_USETHREADS */
- UNLOCK(&manager->lock);
-
+ /* can't unlock manager as its memory context is still used */
free_socket(sockp);
+
+ UNLOCK(&manager->lock);
}
static isc_result_t
@@ -1871,7 +1892,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
*/
cmsgbuflen = 0;
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
- cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+ cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo));
#endif
#if defined(USE_CMSG) && defined(SO_TIMESTAMP)
cmsgbuflen += cmsg_space(sizeof(struct timeval));
@@ -1885,7 +1906,14 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
cmsgbuflen = 0;
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
- cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+ cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo));
+#if defined(IPV6_USE_MIN_MTU)
+ /*
+ * Provide space for working around FreeBSD's broken IPV6_USE_MIN_MTU
+ * support.
+ */
+ cmsgbuflen += cmsg_space(sizeof(int));
+#endif
#endif
sock->sendcmsgbuflen = cmsgbuflen;
if (sock->sendcmsgbuflen != 0U) {
@@ -2232,10 +2260,18 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
/* use minimum MTU */
- if (sock->pf == AF_INET6) {
- (void)setsockopt(sock->fd, IPPROTO_IPV6,
- IPV6_USE_MIN_MTU,
- (void *)&on, sizeof(on));
+ if (sock->pf == AF_INET6 &&
+ setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+ (void *)&on, sizeof(on)) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_USE_MIN_MTU) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
}
#endif
#if defined(IPV6_MTU)
@@ -2538,7 +2574,6 @@ isc_result_t
isc_socket_close(isc_socket_t *sock) {
int fd;
isc_socketmgr_t *manager;
- isc_sockettype_t type;
REQUIRE(VALID_SOCKET(sock));
@@ -2558,7 +2593,6 @@ isc_socket_close(isc_socket_t *sock) {
INSIST(sock->connect_ev == NULL);
manager = sock->manager;
- type = sock->type;
fd = sock->fd;
sock->fd = -1;
memset(sock->name, 0, sizeof(sock->name));