diff options
Diffstat (limited to 'contrib/bind9/lib/isc/unix/socket.c')
-rw-r--r-- | contrib/bind9/lib/isc/unix/socket.c | 74 |
1 files changed, 54 insertions, 20 deletions
diff --git a/contrib/bind9/lib/isc/unix/socket.c b/contrib/bind9/lib/isc/unix/socket.c index ec7487e..c9aa454 100644 --- a/contrib/bind9/lib/isc/unix/socket.c +++ b/contrib/bind9/lib/isc/unix/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.333.14.2.2.1 2011-06-02 23:47:36 tbox Exp $ */ +/* $Id: socket.c,v 1.333.14.9 2011-07-29 02:19:20 marka Exp $ */ /*! \file */ @@ -764,6 +764,7 @@ FIX_IPV6_RECVPKTINFO(isc__socket_t *sock) if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *)&on, sizeof(on)) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d, IPV6_RECVPKTINFO) " "%s: %s", sock->fd, @@ -1364,6 +1365,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; @@ -1382,6 +1386,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 */ @@ -1758,6 +1778,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); @@ -1997,9 +2018,10 @@ destroy(isc__socket_t **sockp) { SIGNAL(&manager->shutdown_ok); #endif /* USE_WATCHER_THREAD */ - UNLOCK(&manager->lock); - + /* can't unlock manager as its memory context is still used */ free_socket(sockp); + + UNLOCK(&manager->lock); } static isc_result_t @@ -2036,7 +2058,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)); @@ -2050,7 +2072,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) { @@ -2400,10 +2429,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) @@ -2422,8 +2459,9 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) { */ if (sock->pf == AF_INET6) { int action = IPV6_PMTUDISC_DONT; - (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, - &action, sizeof(action)); + (void)setsockopt(sock->fd, IPPROTO_IPV6, + IPV6_MTU_DISCOVER, &action, + sizeof(action)); } #endif #endif /* ISC_PLATFORM_HAVEIPV6 */ @@ -2755,7 +2793,6 @@ isc__socket_close(isc_socket_t *sock0) { isc__socket_t *sock = (isc__socket_t *)sock0; int fd; isc__socketmgr_t *manager; - isc_sockettype_t type; REQUIRE(VALID_SOCKET(sock)); @@ -2775,7 +2812,6 @@ isc__socket_close(isc_socket_t *sock0) { INSIST(sock->connect_ev == NULL); manager = sock->manager; - type = sock->type; fd = sock->fd; sock->fd = -1; memset(sock->name, 0, sizeof(sock->name)); @@ -4455,9 +4491,8 @@ isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist, INSIST(sock->bound); dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg); - if (dev == NULL) { + if (dev == NULL) return (ISC_R_NOMEMORY); - } /* * UDP sockets are always partial read @@ -4661,9 +4696,8 @@ isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region, INSIST(sock->bound); dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg); - if (dev == NULL) { + if (dev == NULL) return (ISC_R_NOMEMORY); - } dev->region = *region; @@ -4702,9 +4736,8 @@ isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist, REQUIRE(iocount > 0); dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg); - if (dev == NULL) { + if (dev == NULL) return (ISC_R_NOMEMORY); - } /* * Move each buffer from the passed in list to our internal one. @@ -5121,6 +5154,7 @@ isc__socket_accept(isc_socket_t *sock0, */ isc_task_attach(task, &ntask); if (isc_task_exiting(ntask)) { + free_socket(&nsock); isc_task_detach(&ntask); isc_event_free(ISC_EVENT_PTR(&dev)); UNLOCK(&sock->lock); @@ -5632,7 +5666,7 @@ isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) { if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&onoff, sizeof(int)) < 0) { char strbuf[ISC_STRERRORSIZE]; - + isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d, IPV6_V6ONLY) " "%s: %s", sock->fd, |