X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fnet_packet.c;h=2a86d657e35e783b827f3e927829fb528ce67aa4;hb=fb0cfccf7dc2240b576011edcf74fd5b058916cb;hp=ae5a8402a7af159ad3873b877854c2b286a0c485;hpb=56aad1bb486675ff9aba31418708cc179eea0381;p=tinc diff --git a/src/net_packet.c b/src/net_packet.c index ae5a8402..2a86d657 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -1,7 +1,7 @@ /* net_packet.c -- Handles in- and outgoing VPN packets - Copyright (C) 1998-2003 Ivo Timmermans , - 2000-2003 Guus Sliepen + Copyright (C) 1998-2005 Ivo Timmermans, + 2000-2006 Guus Sliepen 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 @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net_packet.c,v 1.1.2.49 2003/12/27 16:32:52 guus Exp $ + $Id$ */ #include "system.h" @@ -29,14 +29,13 @@ #include #include -#include +#include LZO1X_H -#include "avl_tree.h" +#include "splay_tree.h" #include "conf.h" #include "connection.h" #include "device.h" #include "ethernet.h" -#include "event.h" #include "graph.h" #include "list.h" #include "logger.h" @@ -53,8 +52,6 @@ #endif int keylifetime = 0; -int keyexpires = 0; -bool strictsource = true; 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]; @@ -62,15 +59,14 @@ static void send_udppacket(node_t *, vpn_packet_t *); #define MAX_SEQNO 1073741824 -void send_mtu_probe(node_t *n) -{ +static void send_mtu_probe_handler(int fd, short events, void *data) { + node_t *n = data; vpn_packet_t packet; int len, i; cp(); n->mtuprobes++; - n->mtuevent = NULL; if(n->mtuprobes >= 10 && !n->minmtu) { ifdebug(TRAFFIC) logger(LOG_INFO, _("No response to MTU probes from %s (%s)"), n->name, n->hostname); @@ -97,11 +93,13 @@ void send_mtu_probe(node_t *n) send_udppacket(n, &packet); } - n->mtuevent = xmalloc(sizeof(*n->mtuevent)); - n->mtuevent->handler = (event_handler_t)send_mtu_probe; - n->mtuevent->data = n; - n->mtuevent->time = now + 1; - event_add(n->mtuevent); + event_add(&n->mtuevent, &(struct timeval){1, 0}); +} + +void send_mtu_probe(node_t *n) { + if(!timeout_initialized(&n->mtuevent)) + timeout_set(&n->mtuevent, send_mtu_probe_handler, n); + send_mtu_probe_handler(0, 0, n); } void mtu_probe_h(node_t *n, vpn_packet_t *packet) { @@ -116,8 +114,7 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet) { } } -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 +134,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,8 +154,7 @@ 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) -{ +static void receive_packet(node_t *n, vpn_packet_t *packet) { cp(); ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), @@ -168,43 +163,38 @@ static void receive_packet(node_t *n, vpn_packet_t *packet) route(n, packet); } -static bool authenticate_udppacket(node_t *n, vpn_packet_t *inpkt) { - char hmac[EVP_MAX_MD_SIZE]; - - if(inpkt->len < sizeof(inpkt->seqno) + (myself->digest ? myself->maclength : 0)) - return false; - - /* Check the message authentication code */ - - if(myself->digest && myself->maclength) { - HMAC(myself->digest, myself->key, myself->keylength, - (char *) &inpkt->seqno, inpkt->len - myself->maclength, hmac, NULL); - - if(memcmp(hmac, (char *) &inpkt->seqno + inpkt->len - myself->maclength, myself->maclength)) - return false; - } - - return true; -} - -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; vpn_packet_t *outpkt = pkt[0]; int outlen, outpad; + unsigned char hmac[EVP_MAX_MD_SIZE]; int i; cp(); - if(!authenticate_udppacket(n, inpkt)) { - ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), - n->name, n->hostname); + /* Check packet length */ + + if(inpkt->len < sizeof(inpkt->seqno) + myself->maclength) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got too short packet from %s (%s)"), + n->name, n->hostname); return; } - inpkt->len -= myself->digest ? myself->maclength : 0; + /* Check the message authentication code */ + + if(myself->digest && myself->maclength) { + inpkt->len -= myself->maclength; + HMAC(myself->digest, myself->key, myself->keylength, + (unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL); + + if(memcmp(hmac, (char *) &inpkt->seqno + inpkt->len, myself->maclength)) { + ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), + n->name, n->hostname); + return; + } + } /* Decrypt the packet */ @@ -212,9 +202,9 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) outpkt = pkt[nextpkt++]; if(!EVP_DecryptInit_ex(&packet_ctx, NULL, NULL, NULL, NULL) - || !EVP_DecryptUpdate(&packet_ctx, (char *) &outpkt->seqno, &outlen, - (char *) &inpkt->seqno, inpkt->len) - || !EVP_DecryptFinal_ex(&packet_ctx, (char *) &outpkt->seqno + outlen, &outpad)) { + || !EVP_DecryptUpdate(&packet_ctx, (unsigned char *) &outpkt->seqno, &outlen, + (unsigned char *) &inpkt->seqno, inpkt->len) + || !EVP_DecryptFinal_ex(&packet_ctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) { ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Error decrypting packet from %s (%s): %s"), n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL)); return; @@ -236,20 +226,24 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) memset(n->late, 0, sizeof(n->late)); } else if (inpkt->seqno <= n->received_seqno) { - if(inpkt->seqno <= n->received_seqno - sizeof(n->late) * 8 || !(n->late[(inpkt->seqno / 8) % sizeof(n->late)] & (1 << inpkt->seqno % 8))) { + 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); - } else - for(i = n->received_seqno + 1; i < inpkt->seqno; i++) - n->late[(inpkt->seqno / 8) % sizeof(n->late)] |= 1 << i % 8; + return; + } + } else { + for(i = n->received_seqno + 1; i < inpkt->seqno; i++) + n->late[(i / 8) % sizeof(n->late)] |= 1 << i % 8; } } - n->received_seqno = inpkt->seqno; - n->late[(n->received_seqno / 8) % sizeof(n->late)] &= ~(1 << n->received_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; if(n->received_seqno > MAX_SEQNO) - keyexpires = 0; + regenerate_key(); /* Decompress the packet */ @@ -265,17 +259,13 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) inpkt = outpkt; } - if(n->connection) - n->connection->last_ping_time = now; - if(!inpkt->data[12] && !inpkt->data[13]) mtu_probe_h(n, inpkt); 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(); @@ -286,10 +276,10 @@ 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 *inpkt) -{ +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; int nextpkt = 0; vpn_packet_t *outpkt; int origlen; @@ -353,9 +343,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *inpkt) outpkt = pkt[nextpkt++]; if(!EVP_EncryptInit_ex(&n->packet_ctx, NULL, NULL, NULL, NULL) - || !EVP_EncryptUpdate(&n->packet_ctx, (char *) &outpkt->seqno, &outlen, - (char *) &inpkt->seqno, inpkt->len) - || !EVP_EncryptFinal_ex(&n->packet_ctx, (char *) &outpkt->seqno + outlen, &outpad)) { + || !EVP_EncryptUpdate(&n->packet_ctx, (unsigned char *) &outpkt->seqno, &outlen, + (unsigned char *) &inpkt->seqno, inpkt->len) + || !EVP_EncryptFinal_ex(&n->packet_ctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) { ifdebug(TRAFFIC) logger(LOG_ERR, _("Error while encrypting packet to %s (%s): %s"), n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL)); goto end; @@ -368,8 +358,8 @@ static void send_udppacket(node_t *n, vpn_packet_t *inpkt) /* Add the message authentication code */ if(n->digest && n->maclength) { - HMAC(n->digest, n->key, n->keylength, (char *) &inpkt->seqno, - inpkt->len, (char *) &inpkt->seqno + inpkt->len, &outlen); + HMAC(n->digest, n->key, n->keylength, (unsigned char *) &inpkt->seqno, + inpkt->len, (unsigned char *) &inpkt->seqno + inpkt->len, NULL); inpkt->len += n->maclength; } @@ -405,14 +395,13 @@ static void send_udppacket(node_t *n, vpn_packet_t *inpkt) } end: - inpkt->len = origlen; + origpkt->len = origlen; } /* 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(); @@ -448,9 +437,8 @@ 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) -{ - avl_node_t *node; +void broadcast_packet(const node_t *from, vpn_packet_t *packet) { + splay_node_t *node; connection_t *c; cp(); @@ -458,6 +446,9 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) ifdebug(TRAFFIC) logger(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"), packet->len, from->name, from->hostname); + if(from != myself) + send_packet(myself, packet); + for(node = connection_tree->head; node; node = node->next) { c = node->data; @@ -466,8 +457,7 @@ void broadcast_packet(const node_t *from, vpn_packet_t *packet) } } -void flush_queue(node_t *n) -{ +void flush_queue(node_t *n) { list_node_t *node, *next; cp(); @@ -481,14 +471,12 @@ void flush_queue(node_t *n) } } -void handle_incoming_vpn_data(int sock) -{ +void handle_incoming_vpn_data(int sock, short events, void *data) { vpn_packet_t pkt; char *hostname; sockaddr_t from; socklen_t fromlen = sizeof(from); node_t *n; - static time_t lasttime = 0; cp(); @@ -503,28 +491,20 @@ void handle_incoming_vpn_data(int sock) n = lookup_node_udp(&from); - if(!n && !strictsource && myself->digest && myself->maclength && lasttime != now) { - avl_node_t *node; - - lasttime = now; - - for(node = node_tree->head; node; node = node->next) { - n = node->data; - - if(authenticate_udppacket(n, &pkt)) { - update_node_address(n, &from); - logger(LOG_DEBUG, _("Updated address of node %s to %s"), n->name, n->hostname); - break; - } - } - } - if(!n) { hostname = sockaddr2hostname(&from); - logger(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname); + logger(LOG_WARNING, _("Received UDP packet from unknown source %s"), + hostname); free(hostname); return; } receive_udppacket(n, &pkt); } + +void handle_device_data(int sock, short events, void *data) { + vpn_packet_t packet; + + if(read_packet(&packet)) + route(myself, &packet); +}