Yet another patch, on top of the previous ones.
This one tries to get the default value of TCP_MAXSEG by creating a temporary 
TCP socket, so that one can remove the "mss" entry from its configuration file,
 and reset the mss value for any transferred socket from the old process.

Olivier
>From 7dc2432f3a7c4a9e9531adafa4524a199e394f90 Mon Sep 17 00:00:00 2001
From: Olivier Houchard <ohouch...@haproxy.com>
Date: Wed, 12 Apr 2017 19:32:15 +0200
Subject: [PATCH 10/10] MINOR: tcp: Attempt to reset TCP_MAXSEG when reusing a
 socket.

Guess the default value for TCP_MAXSEG by binding a temporary TCP socket and
getting it, and use that in case the we're reusing a socket from the old
process, and its TCP_MAXSEG is different. That way one can reset the
TCP_MAXSEG value to the default one when reusing sockets.
---
 src/proto_tcp.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 52 insertions(+), 3 deletions(-)

diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index ea6b8f7..8050f3e 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -110,6 +110,12 @@ static struct protocol proto_tcpv6 = {
        .nb_listeners = 0,
 };
 
+/* Default TCP parameters, got by opening a temporary TCP socket. */
+#ifdef TCP_MAXSEG
+static int default_tcp_maxseg = -1;
+static int default_tcp6_maxseg = -1;
+#endif
+
 /* Binds ipv4/ipv6 address <local> to socket <fd>, unless <flags> is set, in 
which
  * case we try to bind <remote>. <flags> is a 2-bit field consisting of :
  *  - 0 : ignore remote address (may even be a NULL pointer)
@@ -829,6 +835,35 @@ int tcp_bind_listener(struct listener *listener, char 
*errmsg, int errlen)
        int ext, ready;
        socklen_t ready_len;
        const char *msg = NULL;
+#ifdef TCP_MAXSEG
+
+       /* Create a temporary TCP socket to get default parameters we can't
+        * guess.
+        * */
+       ready_len = sizeof(default_tcp_maxseg);
+       if (default_tcp_maxseg == -1) {
+               default_tcp_maxseg = -2;
+               fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+               if (fd < 0)
+                       Warning("Failed to create a temporary socket!\n");
+               else {
+                       if (getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, 
&default_tcp_maxseg,
+                           &ready_len) == -1)
+                               Warning("Failed to get the default value of 
TCP_MAXSEG\n");
+               }
+       }
+       if (default_tcp6_maxseg == -1) {
+               default_tcp6_maxseg = -2;
+               fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+               if (fd >= 0) {
+                       if (getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, 
&default_tcp6_maxseg,
+                           &ready_len) == -1)
+                               Warning("Failed ot get the default value of 
TCP_MAXSEG for IPv6\n");
+                       close(fd);
+               }
+       }
+#endif
+
 
        /* ensure we never return garbage */
        if (errlen)
@@ -960,10 +995,24 @@ int tcp_bind_listener(struct listener *listener, char 
*errmsg, int errlen)
                        msg = "cannot set MSS";
                        err |= ERR_WARN;
                }
+       } else if (ext) {
+               int tmpmaxseg = -1;
+               int defaultmss;
+               socklen_t len = sizeof(tmpmaxseg);
+
+               if (listener->addr.ss_family == AF_INET)
+                       defaultmss = default_tcp_maxseg;
+               else
+                       defaultmss = default_tcp6_maxseg;
+
+               getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &tmpmaxseg, &len);
+               if (tmpmaxseg != defaultmss &&
+                   setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG,
+                   &defaultmss, sizeof(defaultmss)) == -1) {
+                       msg = "cannot set MSS";
+                       err |= ERR_WARN;
+               }
        }
-       /* XXX: No else, the way to get the default MSS will vary from system
-        * to system.
-        */
 #endif
 #if defined(TCP_USER_TIMEOUT)
        if (listener->tcp_ut) {
-- 
2.9.3

Reply via email to