unsigned replaywin = 16;
bool localdiscovery = false;
+sockaddr_t localdiscovery_address;
#define MAX_SEQNO 1073741824
}
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. */
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. */
/* 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;
/* 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
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);
}
}
size_t outlen;
if(n->status.sptps) {
+ if(!n->sptps.state) {
+ if(!n->status.waitingforkey) {
+ logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but we haven't exchanged keys yet", n->name, n->hostname);
+ send_req_key(n);
+ } else {
+ logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
+ }
+ return;
+ }
sptps_receive_data(&n->sptps, (char *)&inpkt->seqno, inpkt->len);
return;
}
if(!cipher_active(n->incipher)) {
- logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet",
- n->name, n->hostname);
+ logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
return;
}
*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;
+ }
}
}
/* Add the message authentication code */
if(digest_active(n->outdigest)) {
- digest_create(n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len);
+ if(!digest_create(n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len)) {
+ logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname);
+ goto end;
+ }
+
inpkt->len += digest_length(n->outdigest);
}