git: de156263a598 - main - Several IP level socket options may affect TCP.

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Wed, 27 Oct 2021 15:22:58 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=de156263a598a0277b7bbc13ef8bdc6f4541b604

commit de156263a598a0277b7bbc13ef8bdc6f4541b604
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2021-10-26 03:40:12 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2021-10-27 15:21:59 +0000

    Several IP level socket options may affect TCP.
    
    After handling them in IP level ctloutput, pass them down to TCP
    ctloutput.
    
    We already have a hack to handle IPV6_USE_MIN_MTU. Leave it in place
    for now, but comment out how it should be handled.
    
    For IPv4 we are interested in IP_TOS and IP_TTL.
    
    Reviewed by:            rrs
    Differential Revision:  https://reviews.freebsd.org/D32655
---
 sys/netinet/tcp_usrreq.c | 75 ++++++++++++++++++++++++++++++++++--------------
 1 file changed, 54 insertions(+), 21 deletions(-)

diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 0fca9b88e6f3..b6e345bd454c 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1739,20 +1739,44 @@ tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt)
 
 	if (sopt->sopt_level != IPPROTO_TCP) {
 #ifdef INET6
-		if (inp->inp_vflag & INP_IPV6PROTO) {
+		if (inp->inp_vflag & INP_IPV6PROTO)
 			error = ip6_ctloutput(inp->inp_socket, sopt);
-			/*
-			 * In case of the IPV6_USE_MIN_MTU socket option,
-			 * the INC_IPV6MINMTU flag to announce a corresponding
-			 * MSS during the initial handshake.
-			 * If the TCP connection is not in the front states,
-			 * just reduce the MSS being used.
-			 * This avoids the sending of TCP segments which will
-			 * be fragmented at the IPv6 layer.
-			 */
-			if ((error == 0) &&
-			    (sopt->sopt_level == IPPROTO_IPV6) &&
-			    (sopt->sopt_name == IPV6_USE_MIN_MTU)) {
+#endif
+#if defined(INET6) && defined(INET)
+		else
+#endif
+#ifdef INET
+			error = ip_ctloutput(inp->inp_socket, sopt);
+#endif
+		/*
+		 * When an IP-level socket option affects TCP, pass control
+		 * down to stack tfb_tcp_ctloutput, otherwise return what
+		 * IP level returned.
+		 */
+		switch (sopt->sopt_level) {
+#ifdef INET6
+		case IPPROTO_IPV6:
+			if ((inp->inp_vflag & INP_IPV6PROTO) == 0)
+				return (error);
+			switch (sopt->sopt_name) {
+			case IPV6_TCLASS:
+				/* Notify tcp stacks that care (e.g. RACK). */
+				break;
+			case IPV6_USE_MIN_MTU:
+				/*
+				 * XXXGL: this handling should belong to
+				 * stack specific tfb_tcp_ctloutput, we
+				 * should just break here.
+				 *
+				 * In case of the IPV6_USE_MIN_MTU socket
+				 * option, the INC_IPV6MINMTU flag to announce
+				 * a corresponding MSS during the initial
+				 * handshake.  If the TCP connection is not in
+				 * the front states, just reduce the MSS being
+				 * used.  This avoids the sending of TCP
+				 * segments which will be fragmented at the
+				 * IPv6 layer.
+				 */
 				INP_WLOCK(inp);
 				if ((inp->inp_flags &
 				    (INP_TIMEWAIT | INP_DROPPED))) {
@@ -1775,18 +1799,27 @@ tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt)
 					}
 				}
 				INP_WUNLOCK(inp);
+				/* FALLTHROUGH */
+			default:
+				return (error);
 			}
-		}
-#endif /* INET6 */
-#if defined(INET6) && defined(INET)
-		else
+			break;
 #endif
 #ifdef INET
-		{
-			error = ip_ctloutput(inp->inp_socket, sopt);
-		}
+		case IPPROTO_IP:
+			switch (sopt->sopt_name) {
+			case IP_TOS:
+			case IP_TTL:
+				/* Notify tcp stacks that care (e.g. RACK). */
+				break;
+			default:
+				return (error);
+			}
+			break;
 #endif
-		return (error);
+		default:
+			return (error);
+		}
 	} else if (sopt->sopt_name == TCP_FUNCTION_BLK) {
 		/*
 		 * Protect the TCP option TCP_FUNCTION_BLK so