#include "system.h"
#ifdef HAVE_ZLIB
+#define ZLIB_CONST
#include <zlib.h>
#endif
#include LZO1X_H
#endif
+#include "address_cache.h"
#include "cipher.h"
#include "conf.h"
#include "connection.h"
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;
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) {
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 * 1000000 + rtt.tv_usec;
+ logger(DEBUG_TRAFFIC, LOG_INFO, "Got type %d UDP probe reply %d from %s (%s) rtt=%d.%03d", 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);
#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;
}
}
if(n->status.sptps) {
- return send_sptps_packet(n, origpkt);
+ send_sptps_packet(n, origpkt);
+ return;
}
#ifdef DISABLE_LEGACY
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);
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);
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 {
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;
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;
return;
}
- return try_tx(via, mtu);
+ try_tx(via, mtu);
+ return;
}
/* Otherwise, try to establish UDP connectivity. */
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;
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,
};
}