]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3135. [port] FreeBSD: workaround broken IPV6_USE_MIN_MTU processing.
authorMark Andrews <marka@isc.org>
Thu, 21 Jul 2011 01:55:56 +0000 (01:55 +0000)
committerMark Andrews <marka@isc.org>
Thu, 21 Jul 2011 01:55:56 +0000 (01:55 +0000)
                        See http://www.freebsd.org/cgi/query-pr.cgi?pr=158307
                        [RT #24950]

CHANGES
lib/isc/unix/socket.c

diff --git a/CHANGES b/CHANGES
index f369f37f435075c56d8085656d359b3d810c13e7..cf756df29b27764a6e05be3e6420dc7b9051db84 100644 (file)
--- 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 ---
 
index a1f6cb50a05d84922d21632dc4ff2a9ad4fefaf0..1675da1508927d4650ca961d74dc43ed1c2a55ee 100644 (file)
@@ -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 */