Fix DecrementTTL option.
[tinc] / src / route.c
index 2785146..d7c4c87 100644 (file)
@@ -164,7 +164,7 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
                /* Found it */
                uint16_t oldmss = DATA(packet)[start + 22 + i] << 8 | DATA(packet)[start + 23 + i];
                uint16_t newmss = mtu - start - 20;
-               uint16_t csum = DATA(packet)[start + 16] << 8 | DATA(packet)[start + 17];
+               uint32_t csum = DATA(packet)[start + 16] << 8 | DATA(packet)[start + 17];
 
                if(oldmss <= newmss)
                        break;
@@ -175,11 +175,13 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
                DATA(packet)[start + 22 + i] = newmss >> 8;
                DATA(packet)[start + 23 + i] = newmss & 0xff;
                csum ^= 0xffff;
-               csum -= oldmss;
+               csum += oldmss ^ 0xffff;
                csum += newmss;
+               csum = (csum & 0xffff) + (csum >> 16);
+               csum += csum >> 16;
                csum ^= 0xffff;
                DATA(packet)[start + 16] = csum >> 8;
-               DATA(packet)[start + 17] = csum & 0xff;
+               DATA(packet)[start + 17] = csum;
                break;
        }
 }
@@ -782,15 +784,13 @@ static void route_arp(node_t *source, vpn_packet_t *packet) {
        if(subnet->owner == myself)
                return;                                          /* silently ignore */
 
-       memcpy(DATA(packet), DATA(packet) + ETH_ALEN, ETH_ALEN); /* copy destination address */
-       DATA(packet)[ETH_ALEN * 2 - 1] ^= 0xFF;                  /* mangle source address so it looks like it's not from us */
-
        memcpy(&addr, arp.arp_tpa, sizeof addr);                 /* save protocol addr */
        memcpy(arp.arp_tpa, arp.arp_spa, sizeof addr);           /* swap destination and source protocol address */
        memcpy(arp.arp_spa, &addr, sizeof addr);                 /* ... */
 
        memcpy(arp.arp_tha, arp.arp_sha, ETH_ALEN);              /* set target hard/proto addr */
-       memcpy(arp.arp_sha, DATA(packet) + ETH_ALEN, ETH_ALEN);  /* add fake source hard addr */
+       memcpy(arp.arp_sha, DATA(packet) + ETH_ALEN, ETH_ALEN);  /* set source hard/proto addr */
+       arp.arp_sha[ETH_ALEN - 1] ^= 0xFF;                       /* for consistency with route_packet() */
        arp.arp_op = htons(ARPOP_REPLY);
 
        /* Copy structs on stack back to packet */
@@ -902,7 +902,7 @@ static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
                        if(!checklength(source, packet, ethlen + ip_size))
                                return false;
 
-                       if(DATA(packet)[ethlen + 8] < 1) {
+                       if(DATA(packet)[ethlen + 8] <= 1) {
                                if(DATA(packet)[ethlen + 11] != IPPROTO_ICMP || DATA(packet)[ethlen + 32] != ICMP_TIME_EXCEEDED)
                                        route_ipv4_unreachable(source, packet, ethlen, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
                                return false;
@@ -925,7 +925,7 @@ static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
                        if(!checklength(source, packet, ethlen + ip6_size))
                                return false;
 
-                       if(DATA(packet)[ethlen + 7] < 1) {
+                       if(DATA(packet)[ethlen + 7] <= 1) {
                                if(DATA(packet)[ethlen + 6] != IPPROTO_ICMPV6 || DATA(packet)[ethlen + 40] != ICMP6_TIME_EXCEEDED)
                                        route_ipv6_unreachable(source, packet, ethlen, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
                                return false;