From: Wouter Wijngaards Date: Mon, 29 Jun 2009 13:47:48 +0000 (+0000) Subject: Linux IPv6 large response support. X-Git-Tag: release-1.3.1~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d232dbd4a5255c2ef2543976f8f8a636d8a38208;p=thirdparty%2Funbound.git Linux IPv6 large response support. git-svn-id: file:///svn/unbound/trunk@1689 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 986f3ba4c..69e51130b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -2,6 +2,8 @@ - ldns trunk r2959 imported as tarball, because of solaris cc compile support for c99. r2960 for better configure. - better wrongly_truncated check. + - On Linux, fragment IPv6 datagrams to the IPv6 minimum MTU, to + avoid dropped packets at routers. 26 June 2009: Wouter - Fix EDNS fallback when EDNS works for short answers but long answers diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index c6079008c..ac9acc846 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -92,11 +92,15 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, socklen_t addrlen, int v6only, int* inuse, int* noproto) { int s; -# if defined(IPV6_USE_MIN_MTU) +#if defined(IPV6_USE_MIN_MTU) int on=1; -# else +#endif +#ifdef IPV6_MTU + int mtu = IPV6_MIN_MTU; +#endif +#ifndef IPV6_V6ONLY (void)v6only; -# endif +#endif if((s = socket(family, socktype, 0)) == -1) { *inuse = 0; #ifndef USE_WINSOCK @@ -150,21 +154,42 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, */ if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU, (void*)&on, (socklen_t)sizeof(on)) < 0) { -#ifndef USE_WINSOCK +# ifndef USE_WINSOCK log_err("setsockopt(..., IPV6_USE_MIN_MTU, " "...) failed: %s", strerror(errno)); close(s); -#else +# else log_err("setsockopt(..., IPV6_USE_MIN_MTU, " "...) failed: %s", wsa_strerror(WSAGetLastError())); closesocket(s); -#endif +# endif *noproto = 0; *inuse = 0; return -1; } -# endif +# elif defined(IPV6_MTU) + /* + * On Linux, to send no larger than 1280, the PMTUD is + * disabled by default for datagrams anyway, so we set + * the MTU to use. + */ + if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU, + (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) { +# ifndef USE_WINSOCK + log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", + strerror(errno)); + close(s); +# else + log_err("setsockopt(..., IPV6_MTU, ...) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +# endif + *noproto = 0; + *inuse = 0; + return -1; + } +# endif /* IPv6 MTU */ } if(bind(s, (struct sockaddr*)addr, addrlen) != 0) { *noproto = 0;