]> tinc-vpn.org Git - tinc/commitdiff
Correct for offset when (de)compressing packets
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 28 Mar 2026 14:48:43 +0000 (15:48 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 28 Mar 2026 14:48:43 +0000 (15:48 +0100)
src/net_packet.c

index 0b95a939bb84fdc874f115f1a4437d7d84806e3f..7c19cd5e49e1d8e1b1fc92cec476c6fcaaaf5df7 100644 (file)
 #include "net.h"
 #include "netutl.h"
 #include "protocol.h"
+#include "random.h"
 #include "route.h"
 #include "utils.h"
-#include "random.h"
+#include "xalloc.h"
 
 /* The minimum size of a probe is 14 bytes, but since we normally use CBC mode
    encryption, we can add a few extra random bytes without increasing the
@@ -236,30 +237,26 @@ static void udp_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
        }
 }
 
+static length_t compress_packet_lz4(uint8_t *dest, length_t dest_len, const uint8_t *source, length_t len) {
 #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);
+       return LZ4_compress_fast_extState(&lz4_stream, (const char *) source, (char *) dest, len, dest_len, 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;
+               lz4_state = xmalloc(LZ4_sizeofState());
        }
 
-       return LZ4_compress_fast_extState(lz4_state, (const char *) source, (char *) dest, len, MAXSIZE, 0);
+       return LZ4_compress_fast_extState(lz4_state, (const char *) source, (char *) dest, len, dest_len, 0);
 #endif /* HAVE_LZ4_BUILTIN */
-}
 #endif /* HAVE_LZ4 */
+       return 0;
+}
 
+static length_t compress_packet_lzo(uint8_t *dest, length_t dest_len, const uint8_t *source, length_t len, compression_level_t level) {
 #ifdef HAVE_LZO
-static length_t compress_packet_lzo(uint8_t *dest, const uint8_t *source, length_t len, compression_level_t level) {
-       lzo_uint lzolen = MAXSIZE;
+       lzo_uint lzolen = dest_len;
        int result;
 
        if(level == COMPRESS_LZO_HI) {
@@ -270,27 +267,35 @@ static length_t compress_packet_lzo(uint8_t *dest, const uint8_t *source, length
 
        if(result == LZO_E_OK) {
                return lzolen;
-       } else {
-               return 0;
        }
+
+#endif /* HAVE_LZO */
+
+       return 0;
 }
-#endif
 
-static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, compression_level_t level) {
+static length_t compress_packet_zlib(uint8_t *dest, length_t dest_len, const uint8_t *source, length_t len, compression_level_t level) {
+#ifdef HAVE_ZLIB
+       unsigned long result_len = dest_len;
+
+       if(compress2(dest, &result_len, source, len, level) == Z_OK) {
+               return result_len;
+       }
+
+#endif /* HAVE_ZLIB */
+
+       return 0;
+}
+
+static length_t compress_packet(uint8_t *dest, length_t dest_len, const uint8_t *source, length_t len, compression_level_t level) {
        switch(level) {
-#ifdef HAVE_LZ4
 
        case COMPRESS_LZ4:
-               return compress_packet_lz4(dest, source, len);
-#endif
-
-#ifdef HAVE_LZO
+               return compress_packet_lz4(dest, dest_len, source, len);
 
        case COMPRESS_LZO_HI:
        case COMPRESS_LZO_LO:
-               return compress_packet_lzo(dest, source, len, level);
-#endif
-#ifdef HAVE_ZLIB
+               return compress_packet_lzo(dest, dest_len, source, len, level);
 
        case COMPRESS_ZLIB_9:
        case COMPRESS_ZLIB_8:
@@ -301,42 +306,39 @@ static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t l
        case COMPRESS_ZLIB_3:
        case COMPRESS_ZLIB_2:
        case COMPRESS_ZLIB_1: {
-               unsigned long dest_len = MAXSIZE;
+               return compress_packet_zlib(dest, dest_len, source, len, level);
+       }
 
-               if(compress2(dest, &dest_len, source, len, level) == Z_OK) {
-                       return dest_len;
+       case COMPRESS_NONE:
+               if(dest_len >= len) {
+                       memcpy(dest, source, len);
+                       return len;
                } else {
                        return 0;
                }
-       }
-
-#endif
-
-       case COMPRESS_NONE:
-               memcpy(dest, source, len);
-               return len;
 
        default:
                return 0;
        }
 }
 
-static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, compression_level_t level) {
+static length_t uncompress_packet(uint8_t *dest, length_t dest_len, const uint8_t *source, length_t len, compression_level_t level) {
        switch(level) {
 #ifdef HAVE_LZ4
 
        case COMPRESS_LZ4:
-               return LZ4_decompress_safe((char *)source, (char *) dest, len, MAXSIZE);
+
+               return LZ4_decompress_safe((char *)source, (char *) dest, len, dest_len);
 
 #endif
 #ifdef HAVE_LZO
 
        case COMPRESS_LZO_HI:
        case COMPRESS_LZO_LO: {
-               lzo_uint dst_len = MAXSIZE;
+               lzo_uint lzo_len = dest_len;
 
-               if(lzo1x_decompress_safe(source, len, dest, &dst_len, NULL) == LZO_E_OK) {
-                       return dst_len;
+               if(lzo1x_decompress_safe(source, len, dest, &lzo_len, NULL) == LZO_E_OK) {
+                       return lzo_len;
                } else {
                        return 0;
                }
@@ -354,7 +356,6 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t
        case COMPRESS_ZLIB_3:
        case COMPRESS_ZLIB_2:
        case COMPRESS_ZLIB_1: {
-               unsigned long destlen = MAXSIZE;
                static z_stream stream;
 
                if(stream.next_in) {
@@ -366,7 +367,7 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t
                stream.next_in = source;
                stream.avail_in = len;
                stream.next_out = dest;
-               stream.avail_out = destlen;
+               stream.avail_out = dest_len;
                stream.total_out = 0;
 
                if(inflate(&stream, Z_FINISH) == Z_STREAM_END) {
@@ -379,8 +380,12 @@ static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t
 #endif
 
        case COMPRESS_NONE:
-               memcpy(dest, source, len);
-               return len;
+               if(dest_len >= len) {
+                       memcpy(dest, source, len);
+                       return len;
+               } else {
+                       return 0;
+               }
 
        default:
                return 0;
@@ -555,7 +560,7 @@ static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
        if(n->incompression != COMPRESS_NONE) {
                vpn_packet_t *outpkt = pkt[nextpkt++];
 
-               if(!(outpkt->len = uncompress_packet(DATA(outpkt), DATA(inpkt), inpkt->len, n->incompression))) {
+               if(!(outpkt->len = uncompress_packet(DATA(outpkt), MAXSIZE - outpkt->offset, DATA(inpkt), inpkt->len, n->incompression))) {
                        logger(DEBUG_TRAFFIC, LOG_ERR, "Error while uncompressing packet from %s (%s)",
                               n->name, n->hostname);
                        return false;
@@ -701,7 +706,7 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
 
        if(n->outcompression != COMPRESS_NONE) {
                outpkt.offset = 0;
-               length_t len = compress_packet(DATA(&outpkt) + offset, DATA(origpkt) + offset, origpkt->len - offset, n->outcompression);
+               length_t len = compress_packet(DATA(&outpkt) + offset, MAXSIZE - offset, DATA(origpkt) + offset, origpkt->len - offset, n->outcompression);
 
                if(!len) {
                        logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
@@ -856,7 +861,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
        if(n->outcompression != COMPRESS_NONE) {
                outpkt = pkt[nextpkt++];
 
-               if(!(outpkt->len = compress_packet(DATA(outpkt), DATA(inpkt), inpkt->len, n->outcompression))) {
+               if(!(outpkt->len = compress_packet(DATA(outpkt), MAXSIZE - outpkt->offset, DATA(inpkt), inpkt->len, n->outcompression))) {
                        logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)",
                               n->name, n->hostname);
                        return;
@@ -1101,7 +1106,7 @@ bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t
        int offset = (type & PKT_MAC) ? 0 : 14;
 
        if(type & PKT_COMPRESSED) {
-               length_t ulen = uncompress_packet(DATA(&inpkt) + offset, (const uint8_t *)data, len, from->incompression);
+               length_t ulen = uncompress_packet(DATA(&inpkt) + offset, MAXSIZE - inpkt.offset, (const uint8_t *)data, len, from->incompression);
 
                if(!ulen) {
                        return false;