diff options
Diffstat (limited to 'lib/isc/unix/socket.c')
-rw-r--r-- | lib/isc/unix/socket.c | 58 |
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)); |