From marka@isc.org  Wed Nov  7 14:23:59 2012
Return-Path: <marka@isc.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 5BB2C937
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  7 Nov 2012 14:23:59 +0000 (UTC)
	(envelope-from marka@isc.org)
Received: from mx.ams1.isc.org (mx.ams1.isc.org [IPv6:2001:500:60::65])
	by mx1.freebsd.org (Postfix) with ESMTP id DAFBA8FC0A
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  7 Nov 2012 14:23:58 +0000 (UTC)
Received: from bikeshed.isc.org (bikeshed.isc.org [IPv6:2001:4f8:3:d::19])
	(using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits))
	(Client CN "mail.isc.org", Issuer "RapidSSL CA" (not verified))
	by mx.ams1.isc.org (Postfix) with ESMTPS id A46A65FA7C2
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  7 Nov 2012 14:23:47 +0000 (UTC)
	(envelope-from marka@isc.org)
Received: from sex.dv.isc.org (sex.dv.isc.org [IPv6:2001:470:1f00:820:218:f3ff:feba:9a37])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(Client did not present a certificate)
	by bikeshed.isc.org (Postfix) with ESMTPSA id 71879216C3D
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  7 Nov 2012 14:23:45 +0000 (UTC)
	(envelope-from marka@isc.org)
Received: from sex.dv.isc.org (localhost [127.0.0.1])
	by sex.dv.isc.org (8.14.5/8.14.5) with ESMTP id qA7ENg2O076244
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 8 Nov 2012 01:23:42 +1100 (EST)
	(envelope-from marka@sex.dv.isc.org)
Received: (from marka@localhost)
	by sex.dv.isc.org (8.14.5/8.14.5/Submit) id qA7ENfHK076243;
	Thu, 8 Nov 2012 01:23:41 +1100 (EST)
	(envelope-from marka)
Message-Id: <201211071423.qA7ENfHK076243@sex.dv.isc.org>
Date: Thu, 8 Nov 2012 01:23:41 +1100 (EST)
From: Mark Andrews <marka@isc.org>
Reply-To: Mark Andrews <marka@isc.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: IPV6_USE_MIN_MTU and TCP is broken
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         173444
>Category:       kern
>Synopsis:       [socket] [patch] IPV6_USE_MIN_MTU and TCP is broken
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    andre
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 07 14:30:01 UTC 2012
>Closed-Date:    
>Last-Modified:  Wed Mar 20 04:00:00 UTC 2013
>Originator:     Mark Andrews
>Release:        FreeBSD 8.3-STABLE i386
>Organization:
ISC
>Environment:
System: FreeBSD sex.dv.isc.org 8.3-STABLE FreeBSD 8.3-STABLE #18: Mon Jun 18 11:57:52 EST 2012 root@sex.dv.isc.org:/usr/obj/usr/src/sys/DEBUG i386


>Description:

Setting IPV6_USE_MIN_MTU to one (1) on a IPv6 TCP socket results
in fragmented IPv6 packets being sent rather than the TCP segment
size being adjusted to reflect the MTU limit on the socket.

00:56:44.177930 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (0|1232) 5555 > 63656: Flags [.], ack 42, win 8211, options [nop,nop,TS val 2829969063 ecr 1028520077], length 1200
00:56:44.177936 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (1232|228)
00:56:44.177953 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (0|1232) 5555 > 63656: Flags [.], ack 42, win 8211, options [nop,nop,TS val 2829969063 ecr 1028520077], length 1200
00:56:44.177957 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (1232|228)
00:56:44.177974 IP6 2001:470:1f00:820:218:f3ff:feba:9a37 > 2001:470:1f00:820:6233:4bff:fe01:7585: frag (0|1232) 5555 > 63656: Flags [.], ack 42, win 8211, options [nop,nop,TS val 2829969063 ecr 1028520077], length 1200

>How-To-Repeat:

Apply the following patch to named and transfer a zone.
[The intent of the patch is to avoid PMTUD issues.  Too
many nameservers are behind load balancers / firewalls that
don't pass PTB messages.]

diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index ffe7e02..6fb8860 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -2262,6 +2264,31 @@ clear_bsdcompat(void) {
 }
 #endif
 
+static void
+use_min_mtu(isc__socket_t *sock) {
+#if !defined(IPV6_USE_MIN_MTU) && !defined(IPV6_MTU)
+	UNUSED(sock);
+#endif
+#ifdef IPV6_USE_MIN_MTU
+	/* use minimum MTU */
+	if (sock->pf == AF_INET6) {
+		int on = 1;
+		(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+				(void *)&on, sizeof(on));
+	}
+#endif
+#if defined(IPV6_MTU)
+	/*
+	 * Use minimum MTU on IPv6 sockets.
+	 */
+	if (sock->pf == AF_INET6) {
+		int mtu = 1280;
+		(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU,
+				 &mtu, sizeof(mtu));
+	}
+#endif
+}
+
 static isc_result_t
 opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
 	   isc__socket_t *dup_socket)
