From: Mark Andrews Date: Thu, 21 Jul 2011 01:55:56 +0000 (+0000) Subject: 3135. [port] FreeBSD: workaround broken IPV6_USE_MIN_MTU processing. X-Git-Tag: v9.4-ESV-R5~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d6b72e48f3ec438138e0dfa9490a00bba025dee;p=thirdparty%2Fbind9.git 3135. [port] FreeBSD: workaround broken IPV6_USE_MIN_MTU processing. See http://www.freebsd.org/cgi/query-pr.cgi?pr=158307 [RT #24950] --- diff --git a/CHANGES b/CHANGES index f369f37f435..cf756df29b2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +3135. [port] FreeBSD: workaround broken IPV6_USE_MIN_MTU processing. + See http://www.freebsd.org/cgi/query-pr.cgi?pr=158307 + [RT #24950] --- 9.4-ESV-R5rc1 released --- diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index a1f6cb50a05..1675da15089 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.237.18.70 2010/12/22 23:45:17 tbox Exp $ */ +/* $Id: socket.c,v 1.237.18.71 2011/07/21 01:55:56 marka Exp $ */ /*! \file */ @@ -1088,6 +1088,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; @@ -1106,6 +1109,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 */ @@ -1724,7 +1743,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) { @@ -2055,10 +2081,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 #endif /* ISC_PLATFORM_HAVEIPV6 */