keep track of round trip times of UDP pings
[tinc] / src / net_packet.c
index 1aa881c..6ce6431 100644 (file)
@@ -23,6 +23,7 @@
 #include "system.h"
 
 #ifdef HAVE_ZLIB
+#define ZLIB_CONST
 #include <zlib.h>
 #endif
 
@@ -30,6 +31,7 @@
 #include LZO1X_H
 #endif
 
+#include "address_cache.h"
 #include "cipher.h"
 #include "conf.h"
 #include "connection.h"
@@ -100,6 +102,7 @@ static void udp_probe_timeout_handler(void *data) {
 
        logger(DEBUG_TRAFFIC, LOG_INFO, "Too much time has elapsed since last UDP ping response from %s (%s), stopping UDP communication", n->name, n->hostname);
        n->status.udp_confirmed = false;
+       n->udp_ping_rtt = -1;
        n->maxrecentlen = 0;
        n->mtuprobes = 0;
        n->minmtu = 0;
@@ -138,7 +141,8 @@ static void send_udp_probe_reply(node_t *n, vpn_packet_t *packet, length_t len)
 static void udp_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
        if(!DATA(packet)[0]) {
                logger(DEBUG_TRAFFIC, LOG_INFO, "Got UDP probe request %d from %s (%s)", packet->len, n->name, n->hostname);
-               return send_udp_probe_reply(n, packet, len);
+               send_udp_probe_reply(n, packet, len);
+               return;
        }
 
        if(DATA(packet)[0] == 2) {
@@ -148,15 +152,32 @@ static void udp_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
                len = ntohs(len16);
        }
 
-       logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d UDP probe reply %d from %s (%s)", DATA(packet)[0], len, n->name, n->hostname);
+       if (n->udp_ping_sent.tv_sec != 0) { // a probe in flight
+               gettimeofday(&now, NULL);
+               struct timeval rtt;
+               timersub(&now, &n->udp_ping_sent, &rtt);
+               n->udp_ping_rtt = rtt.tv_sec*1000000L + rtt.tv_usec;
+               logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d UDP probe reply %d from %s (%s) rtt=%ld.%03ld", DATA(packet)[0], len, n->name, n->hostname, n->udp_ping_rtt/1000, n->udp_ping_rtt%1000);
+       } else {
+               logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d UDP probe reply %d from %s (%s)", DATA(packet)[0], len, 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. */
-       n->status.udp_confirmed = true;
+       if(!n->status.udp_confirmed) {
+               n->status.udp_confirmed = true;
+               fprintf(stderr, "Updating address cache...\n");
+
+               if(!n->address_cache) {
+                       n->address_cache = open_address_cache(n);
+               }
+
+               reset_address_cache(n->address_cache, &n->address);
+       }
 
-       // Reset the UDP ping timer.
-       n->udp_ping_sent = now;
+       // Reset the UDP ping timer. (no probe in flight)
+       n->udp_ping_sent.tv_sec = 0;
 
        if(udp_discovery) {
                timeout_del(&n->udp_ping_timeout);
@@ -238,9 +259,22 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t
 #ifdef HAVE_ZLIB
        else {
                unsigned long destlen = MAXSIZE;
+               static z_stream stream;
 
-               if(uncompress(dest, &destlen, source, len) == Z_OK) {
-                       return destlen;
+               if(stream.next_in) {
+                       inflateReset(&stream);
+               } else {
+                       inflateInit(&stream);
+               }
+
+               stream.next_in = source;
+               stream.avail_in = len;
+               stream.next_out = dest;
+               stream.avail_out = destlen;
+               stream.total_out = 0;
+
+               if(inflate(&stream, Z_FINISH) == Z_STREAM_END) {
+                       return stream.total_out;
                } else {
                        return -1;
                }
@@ -680,7 +714,8 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
        }
 
        if(n->status.sptps) {
-               return send_sptps_packet(n, origpkt);
+               send_sptps_packet(n, origpkt);
+               return;
        }
 
 #ifdef DISABLE_LEGACY
@@ -773,7 +808,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
                listen_socket[sock].priority = origpriority;
 
                switch(sa->sa.sa_family) {
-#if defined(IPPROTO_IP) && defined(IP_TOS)
+#if defined(IP_TOS)
 
                case AF_INET:
                        logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting IPv4 outgoing packet priority to %d", origpriority);
@@ -784,7 +819,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
 
                        break;
 #endif
-#if defined(IPPROTO_IPV6) & defined(IPV6_TCLASS)
+#if defined(IPV6_TCLASS)
 
                case AF_INET6:
                        logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting IPv6 outgoing packet priority to %d", origpriority);
@@ -869,7 +904,7 @@ bool send_sptps_data(node_t *to, node_t *from, int type, const void *data, size_
        if(relay_supported) {
                if(direct) {
                        /* Inform the recipient that this packet was sent directly. */
-                       node_id_t nullid = {};
+                       node_id_t nullid = {{0}};
                        memcpy(buf_ptr, &nullid, sizeof(nullid));
                        buf_ptr += sizeof(nullid);
                } else {
@@ -929,7 +964,7 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t
                if(!from->status.validkey) {
                        from->status.validkey = true;
                        from->status.waitingforkey = false;
-                       logger(DEBUG_META, LOG_INFO, "SPTPS key exchange with %s (%s) succesful", from->name, from->hostname);
+                       logger(DEBUG_META, LOG_INFO, "SPTPS key exchange with %s (%s) successful", from->name, from->hostname);
                }
 
                return true;
@@ -1093,8 +1128,9 @@ static void try_udp(node_t *n) {
        int interval = n->status.udp_confirmed ? udp_discovery_keepalive_interval : udp_discovery_interval;
 
        if(ping_tx_elapsed.tv_sec >= interval) {
+               gettimeofday(&now, NULL);
+               n->udp_ping_sent = now; // a probe in flight
                send_udp_probe_packet(n, MIN_PROBE_SIZE);
-               n->udp_ping_sent = now;
 
                if(localdiscovery && !n->status.udp_confirmed && n->prevedge) {
                        n->status.send_locally = true;
@@ -1347,7 +1383,8 @@ static void try_tx_sptps(node_t *n, bool mtu) {
                        return;
                }
 
-               return try_tx(via, mtu);
+               try_tx(via, mtu);
+               return;
        }
 
        /* Otherwise, try to establish UDP connectivity. */
@@ -1569,7 +1606,7 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
 
 static void handle_incoming_vpn_packet(listen_socket_t *ls, vpn_packet_t *pkt, sockaddr_t *addr) {
        char *hostname;
-       node_id_t nullid = {};
+       node_id_t nullid = {{0}};
        node_t *from, *to;
        bool direct = false;
 
@@ -1701,14 +1738,14 @@ void handle_incoming_vpn_data(void *data, int flags) {
 
                iov[i] = (struct iovec) {
                        .iov_base = DATA(&pkt[i]),
-                        .iov_len = MAXSIZE,
+                       .iov_len = MAXSIZE,
                };
 
                msg[i].msg_hdr = (struct msghdr) {
                        .msg_name = &addr[i].sa,
-                        .msg_namelen = sizeof(addr)[i],
-                         .msg_iov = &iov[i],
-                          .msg_iovlen = 1,
+                       .msg_namelen = sizeof(addr)[i],
+                       .msg_iov = &iov[i],
+                       .msg_iovlen = 1,
                };
        }