@@ -2426,6 +2453,11 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
 	}
 #endif
 
+	/*
+	 * Use minimum mtu if possible.
+	 */
+	use_min_mtu(sock);
+
 #if defined(USE_CMSG) || defined(SO_RCVBUF)
 	if (sock->type == isc_sockettype_udp) {
 
@@ -2490,32 +2522,6 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
 		}
 #endif /* IPV6_RECVPKTINFO */
 #endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
-#ifdef IPV6_USE_MIN_MTU        /* RFC 3542, not too common yet*/
-		/* use minimum MTU */
-		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)
-		/*
-		 * Use minimum MTU on IPv6 sockets.
-		 */
-		if (sock->pf == AF_INET6) {
-			int mtu = 1280;
-			(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU,
-					 &mtu, sizeof(mtu));
-		}
-#endif
 #if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
 		/*
 		 * Turn off Path MTU discovery on IPv6/UDP sockets.
@@ -3313,6 +3319,11 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
 		NEWCONNSOCK(dev)->connected = 1;
 
 		/*
+		 * Use minimum mtu if possible.
+		 */
+		use_min_mtu(NEWCONNSOCK(dev));
+
+		/*
 		 * Save away the remote address
 		 */
 		dev->address = NEWCONNSOCK(dev)->peer_address;
>Fix:

	The TCP layer should check whether ip6po_minmtu is set on
	the socket and adjust the maxmtu appropriately.  The code
	fragment below should do that but has not been tested.

sys/netinet/tcp_input.c:

        if (isipv6) {
                struct ip6_pktopts *opt;
                maxmtu = tcp_maxmtu6(&inp->inp_inc, mtuflags);
                opt = inp->inp_depend6.inp6_outputopts;
                if (opt && opt->ip6po_minmtu)
                        maxmtu = min(maxmtu, IPV6_MMTU);
                tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt;
        } else



>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Nov 8 23:48:35 UTC 2012 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=173444 
Responsible-Changed-From-To: freebsd-net->andre 
Responsible-Changed-By: andre 
Responsible-Changed-When: Thu Nov 8 23:58:17 UTC 2012 
Responsible-Changed-Why:  
Take over. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=173444 

From: Mark Andrews <marka@isc.org>
To: bug-followup@FreeBSD.org,
 marka@isc.org
