X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fnet_packet.c;h=417c74ece48d162a35eacfcf10a81b1d4cc6a07e;hb=7ab400aebdc38e7ee5dafc0a2291bbbea25e3f7c;hp=25d3efb861047cbea812a83f5b1f686224a577b0;hpb=9eb34ebfbe763e50b6efb1168dec52331559f7d1;p=tinc diff --git a/src/net_packet.c b/src/net_packet.c index 25d3efb8..417c74ec 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -25,12 +25,18 @@ #ifdef HAVE_ZLIB #define ZLIB_CONST #include +#include + #endif #ifdef HAVE_LZO #include LZO1X_H #endif +#ifdef LZ4_H +#include LZ4_H +#endif + #include "address_cache.h" #include "cipher.h" #include "conf.h" @@ -64,6 +70,12 @@ int keylifetime = 0; static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS]; #endif +#ifdef HAVE_LZ4_BUILTIN +static LZ4_stream_t lz4_stream; +#else +static void *lz4_state = NULL; +#endif /* HAVE_LZ4_BUILTIN */ + static void send_udppacket(node_t *, vpn_packet_t *); unsigned replaywin = 32; @@ -206,57 +218,126 @@ static void udp_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { } } -static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { - if(level == 0) { - memcpy(dest, source, len); - return len; - } else if(level == 10) { +#ifdef HAVE_LZ4 +static length_t compress_packet_lz4(uint8_t *dest, const uint8_t *source, length_t len) { +#ifdef HAVE_LZ4_BUILTIN + return LZ4_compress_fast_extState(&lz4_stream, (const char *) source, (char *) dest, len, MAXSIZE, 0); +#else + + /* @FIXME: Put this in a better place, and free() it too. */ + if(lz4_state == NULL) { + lz4_state = malloc(LZ4_sizeofState()); + } + + if(lz4_state == NULL) { + logger(DEBUG_ALWAYS, LOG_ERR, "Failed to allocate lz4_state, error: %i", errno); + return 0; + } + + return LZ4_compress_fast_extState(lz4_state, (const char *) source, (char *) dest, len, MAXSIZE, 0); +#endif /* HAVE_LZ4_BUILTIN */ +} +#endif /* HAVE_LZ4 */ + #ifdef HAVE_LZO - lzo_uint lzolen = MAXSIZE; - lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem); +static length_t compress_packet_lzo(uint8_t *dest, const uint8_t *source, length_t len, int level) { + assert(level == 10 || level == 11); + + lzo_uint lzolen = MAXSIZE; + int result; + + if(level == 11) { + result = lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem); + } else { // level == 10 + result = lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem); + } + + if(result == LZO_E_OK) { return lzolen; -#else + } else { return 0; + } +} #endif - } else if(level < 10) { -#ifdef HAVE_ZLIB - unsigned long destlen = MAXSIZE; - if(compress2(dest, &destlen, source, len, level) == Z_OK) { - return destlen; - } else +static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { + switch(level) { +#ifdef HAVE_LZ4 + + case 12: + return compress_packet_lz4(dest, source, len); #endif - return 0; - } else { + #ifdef HAVE_LZO - lzo_uint lzolen = MAXSIZE; - lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem); - return lzolen; -#else - return 0; + + case 11: + case 10: + return compress_packet_lzo(dest, source, len, level); #endif +#ifdef HAVE_ZLIB + + case 9: + case 8: + case 7: + case 6: + case 5: + case 4: + case 3: + case 2: + case 1: { + unsigned long dest_len = MAXSIZE; + + if(compress2(dest, (unsigned long *) &dest_len, source, len, level) == Z_OK) { + return dest_len; + } else { + return 0; + } } - return 0; -} +#endif -static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { - if(level == 0) { + case 0: memcpy(dest, source, len); return len; - } else if(level > 9) { -#ifdef HAVE_LZO - lzo_uint lzolen = MAXSIZE; - if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK) { - return lzolen; - } else + default: + return 0; + } +} + +static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { + switch(level) { +#ifdef HAVE_LZ4 + + case 12: + return LZ4_decompress_safe((char *)source, (char *) dest, len, MAXSIZE); + #endif +#ifdef HAVE_LZO + + case 11: + case 10: { + lzo_uint dst_len = MAXSIZE; + + if(lzo1x_decompress_safe(source, len, dest, (lzo_uint *) &dst_len, NULL) == LZO_E_OK) { + return dst_len; + } else { return 0; + } } +#endif #ifdef HAVE_ZLIB - else { + + case 9: + case 8: + case 7: + case 6: + case 5: + case 4: + case 3: + case 2: + case 1: { unsigned long destlen = MAXSIZE; static z_stream stream; @@ -281,7 +362,13 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t #endif - return 0; + case 0: + memcpy(dest, source, len); + return len; + + default: + return 0; + } } /* VPN packet I/O */ @@ -1085,14 +1172,14 @@ static void try_sptps(node_t *n) { static void send_udp_probe_packet(node_t *n, int len) { vpn_packet_t packet; - packet.offset = DEFAULT_PACKET_OFFSET; - memset(DATA(&packet), 0, 14); if(len > sizeof(packet.data)) { logger(DEBUG_TRAFFIC, LOG_INFO, "Truncating probe length %d to %s (%s)", len, n->name, n->hostname); len = sizeof(packet.data); } + packet.offset = DEFAULT_PACKET_OFFSET; + memset(DATA(&packet), 0, 14); randomize(DATA(&packet) + 14, len - 14); packet.len = len; packet.priority = 0; @@ -1333,14 +1420,19 @@ static void try_mtu(node_t *n) { const length_t minmtu = MAX(n->minmtu, 512); const float interval = n->maxmtu - minmtu; - /* The core of the discovery algorithm is this exponential. - It produces very large probes early in the cycle, and then it very quickly decreases the probe size. - This reflects the fact that in the most difficult cases, we don't get any feedback for probes that - are too large, and therefore we need to concentrate on small offsets so that we can quickly converge - on the precise MTU as we are approaching it. - The last probe of the cycle is always 1 byte in size - this is to make sure we'll get at least one - reply per cycle so that we can make progress. */ - const length_t offset = powf(interval, multiplier * cycle_position / (probes_per_cycle - 1)); + length_t offset = 0; + + /* powf can be underflowed if n->maxmtu is less than 512 due to the minmtu MAX bound */ + if(interval > 0) { + /* The core of the discovery algorithm is this exponential. + It produces very large probes early in the cycle, and then it very quickly decreases the probe size. + This reflects the fact that in the most difficult cases, we don't get any feedback for probes that + are too large, and therefore we need to concentrate on small offsets so that we can quickly converge + on the precise MTU as we are approaching it. + The last probe of the cycle is always 1 byte in size - this is to make sure we'll get at least one + reply per cycle so that we can make progress. */ + offset = powf(interval, multiplier * cycle_position / (probes_per_cycle - 1)); + } length_t maxmtu = n->maxmtu; send_udp_probe_packet(n, minmtu + offset);