X-Git-Url: https://www.tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fnet_packet.c;h=d700fd6b7502c34fb686e5df5bd473773408240c;hb=e3c763eae89df9a69bb2d611238ef18f78de311f;hp=26e4907140556c49025c24750cfd0113a71b1e9f;hpb=bc87b450034382858822b918f43bdf31ad8e6995;p=tinc diff --git a/src/net_packet.c b/src/net_packet.c index 26e49071..d700fd6b 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -56,6 +56,7 @@ static void send_udppacket(node_t *, vpn_packet_t *); unsigned replaywin = 16; bool localdiscovery = false; +sockaddr_t localdiscovery_address; #define MAX_SEQNO 1073741824 @@ -178,12 +179,20 @@ void send_mtu_probe(node_t *n) { } 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]) { + logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe request %d from %s (%s)", packet->len, n->name, n->hostname); + /* It's a probe request, send back a reply */ - packet->data[0] = 1; + /* Type 2 probe replies were introduced in protocol 17.3 */ + if ((n->options >> 24) == 3) { + uint8_t* data = packet->data; + *data++ = 2; + uint16_t len16 = htons(len); memcpy(data, &len16, 2); data += 2; + } else { + /* Legacy protocol: n won't understand type 2 probe replies. */ + packet->data[0] = 1; + } /* Temporarily set udp_confirmed, so that the reply is sent back exactly the way it came in. */ @@ -193,6 +202,16 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { send_udppacket(n, packet); n->status.udp_confirmed = udp_confirmed; } else { + length_t probelen = len; + if (packet->data[0] == 2) { + if (len < 3) + logger(DEBUG_TRAFFIC, LOG_WARNING, "Received invalid (too short) MTU probe reply from %s (%s)", n->name, n->hostname); + else { + uint16_t probelen16; memcpy(&probelen16, packet->data + 1, 2); probelen = ntohs(probelen16); + } + } + logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d MTU probe reply %d from %s (%s)", packet->data[0], probelen, n->name, n->hostname); + /* It's a valid reply: now we know bidirectional communication is possible using the address and socket that the reply packet used. */ @@ -202,7 +221,7 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { /* If we haven't established the PMTU yet, restart the discovery process. */ if(n->mtuprobes > 30) { - if (len == n->maxmtu + 8) { + if (probelen == n->maxmtu + 8) { logger(DEBUG_TRAFFIC, LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname); n->maxmtu = MTU; n->mtuprobes = 10; @@ -217,10 +236,10 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { /* If applicable, raise the minimum supported MTU */ - if(len > n->maxmtu) - len = n->maxmtu; - if(n->minmtu < len) - n->minmtu = len; + if(probelen > n->maxmtu) + probelen = n->maxmtu; + if(n->minmtu < probelen) + n->minmtu = probelen; /* Calculate RTT and bandwidth. The RTT is the time between the MTU probe burst was sent and the first @@ -237,7 +256,7 @@ static void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { n->rtt = diff.tv_sec + diff.tv_usec * 1e-6; n->probe_time = now; } else if(n->probe_counter == 3) { - n->bandwidth = 2.0 * len / (diff.tv_sec + diff.tv_usec * 1e-6); + n->bandwidth = 2.0 * probelen / (diff.tv_sec + diff.tv_usec * 1e-6); logger(DEBUG_TRAFFIC, LOG_DEBUG, "%s (%s) RTT %.2f ms, burst bandwidth %.3f Mbit/s, rx packet loss %.2f %%", n->name, n->hostname, n->rtt * 1e3, n->bandwidth * 8e-6, n->packetloss * 1e2); } } @@ -580,12 +599,22 @@ static void choose_broadcast_address(const node_t *n, const sockaddr_t **sa, int *sock = rand() % listen_sockets; if(listen_socket[*sock].sa.sa.sa_family == AF_INET6) { - broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port; - broadcast_ipv6.in6.sin6_scope_id = listen_socket[*sock].sa.in6.sin6_scope_id; - *sa = &broadcast_ipv6; + if(localdiscovery_address.sa.sa_family == AF_INET6) { + localdiscovery_address.in6.sin6_port = n->prevedge->address.in.sin_port; + *sa = &localdiscovery_address; + } else { + broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port; + broadcast_ipv6.in6.sin6_scope_id = listen_socket[*sock].sa.in6.sin6_scope_id; + *sa = &broadcast_ipv6; + } } else { - broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port; - *sa = &broadcast_ipv4; + if(localdiscovery_address.sa.sa_family == AF_INET) { + localdiscovery_address.in.sin_port = n->prevedge->address.in.sin_port; + *sa = &localdiscovery_address; + } else { + broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port; + *sa = &broadcast_ipv4; + } } }