Cc:  
Subject: Re: kern/173444: [socket] [patch] IPV6_USE_MIN_MTU and TCP is broken
Date: Fri, 25 Jan 2013 12:48:27 +1100

 --Apple-Mail=_63EA0392-6174-4870-B2DA-C892BB400A10
 Content-Transfer-Encoding: 7bit
 Content-Type: text/plain;
 	charset=us-ascii
 
 
 If IP6PO_MINMTU_ALL is set it should also impact mss negotiation.
 
 
 
 
 --Apple-Mail=_63EA0392-6174-4870-B2DA-C892BB400A10
 Content-Disposition: attachment;
 	filename=kern173444
 Content-Type: application/octet-stream;
 	name="kern173444"
 Content-Transfer-Encoding: 7bit
 
 Index: sys/netinet/tcp_input.c
 ===================================================================
 --- sys/netinet/tcp_input.c	(revision 245321)
 +++ sys/netinet/tcp_input.c	(working copy)
 @@ -1280,6 +1280,18 @@
  			    (void *)tcp_saveipgen, &tcp_savetcp, 0);
  #endif
  		tcp_dooptions(&to, optp, optlen, TO_SYN);
 +#ifdef INET6
 +		if (isipv6 && inp) {
 +			struct ip6_pktopts *opt;
 +			opt = inp->in6p_outputopts;
 +			if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL) {
 +				if (to.to_flags & TOF_MSS)
 +					to.to_mss = min(to.to_mss, IPV6_MMTU);
 +				else
 +					to.to_mss = IPV6_MMTU;
 +			}
 +		}
 +#endif
  		syncache_add(&inc, &to, th, inp, &so, m);
  		/*
  		 * Entry added to syncache and mbuf consumed.
 @@ -3326,7 +3338,11 @@
  	/* Initialize. */
  #ifdef INET6
  	if (isipv6) {
 +		struct ip6_pktopts *opt;
  		maxmtu = tcp_maxmtu6(&inp->inp_inc, mtuflags);
 +		opt = inp->inp_depend6.inp6_outputopts;
 +		if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
 +			maxmtu = min(maxmtu, IPV6_MMTU);
  		tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt;
  	} else
  #endif
 Index: sys/netinet/tcp_output.c
 ===================================================================
 --- sys/netinet/tcp_output.c	(revision 245321)
 +++ sys/netinet/tcp_output.c	(working copy)
 @@ -692,6 +692,15 @@
  		if (flags & TH_SYN) {
  			tp->snd_nxt = tp->iss;
  			to.to_mss = tcp_mssopt(&tp->t_inpcb->inp_inc);
 +#ifdef INET6
 +			if (isipv6) {
 +				struct ip6_pktopts *opt;
 +				opt = tp->t_inpcb->in6p_outputopts;
 +				if (opt &&
 +				    opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
 +					to.to_mss = min(to.to_mss, IPV6_MMTU);
 +			}
 +#endif
  			to.to_flags |= TOF_MSS;
  		}
  		/* Window scaling. */
 
 --Apple-Mail=_63EA0392-6174-4870-B2DA-C892BB400A10--

From: Mark Andrews <marka@isc.org>
To: bug-followup@FreeBSD.org,
 marka@isc.org
Cc:  
Subject: Re: kern/173444: [socket] [patch] IPV6_USE_MIN_MTU and TCP is broken
Date: Wed, 20 Mar 2013 14:51:41 +1100

 --Apple-Mail=_33372122-CD81-4FE1-9EBF-64D7DCCC1D46
 Content-Transfer-Encoding: 7bit
 Content-Type: text/plain;
 	charset=us-ascii
 
 Need to account for ipv6 and tcp header sizes in advertised mss.
 
 
 --Apple-Mail=_33372122-CD81-4FE1-9EBF-64D7DCCC1D46
 Content-Disposition: attachment;
 	filename=kern173444-rev2
 Content-Type: application/octet-stream;
 	name="kern173444-rev2"
 Content-Transfer-Encoding: 7bit
 
 Index: sys/netinet/ip6.h
 ===================================================================
 --- sys/netinet/ip6.h	(revision 248493)
 +++ sys/netinet/ip6.h	(working copy)
 @@ -256,6 +256,7 @@
  #define IPV6_HLIMDEC	1	/* subtracted when forwarding */
  
  #define IPV6_MMTU	1280	/* minimal MTU and reassembly. 1024 + 256 */
 +#define IPV6_MMSS	1220	/* maximum MSS when IP6_USE_MIN_MTU is 1 */
  #define IPV6_MAXPACKET	65535	/* ip6 max packet size without Jumbo payload*/
  #define IPV6_MAXOPTHDR	2048	/* max option header size, 256 64-bit words */
  
 Index: sys/netinet/tcp_input.c
 ===================================================================
 --- sys/netinet/tcp_input.c	(revision 248493)
 +++ sys/netinet/tcp_input.c	(working copy)
 @@ -1280,6 +1280,18 @@
  			    (void *)tcp_saveipgen, &tcp_savetcp, 0);
  #endif
  		tcp_dooptions(&to, optp, optlen, TO_SYN);
 +#ifdef INET6
 +		if (isipv6 && inp) {
 +			struct ip6_pktopts *opt;
 +			opt = inp->in6p_outputopts;
 +			if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL) {
 +				if (to.to_flags & TOF_MSS)
 +					to.to_mss = min(to.to_mss, IPV6_MMSS);
 +				else
 +					to.to_mss = IPV6_MMSS;
 +			}
 +		}
 +#endif
  		syncache_add(&inc, &to, th, inp, &so, m);
  		/*
  		 * Entry added to syncache and mbuf consumed.
 @@ -3356,7 +3368,11 @@
  	/* Initialize. */
  #ifdef INET6
  	if (isipv6) {
 +		struct ip6_pktopts *opt;
  		maxmtu = tcp_maxmtu6(&inp->inp_inc, mtuflags);
 +		opt = inp->inp_depend6.inp6_outputopts;
 +		if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
 +			maxmtu = min(maxmtu, IPV6_MMTU);
  		tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt;
  	} else
  #endif
 Index: sys/netinet/tcp_output.c
 ===================================================================
 --- sys/netinet/tcp_output.c	(revision 248493)
 +++ sys/netinet/tcp_output.c	(working copy)
 @@ -692,6 +692,15 @@
  		if (flags & TH_SYN) {
  			tp->snd_nxt = tp->iss;
  			to.to_mss = tcp_mssopt(&tp->t_inpcb->inp_inc);
 +#ifdef INET6
 +			if (isipv6) {
 +				struct ip6_pktopts *opt;
 +				opt = tp->t_inpcb->in6p_outputopts;
 +				if (opt &&
 +				    opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
 +					to.to_mss = min(to.to_mss, IPV6_MMSS);
 +			}
 +#endif
  			to.to_flags |= TOF_MSS;
  		}
  		/* Window scaling. */
 
 --Apple-Mail=_33372122-CD81-4FE1-9EBF-64D7DCCC1D46--
>Unformatted:
