X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fnet_packet.c;h=54deb26c70ab66c1a2e755225ba4f053a93ce733;hp=a438d3e9577e45aefd5ffeabc49d5da1955fe6ce;hb=708314df2f61675d0f54e541c9fff62ac1f433b5;hpb=ddb8cb0779ed36d17ce186dd0bf67e9f0c860d28 diff --git a/src/net_packet.c b/src/net_packet.c index a438d3e9..54deb26c 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -1,7 +1,9 @@ /* net_packet.c -- Handles in- and outgoing VPN packets Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2010 Guus Sliepen + 2000-2011 Guus Sliepen + 2010 Timothy Redaelli + 2010 Brandon Black This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,7 +43,6 @@ #include "ethernet.h" #include "event.h" #include "graph.h" -#include "list.h" #include "logger.h" #include "net.h" #include "netutl.h" @@ -59,6 +60,8 @@ static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999 static void send_udppacket(node_t *, vpn_packet_t *); +unsigned replaywin = 16; + #define MAX_SEQNO 1073741824 // mtuprobes == 1..30: initial discovery, send bursts with 1 second interval @@ -81,16 +84,21 @@ void send_mtu_probe(node_t *n) { } if(n->mtuprobes > 32) { + if(!n->minmtu) { + n->mtuprobes = 31; + timeout = pinginterval; + goto end; + } + ifdebug(TRAFFIC) logger(LOG_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname); n->mtuprobes = 1; n->minmtu = 0; n->maxmtu = MTU; } - if(n->mtuprobes >= 10 && !n->minmtu) { + if(n->mtuprobes >= 10 && n->mtuprobes < 32 && !n->minmtu) { ifdebug(TRAFFIC) logger(LOG_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname); - n->mtuprobes = 0; - return; + n->mtuprobes = 31; } if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) { @@ -144,12 +152,17 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { packet->data[0] = 1; send_udppacket(n, packet); } else { + if(n->mtuprobes > 30) { + if(n->minmtu) + n->mtuprobes = 30; + else + n->mtuprobes = 1; + } + if(len > n->maxmtu) len = n->maxmtu; if(n->minmtu < len) n->minmtu = len; - if(n->mtuprobes > 30) - n->mtuprobes = 30; } } @@ -292,25 +305,32 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { inpkt->len -= sizeof(inpkt->seqno); inpkt->seqno = ntohl(inpkt->seqno); - if(inpkt->seqno != n->received_seqno + 1) { - if(inpkt->seqno >= n->received_seqno + sizeof(n->late) * 8) { - logger(LOG_WARNING, "Lost %d packets from %s (%s)", - inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); - - memset(n->late, 0, sizeof(n->late)); - } else if (inpkt->seqno <= n->received_seqno) { - if((n->received_seqno >= sizeof(n->late) * 8 && inpkt->seqno <= n->received_seqno - sizeof(n->late) * 8) || !(n->late[(inpkt->seqno / 8) % sizeof(n->late)] & (1 << inpkt->seqno % 8))) { - logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", - n->name, n->hostname, inpkt->seqno, n->received_seqno); - return; + if(replaywin) { + if(inpkt->seqno != n->received_seqno + 1) { + if(inpkt->seqno >= n->received_seqno + replaywin * 8) { + if(n->farfuture++ < replaywin >> 2) { + logger(LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)", + n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture); + return; + } + logger(LOG_WARNING, "Lost %d packets from %s (%s)", + inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); + memset(n->late, 0, replaywin); + } else if (inpkt->seqno <= n->received_seqno) { + if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) { + logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", + n->name, n->hostname, inpkt->seqno, n->received_seqno); + return; + } + } else { + for(i = n->received_seqno + 1; i < inpkt->seqno; i++) + n->late[(i / 8) % replaywin] |= 1 << i % 8; } - } else { - for(i = n->received_seqno + 1; i < inpkt->seqno; i++) - n->late[(i / 8) % sizeof(n->late)] |= 1 << i % 8; } + + n->farfuture = 0; + n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8); } - - n->late[(inpkt->seqno / 8) % sizeof(n->late)] &= ~(1 << inpkt->seqno % 8); if(inpkt->seqno > n->received_seqno) n->received_seqno = inpkt->seqno; @@ -344,7 +364,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { receive_packet(n, inpkt); } -void receive_tcppacket(connection_t *c, char *buffer, int len) { +void receive_tcppacket(connection_t *c, const char *buffer, int len) { vpn_packet_t outpkt; outpkt.len = len; @@ -365,7 +385,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { vpn_packet_t *outpkt; int origlen; int outlen, outpad; +#if defined(SOL_IP) && defined(IP_TOS) static int priority = 0; +#endif int origpriority; int sock; @@ -381,7 +403,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { "No valid key known yet for %s (%s), forwarding via TCP", n->name, n->hostname); - if(n->last_req_key + 10 < now) { + if(n->last_req_key + 10 <= now) { send_req_key(n); n->last_req_key = now; } @@ -496,7 +518,7 @@ void send_packet(const node_t *n, vpn_packet_t *packet) { if(n == myself) { if(overwrite_mac) memcpy(packet->data, mymac.x, ETH_ALEN); - write_packet(packet); + devops.write(packet); return; } @@ -552,20 +574,21 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { avl_node_t *node; edge_t *e; node_t *n = NULL; + bool hard = false; static time_t last_hard_try = 0; for(node = edge_weight_tree->head; node; node = node->next) { e = node->data; + if(e->to == myself) + continue; + if(sockaddrcmp_noport(from, &e->address)) { if(last_hard_try == now) continue; - last_hard_try = now; + hard = true; } - if(!n) - n = e->to; - if(!try_mac(e->to, pkt)) continue; @@ -573,6 +596,9 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { break; } + if(hard) + last_hard_try = now; + return n; }