aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2022-03-15 16:55:47 +0100
committerGitHub <noreply@github.com>2022-03-15 16:55:47 +0100
commit9e22c88e0abff87f18fee632495b02255f585c0c (patch)
tree96d717dc46c8dcf92bfe99cf2f2af42736a7f62e
parentb83e9f20e7f01807ad97d62d9a076dba9d5f4b45 (diff)
QUIC: convert logs to standard mechanism (#1485)
-rw-r--r--src/lib/protocols/quic.c156
1 files changed, 59 insertions, 97 deletions
diff --git a/src/lib/protocols/quic.c b/src/lib/protocols/quic.c
index 631f47d42..bdd6cc133 100644
--- a/src/lib/protocols/quic.c
+++ b/src/lib/protocols/quic.c
@@ -32,9 +32,6 @@
#include <gcrypt_light.h>
#endif
-// #define DEBUG_CRYPT
-// #define QUIC_DEBUG
-
/* This dissector handles GQUIC and IETF-QUIC both.
Main references:
* https://groups.google.com/a/chromium.org/g/proto-quic/c/wVHBir-uRU0?pli=1
@@ -244,7 +241,6 @@ static uint16_t gquic_get_u16(const uint8_t *buf, uint32_t version)
}
-#ifdef DEBUG_CRYPT
char *__gcry_err(gpg_error_t err, char *buf, size_t buflen)
{
gpg_strerror_r(err, buf, buflen);
@@ -254,7 +250,6 @@ char *__gcry_err(gpg_error_t err, char *buf, size_t buflen)
buf[buflen - 1] = '\0';
return buf;
}
-#endif /* DEBUG_CRYPT */
static uint64_t pntoh64(const void *p)
{
@@ -403,7 +398,8 @@ static gcry_error_t hkdf_extract(int hashalgo, const uint8_t *salt, size_t salt_
* custom label prefix. If "context_hash" is NULL, then an empty context is
* used. Otherwise it must have the same length as the hash algorithm output.
*/
-static int tls13_hkdf_expand_label_context(int md, const StringInfo *secret,
+static int tls13_hkdf_expand_label_context(struct ndpi_detection_module_struct *ndpi_struct,
+ int md, const StringInfo *secret,
const char *label_prefix, const char *label,
const uint8_t *context_hash, uint8_t context_length,
uint16_t out_len, uint8_t **out)
@@ -423,15 +419,13 @@ static int tls13_hkdf_expand_label_context(int md, const StringInfo *secret,
gcry_error_t err;
const unsigned int label_prefix_length = (unsigned int)strlen(label_prefix);
const unsigned label_length = (unsigned int)strlen(label);
-#ifdef DEBUG_CRYPT
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
char buferr[128];
#endif
/* Some sanity checks */
if(!(label_length > 0 && label_prefix_length + label_length <= 255)) {
-#ifdef DEBUG_CRYPT
- printf("Failed sanity checks\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed sanity checks\n");
return 0;
}
@@ -483,9 +477,7 @@ static int tls13_hkdf_expand_label_context(int md, const StringInfo *secret,
ndpi_free(info_data);
if(err) {
-#ifdef DEBUG_CRYPT
- printf("Failed hkdf_expand: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed hkdf_expand: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
ndpi_free(*out);
*out = NULL;
return 0;
@@ -493,11 +485,12 @@ static int tls13_hkdf_expand_label_context(int md, const StringInfo *secret,
return 1;
}
-static int tls13_hkdf_expand_label(int md, const StringInfo *secret,
+static int tls13_hkdf_expand_label(struct ndpi_detection_module_struct *ndpi_struct,
+ int md, const StringInfo *secret,
const char *label_prefix, const char *label,
uint16_t out_len, unsigned char **out)
{
- return tls13_hkdf_expand_label_context(md, secret, label_prefix, label, NULL, 0, out_len, out);
+ return tls13_hkdf_expand_label_context(ndpi_struct, md, secret, label_prefix, label, NULL, 0, out_len, out);
}
@@ -505,12 +498,13 @@ static int tls13_hkdf_expand_label(int md, const StringInfo *secret,
* From epan/dissectors/packet-quic.c
*/
-static int quic_hkdf_expand_label(int hash_algo, uint8_t *secret, uint32_t secret_len,
+static int quic_hkdf_expand_label(struct ndpi_detection_module_struct *ndpi_struct,
+ int hash_algo, uint8_t *secret, uint32_t secret_len,
const char *label, uint8_t *out, uint32_t out_len)
{
const StringInfo secret_si = { secret, secret_len };
uint8_t *out_mem = NULL;
- if(tls13_hkdf_expand_label(hash_algo, &secret_si, "tls13 ", label, out_len, &out_mem)) {
+ if(tls13_hkdf_expand_label(ndpi_struct, hash_algo, &secret_si, "tls13 ", label, out_len, &out_mem)) {
memcpy(out, out_mem, out_len);
ndpi_free(out_mem);
return 1;
@@ -540,7 +534,8 @@ static void quic_ciphers_reset(quic_ciphers *ciphers)
* Expands the secret (length MUST be the same as the "hash_algo" digest size)
* and initialize cipher with the new key.
*/
-static int quic_hp_cipher_init(quic_hp_cipher *hp_cipher, int hash_algo,
+static int quic_hp_cipher_init(struct ndpi_detection_module_struct *ndpi_struct,
+ quic_hp_cipher *hp_cipher, int hash_algo,
uint8_t key_length, uint8_t *secret,
uint32_t version)
{
@@ -548,13 +543,14 @@ static int quic_hp_cipher_init(quic_hp_cipher *hp_cipher, int hash_algo,
uint32_t hash_len = gcry_md_get_algo_dlen(hash_algo);
char const * const label = is_version_with_v1_labels(version) ? "quic hp" : "quicv2 hp";
- if(!quic_hkdf_expand_label(hash_algo, secret, hash_len, label, hp_key, key_length)) {
+ if(!quic_hkdf_expand_label(ndpi_struct, hash_algo, secret, hash_len, label, hp_key, key_length)) {
return 0;
}
return gcry_cipher_setkey(hp_cipher->hp_cipher, hp_key, key_length) == 0;
}
-static int quic_pp_cipher_init(quic_pp_cipher *pp_cipher, int hash_algo,
+static int quic_pp_cipher_init(struct ndpi_detection_module_struct *ndpi_struct,
+ quic_pp_cipher *pp_cipher, int hash_algo,
uint8_t key_length, uint8_t *secret,
uint32_t version)
{
@@ -567,8 +563,8 @@ static int quic_pp_cipher_init(quic_pp_cipher *pp_cipher, int hash_algo,
return 0;
}
- if(!quic_hkdf_expand_label(hash_algo, secret, hash_len, key_label, write_key, key_length) ||
- !quic_hkdf_expand_label(hash_algo, secret, hash_len, iv_label, pp_cipher->pp_iv, sizeof(pp_cipher->pp_iv))) {
+ if(!quic_hkdf_expand_label(ndpi_struct, hash_algo, secret, hash_len, key_label, write_key, key_length) ||
+ !quic_hkdf_expand_label(ndpi_struct, hash_algo, secret, hash_len, iv_label, pp_cipher->pp_iv, sizeof(pp_cipher->pp_iv))) {
return 0;
}
@@ -594,7 +590,8 @@ static int quic_get_pn_cipher_algo(int cipher_algo, int *hp_cipher_mode)
* If the optional base secret is given, then its length MUST match the hash
* algorithm output.
*/
-static int quic_hp_cipher_prepare(quic_hp_cipher *hp_cipher, int hash_algo, int cipher_algo, uint8_t *secret, u_int32_t version)
+static int quic_hp_cipher_prepare(struct ndpi_detection_module_struct *ndpi_struct,
+ quic_hp_cipher *hp_cipher, int hash_algo, int cipher_algo, uint8_t *secret, u_int32_t version)
{
#if 0
/* Clear previous state (if any). */
@@ -603,34 +600,29 @@ static int quic_hp_cipher_prepare(quic_hp_cipher *hp_cipher, int hash_algo, int
int hp_cipher_mode;
if(!quic_get_pn_cipher_algo(cipher_algo, &hp_cipher_mode)) {
-#ifdef DEBUG_CRYPT
- printf("Unsupported cipher algorithm\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Unsupported cipher algorithm\n");
return 0;
}
if(gcry_cipher_open(&hp_cipher->hp_cipher, cipher_algo, hp_cipher_mode, 0)) {
quic_hp_cipher_reset(hp_cipher);
-#ifdef DEBUG_CRYPT
- printf("Failed to create HP cipher\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed to create HP cipher\n");
return 0;
}
if(secret) {
uint32_t cipher_keylen = (uint8_t)gcry_cipher_get_algo_keylen(cipher_algo);
- if(!quic_hp_cipher_init(hp_cipher, hash_algo, cipher_keylen, secret, version)) {
+ if(!quic_hp_cipher_init(ndpi_struct, hp_cipher, hash_algo, cipher_keylen, secret, version)) {
quic_hp_cipher_reset(hp_cipher);
-#ifdef DEBUG_CRYPT
- printf("Failed to derive key material for HP cipher\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed to derive key material for HP cipher\n");
return 0;
}
}
return 1;
}
-static int quic_pp_cipher_prepare(quic_pp_cipher *pp_cipher, int hash_algo, int cipher_algo, int cipher_mode, uint8_t *secret, u_int32_t version)
+static int quic_pp_cipher_prepare(struct ndpi_detection_module_struct *ndpi_struct,
+ quic_pp_cipher *pp_cipher, int hash_algo, int cipher_algo, int cipher_mode, uint8_t *secret, u_int32_t version)
{
#if 0
/* Clear previous state (if any). */
@@ -639,29 +631,26 @@ static int quic_pp_cipher_prepare(quic_pp_cipher *pp_cipher, int hash_algo, int
if(gcry_cipher_open(&pp_cipher->pp_cipher, cipher_algo, cipher_mode, 0)) {
quic_pp_cipher_reset(pp_cipher);
-#ifdef DEBUG_CRYPT
- printf("Failed to create PP cipher\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed to create PP cipher\n");
return 0;
}
if(secret) {
uint32_t cipher_keylen = (uint8_t)gcry_cipher_get_algo_keylen(cipher_algo);
- if(!quic_pp_cipher_init(pp_cipher, hash_algo, cipher_keylen, secret, version)) {
+ if(!quic_pp_cipher_init(ndpi_struct, pp_cipher, hash_algo, cipher_keylen, secret, version)) {
quic_pp_cipher_reset(pp_cipher);
-#ifdef DEBUG_CRYPT
- printf("Failed to derive key material for PP cipher\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed to derive key material for PP cipher\n");
return 0;
}
}
return 1;
}
-static int quic_ciphers_prepare(quic_ciphers *ciphers, int hash_algo, int cipher_algo, int cipher_mode, uint8_t *secret, u_int32_t version)
+static int quic_ciphers_prepare(struct ndpi_detection_module_struct *ndpi_struct,
+ quic_ciphers *ciphers, int hash_algo, int cipher_algo, int cipher_mode, uint8_t *secret, u_int32_t version)
{
- return quic_hp_cipher_prepare(&ciphers->hp_cipher, hash_algo, cipher_algo, secret, version) &&
- quic_pp_cipher_prepare(&ciphers->pp_cipher, hash_algo, cipher_algo, cipher_mode, secret, version);
+ return quic_hp_cipher_prepare(ndpi_struct, &ciphers->hp_cipher, hash_algo, cipher_algo, secret, version) &&
+ quic_pp_cipher_prepare(ndpi_struct, &ciphers->pp_cipher, hash_algo, cipher_algo, cipher_mode, secret, version);
}
/**
* Given a header protection cipher, a buffer and the packet number offset,
@@ -736,7 +725,8 @@ static int quic_decrypt_header(const uint8_t *packet_payload,
* The actual packet number must be constructed according to
* https://tools.ietf.org/html/draft-ietf-quic-transport-22#section-12.3
*/
-static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packet_payload, uint32_t packet_payload_len,
+static void quic_decrypt_message(struct ndpi_detection_module_struct *ndpi_struct,
+ quic_pp_cipher *pp_cipher, const uint8_t *packet_payload, uint32_t packet_payload_len,
uint32_t header_length, uint8_t first_byte, uint32_t pkn_len,
uint64_t packet_number, quic_decrypt_result_t *result)
{
@@ -746,7 +736,7 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packe
uint8_t *buffer;
uint8_t atag[16];
uint32_t buffer_length;
-#ifdef DEBUG_CRYPT
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
char buferr[128];
#endif
@@ -754,9 +744,7 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packe
!(pp_cipher->pp_cipher != NULL) ||
!(pkn_len < header_length) ||
!(1 <= pkn_len && pkn_len <= 4)) {
-#ifdef DEBUG_CRYPT
- printf("Failed sanity checks\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed sanity checks\n");
return;
}
/* Copy header, but replace encrypted first byte and PKN by plaintext. */
@@ -771,9 +759,7 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packe
/* Input is "header || ciphertext (buffer) || auth tag (16 bytes)" */
buffer_length = packet_payload_len - (header_length + 16);
if(buffer_length == 0) {
-#ifdef DEBUG_CRYPT
- printf("Decryption not possible, ciphertext is too short\n");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Decryption not possible, ciphertext is too short\n");
ndpi_free(header);
return;
}
@@ -791,9 +777,7 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packe
gcry_cipher_reset(pp_cipher->pp_cipher);
err = gcry_cipher_setiv(pp_cipher->pp_cipher, nonce, TLS13_AEAD_NONCE_LENGTH);
if(err) {
-#ifdef DEBUG_CRYPT
- printf("Decryption (setiv) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Decryption (setiv) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
ndpi_free(header);
ndpi_free(buffer);
return;
@@ -802,9 +786,7 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packe
/* associated data (A) is the contents of QUIC header */
err = gcry_cipher_authenticate(pp_cipher->pp_cipher, header, header_length);
if(err) {
-#ifdef DEBUG_CRYPT
- printf("Decryption (authenticate) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Decryption (authenticate) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
ndpi_free(header);
ndpi_free(buffer);
return;
@@ -815,18 +797,14 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packe
/* Output ciphertext (C) */
err = gcry_cipher_decrypt(pp_cipher->pp_cipher, buffer, buffer_length, NULL, 0);
if(err) {
-#ifdef DEBUG_CRYPT
- printf("Decryption (decrypt) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Decryption (decrypt) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
ndpi_free(buffer);
return;
}
err = gcry_cipher_checktag(pp_cipher->pp_cipher, atag, 16);
if(err) {
-#ifdef DEBUG_CRYPT
- printf("Decryption (checktag) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Decryption (checktag) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
ndpi_free(buffer);
return;
}
@@ -837,7 +815,8 @@ static void quic_decrypt_message(quic_pp_cipher *pp_cipher, const uint8_t *packe
/**
* Compute the client and server initial secrets given Connection ID "cid".
*/
-static int quic_derive_initial_secrets(uint32_t version,
+static int quic_derive_initial_secrets(struct ndpi_detection_module_struct *ndpi_struct,
+ uint32_t version,
const uint8_t *cid, uint8_t cid_len,
uint8_t client_initial_secret[HASH_SHA2_256_LENGTH])
{
@@ -885,7 +864,7 @@ static int quic_derive_initial_secrets(uint32_t version,
};
gcry_error_t err;
uint8_t secret[HASH_SHA2_256_LENGTH];
-#ifdef DEBUG_CRYPT
+#ifdef NDPI_ENABLE_DEBUG_MESSAGES
char buferr[128];
#endif
@@ -923,17 +902,13 @@ static int quic_derive_initial_secrets(uint32_t version,
cid, cid_len, secret);
}
if(err) {
-#ifdef DEBUG_CRYPT
- printf("Failed to extract secrets: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Failed to extract secrets: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
return -1;
}
- if(!quic_hkdf_expand_label(GCRY_MD_SHA256, secret, sizeof(secret), "client in",
+ if(!quic_hkdf_expand_label(ndpi_struct, GCRY_MD_SHA256, secret, sizeof(secret), "client in",
client_initial_secret, HASH_SHA2_256_LENGTH)) {
-#ifdef DEBUG_CRYPT
- printf("Key expansion (client) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Key expansion (client) failed: %s\n", __gcry_err(err, buferr, sizeof(buferr)));
return -1;
}
@@ -959,7 +934,7 @@ static uint8_t *decrypt_initial_packet(struct ndpi_detection_module_struct *ndpi
uint8_t client_secret[HASH_SHA2_256_LENGTH];
memset(&ciphers, '\0', sizeof(ciphers));
- if(quic_derive_initial_secrets(version, dest_conn_id, dest_conn_id_len,
+ if(quic_derive_initial_secrets(ndpi_struct, version, dest_conn_id, dest_conn_id_len,
client_secret) != 0) {
NDPI_LOG_DBG(ndpi_struct, "Error quic_derive_initial_secrets\n");
return NULL;
@@ -967,7 +942,7 @@ static uint8_t *decrypt_initial_packet(struct ndpi_detection_module_struct *ndpi
/* Packet numbers are protected with AES128-CTR,
Initial packets are protected with AEAD_AES_128_GCM. */
- if(!quic_ciphers_prepare(&ciphers, GCRY_MD_SHA256,
+ if(!quic_ciphers_prepare(ndpi_struct, &ciphers, GCRY_MD_SHA256,
GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_GCM,
client_secret, version)) {
NDPI_LOG_DBG(ndpi_struct, "Error quic_cipher_prepare\n");
@@ -1014,7 +989,8 @@ static uint8_t *decrypt_initial_packet(struct ndpi_detection_module_struct *ndpi
quic_ciphers_reset(&ciphers);
return NULL;
}
- quic_decrypt_message(&ciphers.pp_cipher, &packet->payload[0], pn_offset + payload_length,
+ quic_decrypt_message(ndpi_struct,
+ &ciphers.pp_cipher, &packet->payload[0], pn_offset + payload_length,
offset, first_byte, pkn_len, packet_number, &decryption);
quic_ciphers_reset(&ciphers);
@@ -1150,19 +1126,15 @@ static const uint8_t *get_crypto_data(struct ndpi_detection_module_struct *ndpi_
if(counter + 2 + offset_len + 2 /*gquic_get_u16 reads 2 bytes */ > clear_payload_len)
return NULL;
if(clear_payload[counter + 1] != 0x01) {
-#ifdef QUIC_DEBUG
- NDPI_LOG_ERR(ndpi_struct, "Unexpected stream ID version 0x%x\n", version);
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Unexpected stream ID version 0x%x\n", version);
return NULL;
}
counter += 2 + offset_len;
*crypto_data_len = gquic_get_u16(&clear_payload[counter], version);
counter += 2;
if(*crypto_data_len + counter > clear_payload_len) {
-#ifdef QUIC_DEBUG
- NDPI_LOG_ERR(ndpi_struct, "Invalid length %lu + %d > %d version 0x%x\n",
+ NDPI_LOG_DBG(ndpi_struct, "Invalid length %lu + %d > %d version 0x%x\n",
(unsigned long)*crypto_data_len, counter, clear_payload_len, version);
-#endif
return NULL;
}
crypto_data = &clear_payload[counter];
@@ -1187,10 +1159,8 @@ static const uint8_t *get_crypto_data(struct ndpi_detection_module_struct *ndpi_
counter += quic_len(&clear_payload[counter], &unused);
counter += quic_len(&clear_payload[counter], crypto_data_len);
if(*crypto_data_len + counter > clear_payload_len) {
-#ifdef QUIC_DEBUG
- NDPI_LOG_ERR(ndpi_struct, "Invalid length %lu + %d > %d version 0x%x\n",
+ NDPI_LOG_DBG(ndpi_struct, "Invalid length %lu + %d > %d version 0x%x\n",
(unsigned long)*crypto_data_len, counter, clear_payload_len, version);
-#endif
return NULL;
}
crypto_data = &clear_payload[counter];
@@ -1346,9 +1316,7 @@ static void process_chlo(struct ndpi_detection_module_struct *ndpi_struct,
if(crypto_data_len < 6)
return;
if(memcmp(crypto_data, "CHLO", 4) != 0) {
-#ifdef QUIC_DEBUG
- NDPI_LOG_ERR(ndpi_struct, "Unexpected handshake message");
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Unexpected handshake message");
return;
}
num_tags = le16toh(*(uint16_t *)&crypto_data[4]);
@@ -1457,16 +1425,12 @@ static int may_be_initial_pkt(struct ndpi_detection_module_struct *ndpi_struct,
if(is_gquic_ver_less_than(*version, 43) &&
(!pub_bit5 || pub_bit3 != 0 || pub_bit4 != 0)) {
-#ifdef QUIC_DEBUG
- NDPI_LOG_ERR(ndpi_struct, "Version 0x%x invalid flags 0x%x\n", *version, first_byte);
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Version 0x%x invalid flags 0x%x\n", *version, first_byte);
return 0;
}
if((*version == V_Q046) &&
(pub_bit7 != 1 || pub_bit8 != 1)) {
-#ifdef QUIC_DEBUG
- NDPI_LOG_ERR(ndpi_struct, "Q46 invalid flag 0x%x\n", first_byte);
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Q46 invalid flag 0x%x\n", first_byte);
return 0;
}
if((is_version_quic(*version) || (*version == V_Q046) || (*version == V_Q050)) &&
@@ -1630,9 +1594,7 @@ static void ndpi_search_quic(struct ndpi_detection_module_struct *ndpi_struct,
*/
if(!is_version_supported(version)) {
-#ifdef QUIC_DEBUG
- NDPI_LOG_ERR(ndpi_struct, "Unsupported version 0x%x\n", version);
-#endif
+ NDPI_LOG_DBG(ndpi_struct, "Unsupported version 0x%x\n", version);
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
return;
}