Ensure MTU probe replies are sent back the same way they came in.
[tinc] / src / net_packet.c
index dbf361f..e50135e 100644 (file)
@@ -164,11 +164,26 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
        logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname);
 
        if(!packet->data[0]) {
+               /* It's a probe request, send back a reply */
+
                packet->data[0] = 1;
+
+               /* Temporarily set udp_confirmed, so that the reply is sent
+                  back exactly the way it came in. */
+
+               bool udp_confirmed = n->status.udp_confirmed;
+               n->status.udp_confirmed = true;
                send_udppacket(n, packet);
+               n->status.udp_confirmed = udp_confirmed;
        } else {
+               /* It's a valid reply: now we know bidirectional communication
+                  is possible using the address and socket that the reply
+                  packet used. */
+
                n->status.udp_confirmed = true;
 
+               /* If we haven't established the PMTU yet, restart the discovery process. */
+
                if(n->mtuprobes > 30) {
                        if(n->minmtu)
                                n->mtuprobes = 30;
@@ -176,6 +191,8 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
                                n->mtuprobes = 1;
                }
 
+               /* If applicable, raise the minimum supported MTU */
+
                if(len > n->maxmtu)
                        len = n->maxmtu;
                if(n->minmtu < len)
@@ -447,24 +464,28 @@ static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock
        if(n->status.udp_confirmed)
                return;
 
-       /* Otherwise, go through the list of known addresses of
-          this node. The first address we try is always the
-          one in n->address; that could be set to the node's
-          reflexive UDP address discovered during key
-          exchange. The other known addresses are those found
-          in edges to this node. */
+       /* Send every third packet to n->address; that could be set
+          to the node's reflexive UDP address discovered during key
+          exchange. */
 
+       static int x = 0;
+       if(++x >= 3) {
+               x = 0;
+               return;
+       }
+
+       /* Otherwise, address are found in edges to this node.
+          So we pick a random edge and a random socket. */
 
        int i = 0;
        int j = rand() % n->edge_tree->count;
        edge_t *candidate = NULL;
 
-       for splay_each(edge_t, e, edge_weight_tree) {
-               if(e->to != n)
-                       continue;
-               i++;
-               if(!candidate || i == j)
-                       candidate = e;
+       for splay_each(edge_t, e, n->edge_tree) {
+               if(i++ == j) {
+                       candidate = e->reverse;
+                       break;
+               }
        }
 
        if(candidate) {