* 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 */
#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;
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 */
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) {
#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 */