[MEDIUM] add support for TCP MSS adjustment for listeners
Sometimes it can be useful to limit the advertised TCP MSS on
incoming connections, for instance when requests come through
a VPN or when the system is running with jumbo frames enabled.
Passing the "mss <value>" arguments to a "bind" line will set
the value. This works under Linux >= 2.6.28, and maybe a few
earlier ones, though due to an old kernel bug most of earlier
versions will probably ignore it. It is also possible that some
other OSes will support this.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 9ec869e..413aeae 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -23,6 +23,8 @@
#include <fcntl.h>
#include <unistd.h>
+#include <netinet/tcp.h>
+
#include <common/cfgparse.h>
#include <common/config.h>
#include <common/memory.h>
@@ -960,6 +962,35 @@
return -1;
#endif
}
+ if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
+#ifdef TCP_MAXSEG
+ struct listener *l;
+ int mss;
+
+ if (!*args[cur_arg + 1]) {
+ Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
+ file, linenum, args[0]);
+ return -1;
+ }
+
+ mss = str2uic(args[cur_arg + 1]);
+ if (mss < 1 || mss > 65535) {
+ Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
+ file, linenum, args[0]);
+ return -1;
+ }
+
+ for (l = curproxy->listen; l != last_listen; l = l->next)
+ l->maxseg = mss;
+
+ cur_arg += 2;
+ continue;
+#else
+ Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
+ file, linenum, args[0], args[cur_arg]);
+ return -1;
+#endif
+ }
if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
#ifdef CONFIG_HAP_LINUX_TPROXY
struct listener *l;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index e9b3ae3..adf4e23 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -251,6 +251,15 @@
}
}
#endif
+#ifdef TCP_MAXSEG
+ if (listener->maxseg) {
+ if (setsockopt(fd, SOL_TCP, TCP_MAXSEG,
+ &listener->maxseg, sizeof(listener->maxseg)) == -1) {
+ msg = "cannot set MSS";
+ err |= ERR_WARN;
+ }
+ }
+#endif
if (bind(fd, (struct sockaddr *)&listener->addr, listener->proto->sock_addrlen) == -1) {
err |= ERR_RETRYABLE | ERR_ALERT;
msg = "cannot bind socket";