Make MSS clamping configurable, but enabled by default.
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 16 Jan 2010 19:16:33 +0000 (20:16 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 16 Jan 2010 19:16:33 +0000 (20:16 +0100)
It can either be set globally in tinc.conf, or per-node in host config files.

doc/tinc.conf.5.in
doc/tinc.texi
src/connection.h
src/net_setup.c
src/protocol_auth.c
src/route.c

index 8e644450614da02748b30ae1f31a32f47154bfcb..e2ded368642ad760a5b69229460c23f504db0be6 100644 (file)
@@ -347,6 +347,11 @@ Furthermore, specifying
 will turn off packet encryption.
 It is best to use only those ciphers which support CBC mode.
 
 will turn off packet encryption.
 It is best to use only those ciphers which support CBC mode.
 
+.It Va ClampMSS Li = yes | no Pq yes
+This option specifies whether tinc should clamp the maximum segment size (MSS)
+of TCP packets to the path MTU. This helps in situations where ICMP
+Fragmentation Needed or Packet too Big messages are dropped by firewalls.
+
 .It Va Compression Li = Ar level Pq 0
 This option sets the level of compression used for UDP packets.
 Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
 .It Va Compression Li = Ar level Pq 0
 This option sets the level of compression used for UDP packets.
 Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
index 35658188494a6b048dda3459a3c4e204389cbee8..d2b09fa16abbfdce41c29df3bde2b6b21aaac3ea 100644 (file)
@@ -956,6 +956,12 @@ Any cipher supported by OpenSSL is recognized.
 Furthermore, specifying "none" will turn off packet encryption.
 It is best to use only those ciphers which support CBC mode.
 
 Furthermore, specifying "none" will turn off packet encryption.
 It is best to use only those ciphers which support CBC mode.
 
+@cindex ClampMSS
+@item ClampMSS = <yes|no> (yes)
+This option specifies whether tinc should clamp the maximum segment size (MSS)
+of TCP packets to the path MTU. This helps in situations where ICMP
+Fragmentation Needed or Packet too Big messages are dropped by firewalls.
+
 @cindex Compression
 @item Compression = <@var{level}> (0)
 This option sets the level of compression used for UDP packets.
 @cindex Compression
 @item Compression = <@var{level}> (0)
 This option sets the level of compression used for UDP packets.
index b3a7e33ff1d391a9d5953cded8dc932d31016943..d5c14bd599ed210975d8fa5e51caca473f15d013 100644 (file)
@@ -29,6 +29,7 @@
 #define OPTION_INDIRECT                0x0001
 #define OPTION_TCPONLY         0x0002
 #define OPTION_PMTU_DISCOVERY  0x0004
 #define OPTION_INDIRECT                0x0001
 #define OPTION_TCPONLY         0x0002
 #define OPTION_PMTU_DISCOVERY  0x0004
+#define OPTION_CLAMP_MSS       0x0008
 
 typedef struct connection_status_t {
        int pinged:1;                           /* sent ping */
 
 typedef struct connection_status_t {
        int pinged:1;                           /* sent ping */
index 369c8a40017e14fb60c6d388665a4aaa7ceea073..7d20803d28f755843d5ed2dbb6b7acce4c784f6d 100644 (file)
@@ -303,6 +303,12 @@ bool setup_myself(void) {
        if(choice)
                myself->options |= OPTION_PMTU_DISCOVERY;
 
        if(choice)
                myself->options |= OPTION_PMTU_DISCOVERY;
 
+       choice = true;
+       get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
+       get_config_bool(lookup_config(myself->connection->config_tree, "ClampMSS"), &choice);
+       if(choice)
+               myself->options |= OPTION_CLAMP_MSS;
+
        get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
 
 #if !defined(SOL_IP) || !defined(IP_TOS)
        get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
 
 #if !defined(SOL_IP) || !defined(IP_TOS)
index c2df4cd83badc6e478af94f36167ceaac809e357..4707dcebb9affae0af861d3158a8d882a5297a9a 100644 (file)
@@ -453,6 +453,11 @@ bool send_ack(connection_t *c) {
        if(myself->options & OPTION_PMTU_DISCOVERY)
                c->options |= OPTION_PMTU_DISCOVERY;
 
        if(myself->options & OPTION_PMTU_DISCOVERY)
                c->options |= OPTION_PMTU_DISCOVERY;
 
+       choice = myself->options & OPTION_CLAMP_MSS;
+       get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice);
+       if(choice)
+               c->options |= OPTION_CLAMP_MSS;
+
        get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
 
        return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options);
        get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight);
 
        return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, c->options);
@@ -496,6 +501,7 @@ bool ack_h(connection_t *c) {
        int weight, mtu;
        uint32_t options;
        node_t *n;
        int weight, mtu;
        uint32_t options;
        node_t *n;
+       bool choice;
 
        if(sscanf(c->buffer, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
                logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
 
        if(sscanf(c->buffer, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) {
                logger(LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name,
@@ -536,6 +542,13 @@ bool ack_h(connection_t *c) {
        if(get_config_int(lookup_config(myself->connection->config_tree, "PMTU"), &mtu) && mtu < n->mtu)
                n->mtu = mtu;
 
        if(get_config_int(lookup_config(myself->connection->config_tree, "PMTU"), &mtu) && mtu < n->mtu)
                n->mtu = mtu;
 
+       if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) {
+               if(choice)
+                       c->options |= OPTION_CLAMP_MSS;
+               else
+                       c->options &= ~OPTION_CLAMP_MSS;
+       }
+
        /* Activate this connection */
 
        c->allow_request = ALL;
        /* Activate this connection */
 
        c->allow_request = ALL;
index 77bec047b4738f0c2c6a18789aebe3546714735c..c04b0ad757ebc46d34698e3d8a8e0b6853050f5a 100644 (file)
@@ -94,7 +94,7 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
 }
 
 static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
 }
 
 static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
-       if(!via || via == myself)
+       if(!via || via == myself || !(via->options & OPTION_CLAMP_MSS))
                return;
 
        /* Find TCP header */
                return;
 
        /* Find TCP header */
@@ -112,6 +112,9 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
        /* Use data offset field to calculate length of options field */
        int len = ((packet->data[start + 12] >> 4) - 5) * 4;
 
        /* Use data offset field to calculate length of options field */
        int len = ((packet->data[start + 12] >> 4) - 5) * 4;
 
+       if(packet->len < start + 20 + len)
+               return;
+
        /* Search for MSS option header */
        for(int i = 0; i < len;) {
                if(packet->data[start + 20 + i] == 0)
        /* Search for MSS option header */
        for(int i = 0; i < len;) {
                if(packet->data[start + 20 + i] == 0)