X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fnet_packet.c;h=05336b0f2265d4a097c7aff4047761b095d40b08;hp=1730023d17c6f54c673896bbf4c25faf70b309f7;hb=a227843b739d279b63adcf3736ebb03d856080c4;hpb=3308d13e7e3bf20cfeaf6f2ab17228a9820cea66 diff --git a/src/net_packet.c b/src/net_packet.c index 1730023d..05336b0f 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -13,11 +13,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id$ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "system.h" @@ -54,23 +52,24 @@ int keylifetime = 0; int keyexpires = 0; -EVP_CIPHER_CTX packet_ctx; static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS]; static void send_udppacket(node_t *, vpn_packet_t *); #define MAX_SEQNO 1073741824 -void send_mtu_probe(node_t *n) -{ +void send_mtu_probe(node_t *n) { vpn_packet_t packet; int len, i; - cp(); - n->mtuprobes++; n->mtuevent = NULL; + if(!n->status.reachable) { + logger(LOG_DEBUG, _("Trying to send MTU probe to unreachable node %s (%s)"), n->name, n->hostname); + return; + } + if(n->mtuprobes >= 10 && !n->minmtu) { ifdebug(TRAFFIC) logger(LOG_INFO, _("No response to MTU probes from %s (%s)"), n->name, n->hostname); return; @@ -83,7 +82,7 @@ void send_mtu_probe(node_t *n) return; } - len = n->minmtu + 1 + random() % (n->maxmtu - n->minmtu); + len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu); if(len < 64) len = 64; @@ -104,20 +103,19 @@ void send_mtu_probe(node_t *n) event_add(n->mtuevent); } -void mtu_probe_h(node_t *n, vpn_packet_t *packet) { +void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { ifdebug(TRAFFIC) logger(LOG_INFO, _("Got MTU probe length %d from %s (%s)"), packet->len, n->name, n->hostname); if(!packet->data[0]) { packet->data[0] = 1; send_packet(n, packet); } else { - if(n->minmtu < packet->len) - n->minmtu = packet->len; + if(n->minmtu < len) + n->minmtu = len; } } -static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) -{ +static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { if(level == 10) { lzo_uint lzolen = MAXSIZE; lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem); @@ -137,8 +135,7 @@ static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t l return -1; } -static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) -{ +static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { if(level > 9) { lzo_uint lzolen = MAXSIZE; if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK) @@ -158,18 +155,14 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t /* VPN packet I/O */ -static void receive_packet(node_t *n, vpn_packet_t *packet) -{ - cp(); - +static void receive_packet(node_t *n, vpn_packet_t *packet) { ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname); route(n, packet); } -static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) -{ +static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) { unsigned char hmac[EVP_MAX_MD_SIZE]; if(!n->indigest || !n->inmaclength || !n->inkey || inpkt->len < sizeof inpkt->seqno + n->inmaclength) @@ -180,8 +173,7 @@ static bool try_mac(const node_t *n, const vpn_packet_t *inpkt) return !memcmp(hmac, (char *) &inpkt->seqno + inpkt->len - n->inmaclength, n->inmaclength); } -static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) -{ +static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { vpn_packet_t pkt1, pkt2; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; int nextpkt = 0; @@ -190,8 +182,6 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) unsigned char hmac[EVP_MAX_MD_SIZE]; int i; - cp(); - if(!n->inkey) { ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got packet from %s (%s) but he hasn't got our key yet"), n->name, n->hostname); @@ -271,6 +261,8 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) /* Decompress the packet */ + length_t origlen = inpkt->len; + if(n->incompression) { outpkt = pkt[nextpkt++]; @@ -281,6 +273,8 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) } inpkt = outpkt; + + origlen -= MTU/64 + 20; } inpkt->priority = 0; @@ -289,17 +283,14 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) n->connection->last_ping_time = now; if(!inpkt->data[12] && !inpkt->data[13]) - mtu_probe_h(n, inpkt); + mtu_probe_h(n, inpkt, origlen); else receive_packet(n, inpkt); } -void receive_tcppacket(connection_t *c, char *buffer, int len) -{ +void receive_tcppacket(connection_t *c, char *buffer, int len) { vpn_packet_t outpkt; - cp(); - outpkt.len = len; if(c->options & OPTION_TCPONLY) outpkt.priority = 0; @@ -310,8 +301,7 @@ void receive_tcppacket(connection_t *c, char *buffer, int len) receive_packet(c->node, &outpkt); } -static void send_udppacket(node_t *n, vpn_packet_t *origpkt) -{ +static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { vpn_packet_t pkt1, pkt2; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; vpn_packet_t *inpkt = origpkt; @@ -323,7 +313,10 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) int origpriority; int sock; - cp(); + if(!n->status.reachable) { + ifdebug(TRAFFIC) logger(LOG_INFO, _("Trying to send UDP packet to unreachable node %s (%s)"), n->name, n->hostname); + return; + } /* Make sure we have a valid key */ @@ -342,9 +335,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) return; } - if(!n->minmtu && (inpkt->data[12] | inpkt->data[13])) { + if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { ifdebug(TRAFFIC) logger(LOG_INFO, - _("No minimum MTU established yet for %s (%s), forwarding via TCP"), + _("Packet for %s (%s) larger than minimum MTU, forwarding via TCP"), n->name, n->hostname); send_tcppacket(n->nexthop->connection, origpkt); @@ -438,12 +431,9 @@ end: /* send a packet to the given vpn ip. */ -void send_packet(const node_t *n, vpn_packet_t *packet) -{ +void send_packet(const node_t *n, vpn_packet_t *packet) { node_t *via; - cp(); - if(n == myself) { if(overwrite_mac) memcpy(packet->data, mymac.x, ETH_ALEN); @@ -475,19 +465,22 @@ void send_packet(const node_t *n, vpn_packet_t *packet) /* Broadcast a packet using the minimum spanning tree */ -void broadcast_packet(const node_t *from, vpn_packet_t *packet) -{ +void broadcast_packet(const node_t *from, vpn_packet_t *packet) { avl_node_t *node; connection_t *c; - cp(); - ifdebug(TRAFFIC) logger(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"), packet->len, from->name, from->hostname); - if(from != myself) + if(from != myself) { send_packet(myself, packet); + // In TunnelServer mode, do not forward broadcast packets. + // The MST might not be valid and create loops. + if(tunnelserver) + return; + } + for(node = connection_tree->head; node; node = node->next) { c = node->data; @@ -520,20 +513,18 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { return n; } -void handle_incoming_vpn_data(int sock) -{ +void handle_incoming_vpn_data(int sock) { vpn_packet_t pkt; char *hostname; sockaddr_t from; socklen_t fromlen = sizeof(from); node_t *n; - cp(); - pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); if(pkt.len < 0) { - logger(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); + if(errno != EAGAIN && errno != EINTR) + logger(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); return; } @@ -545,12 +536,14 @@ void handle_incoming_vpn_data(int sock) n = try_harder(&from, &pkt); if(n) update_node_udp(n, &from); - else { + else ifdebug(PROTOCOL) { hostname = sockaddr2hostname(&from); logger(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname); free(hostname); return; } + else + return; } receive_udppacket(n, &pkt);