aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/ndpiReader.c165
-rw-r--r--example/reader_util.c10
-rw-r--r--example/reader_util.h4
-rw-r--r--python/ndpi.py352
-rw-r--r--src/include/ndpi_api.h.in40
-rw-r--r--src/include/ndpi_typedefs.h31
-rw-r--r--src/lib/ndpi_content_match.c.inc17
-rw-r--r--src/lib/ndpi_main.c179
-rw-r--r--src/lib/ndpi_serializer.c917
-rw-r--r--src/lib/ndpi_utils.c127
-rw-r--r--src/lib/protocols/bittorrent.c24
-rw-r--r--src/lib/protocols/http.c225
-rw-r--r--src/lib/protocols/kerberos.c46
-rw-r--r--src/lib/protocols/spotify.c2
-rw-r--r--src/lib/protocols/stun.c2
-rw-r--r--src/lib/protocols/tls.c185
-rw-r--r--tests/pcap/encrypted_sni.pcapbin0 -> 2382 bytes
-rw-r--r--tests/pcap/imaps.pcapbin0 -> 5540 bytes
-rw-r--r--tests/result/encrypted_sni.pcap.out10
-rw-r--r--tests/result/imaps.pcap.out8
-rw-r--r--tests/result/teams.pcap.out20
21 files changed, 1582 insertions, 782 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c
index 15f5d6f9a..eff6ca2c5 100644
--- a/example/ndpiReader.c
+++ b/example/ndpiReader.c
@@ -1244,6 +1244,11 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa
if(flow->ssh_tls.tls_issuerDN) fprintf(out, "[Issuer: %s]", flow->ssh_tls.tls_issuerDN);
if(flow->ssh_tls.tls_subjectDN) fprintf(out, "[Subject: %s]", flow->ssh_tls.tls_subjectDN);
+ if(flow->ssh_tls.encrypted_sni.esni) {
+ fprintf(out, "[ESNI: %s]", flow->ssh_tls.encrypted_sni.esni);
+ fprintf(out, "[ESNI Cipher: %s]", ndpi_cipher2str(flow->ssh_tls.encrypted_sni.cipher_suite));
+ }
+
if((flow->detected_protocol.master_protocol == NDPI_PROTOCOL_TLS)
|| (flow->detected_protocol.app_protocol == NDPI_PROTOCOL_TLS)) {
if(flow->ssh_tls.sha1_cert_fingerprint_set) {
@@ -3079,86 +3084,128 @@ void serializerUnitTest() {
ndpi_serializer serializer, deserializer;
int i;
u_int8_t trace = 0;
+ ndpi_serialization_format fmt = ndpi_serialization_format_tlv;
- assert(ndpi_init_serializer(&serializer, ndpi_serialization_format_tlv) != -1);
+ //trace = 1;
+ //fmt = ndpi_serialization_format_json;
+ //fmt = ndpi_serialization_format_csv;
+
+ assert(ndpi_init_serializer(&serializer, fmt) != -1);
for(i=0; i<16; i++) {
char kbuf[32], vbuf[32];
+ snprintf(kbuf, sizeof(kbuf), "Key %d", i);
+ snprintf(vbuf, sizeof(vbuf), "Value %d", i);
assert(ndpi_serialize_uint32_uint32(&serializer, i, i*i) != -1);
-
- snprintf(kbuf, sizeof(kbuf), "Hello %d", i);
- snprintf(vbuf, sizeof(vbuf), "World %d", i);
- assert(ndpi_serialize_uint32_string(&serializer, i, "Hello") != -1);
+ assert(ndpi_serialize_uint32_string(&serializer, i, "Data") != -1);
assert(ndpi_serialize_string_string(&serializer, kbuf, vbuf) != -1);
assert(ndpi_serialize_string_uint32(&serializer, kbuf, i*i) != -1);
assert(ndpi_serialize_string_float(&serializer, kbuf, (float)(i*i), "%f") != -1);
}
- if(trace)
- printf("Serialization size: %u\n", ndpi_serializer_get_buffer_len(&serializer));
+ if (fmt == ndpi_serialization_format_json) {
- assert(ndpi_init_deserializer(&deserializer, &serializer) != -1);
+ assert(ndpi_serialize_start_of_list(&serializer, "List") != -1);
- while(1) {
- ndpi_serialization_type kt, et;
- et = ndpi_deserialize_get_item_type(&deserializer, &kt);
+ for(i=0; i<4; i++) {
+ char kbuf[32], vbuf[32];
+ snprintf(kbuf, sizeof(kbuf), "Ignored");
+ snprintf(vbuf, sizeof(vbuf), "Item %d", i);
+ assert(ndpi_serialize_uint32_uint32(&serializer, i, i*i) != -1);
+ assert(ndpi_serialize_string_string(&serializer, kbuf, vbuf) != -1);
+ assert(ndpi_serialize_string_float(&serializer, kbuf, (float)(i*i), "%f") != -1);
+ }
+ assert(ndpi_serialize_end_of_list(&serializer) != -1);
+ assert(ndpi_serialize_string_string(&serializer, "Last", "Ok") != -1);
- if(et == ndpi_serialization_unknown)
- break;
- else {
- u_int32_t k32, v32;
- ndpi_string ks, vs;
- float vf;
-
- switch(kt) {
- case ndpi_serialization_uint32:
- ndpi_deserialize_key_uint32(&deserializer, &k32);
- if(trace) printf("%u=", k32);
+ if(trace) {
+ u_int32_t buffer_len = 0;
+ char *buffer = ndpi_serializer_get_buffer(&serializer, &buffer_len);
+ printf("%s\n", buffer);
+ exit(0);
+ }
+
+ } else if (fmt == ndpi_serialization_format_csv) {
+
+ if(trace) {
+ u_int32_t buffer_len = 0;
+ char *buffer;
+
+ buffer = ndpi_serializer_get_header(&serializer, &buffer_len);
+ printf("%s\n", buffer);
+
+ buffer = ndpi_serializer_get_buffer(&serializer, &buffer_len);
+ printf("%s\n", buffer);
+
+ exit(0);
+ }
+
+ } else {
+ if(trace)
+ printf("Serialization size: %u\n", ndpi_serializer_get_buffer_len(&serializer));
+
+ assert(ndpi_init_deserializer(&deserializer, &serializer) != -1);
+
+ while(1) {
+ ndpi_serialization_type kt, et;
+ et = ndpi_deserialize_get_item_type(&deserializer, &kt);
+
+ if(et == ndpi_serialization_unknown)
+ break;
+ else {
+ u_int32_t k32, v32;
+ ndpi_string ks, vs;
+ float vf;
+
+ switch(kt) {
+ case ndpi_serialization_uint32:
+ ndpi_deserialize_key_uint32(&deserializer, &k32);
+ if(trace) printf("%u=", k32);
break;
- case ndpi_serialization_string:
- ndpi_deserialize_key_string(&deserializer, &ks);
- if (trace) {
- u_int8_t bkp = ks.str[ks.str_len];
- ks.str[ks.str_len] = '\0';
- printf("%s=", ks.str);
- ks.str[ks.str_len] = bkp;
- }
+ case ndpi_serialization_string:
+ ndpi_deserialize_key_string(&deserializer, &ks);
+ if (trace) {
+ u_int8_t bkp = ks.str[ks.str_len];
+ ks.str[ks.str_len] = '\0';
+ printf("%s=", ks.str);
+ ks.str[ks.str_len] = bkp;
+ }
break;
- default:
- printf("Unsupported TLV key type %u\n", kt);
+ default:
+ printf("Unsupported TLV key type %u\n", kt);
return;
- }
-
- switch(et) {
- case ndpi_serialization_uint32:
- assert(ndpi_deserialize_value_uint32(&deserializer, &v32) != -1);
- if(trace) printf("%u\n", v32);
- break;
+ }
- case ndpi_serialization_string:
- assert(ndpi_deserialize_value_string(&deserializer, &vs) != -1);
- if(trace) {
- u_int8_t bkp = vs.str[vs.str_len];
- vs.str[vs.str_len] = '\0';
- printf("%s\n", vs.str);
- vs.str[vs.str_len] = bkp;
- }
- break;
+ switch(et) {
+ case ndpi_serialization_uint32:
+ assert(ndpi_deserialize_value_uint32(&deserializer, &v32) != -1);
+ if(trace) printf("%u\n", v32);
+ break;
+
+ case ndpi_serialization_string:
+ assert(ndpi_deserialize_value_string(&deserializer, &vs) != -1);
+ if(trace) {
+ u_int8_t bkp = vs.str[vs.str_len];
+ vs.str[vs.str_len] = '\0';
+ printf("%s\n", vs.str);
+ vs.str[vs.str_len] = bkp;
+ }
+ break;
- case ndpi_serialization_float:
- assert(ndpi_deserialize_value_float(&deserializer, &vf) != -1);
- if(trace) printf("%f\n", vf);
- break;
+ case ndpi_serialization_float:
+ assert(ndpi_deserialize_value_float(&deserializer, &vf) != -1);
+ if(trace) printf("%f\n", vf);
+ break;
- default:
- if (trace) printf("\n");
- printf("serializerUnitTest: unsupported type %u detected!\n", et);
- return;
- break;
+ default:
+ if (trace) printf("\n");
+ printf("serializerUnitTest: unsupported type %u detected!\n", et);
+ return;
+ }
}
- }
- ndpi_deserialize_next(&deserializer);
+ ndpi_deserialize_next(&deserializer);
+ }
}
ndpi_term_serializer(&serializer);
diff --git a/example/reader_util.c b/example/reader_util.c
index 56cd74134..833f200bf 100644
--- a/example/reader_util.c
+++ b/example/reader_util.c
@@ -489,6 +489,11 @@ void ndpi_free_flow_tls_data(struct ndpi_flow_info *flow) {
ndpi_free(flow->ssh_tls.tls_subjectDN);
flow->ssh_tls.tls_subjectDN = NULL;
}
+
+ if(flow->ssh_tls.encrypted_sni.esni) {
+ ndpi_free(flow->ssh_tls.encrypted_sni.esni);
+ flow->ssh_tls.encrypted_sni.esni = NULL;
+ }
}
/* ***************************************************** */
@@ -1121,6 +1126,11 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl
if(flow->ndpi_flow->protos.stun_ssl.ssl.subjectDN)
flow->ssh_tls.tls_subjectDN = strdup(flow->ndpi_flow->protos.stun_ssl.ssl.subjectDN);
+
+ if(flow->ndpi_flow->protos.stun_ssl.ssl.encrypted_sni.esni) {
+ flow->ssh_tls.encrypted_sni.esni = strdup(flow->ndpi_flow->protos.stun_ssl.ssl.encrypted_sni.esni);
+ flow->ssh_tls.encrypted_sni.cipher_suite = flow->ndpi_flow->protos.stun_ssl.ssl.encrypted_sni.cipher_suite;
+ }
if(flow->ssh_tls.tls_supported_versions) {
if((flow->ssh_tls.tls_supported_versions = ndpi_strdup(flow->ndpi_flow->protos.stun_ssl.ssl.tls_supported_versions)) != NULL)
diff --git a/example/reader_util.h b/example/reader_util.h
index 789729c33..f8302866f 100644
--- a/example/reader_util.h
+++ b/example/reader_util.h
@@ -204,6 +204,10 @@ typedef struct ndpi_flow_info {
ja3_client[33], ja3_server[33],
sha1_cert_fingerprint[20];
u_int8_t sha1_cert_fingerprint_set;
+ struct {
+ u_int16_t cipher_suite;
+ char *esni;
+ } encrypted_sni;
time_t notBefore, notAfter;
u_int16_t server_cipher;
ndpi_cipher_weakness client_unsafe_cipher, server_unsafe_cipher;
diff --git a/python/ndpi.py b/python/ndpi.py
index 722911207..1c4d6c59f 100644
--- a/python/ndpi.py
+++ b/python/ndpi.py
@@ -16,9 +16,12 @@ If not, see <http://www.gnu.org/licenses/>.
from os.path import abspath, dirname
import cffi
-import sys
cc_ndpi_network_headers = """
+struct ptr_uint32 {
+ uint32_t value;
+};
+
struct ndpi_chdlc
{
uint8_t addr; /* 0x0F (Unicast) - 0x8F (Broadcast) */
@@ -143,6 +146,11 @@ struct ndpi_mpls_header
uint32_t ttl:8, s:1, exp:3, label:20;
};
+extern union mpls {
+ uint32_t u32;
+ struct ndpi_mpls_header mpls;
+} mpls;
+
/* ++++++++++++++++++++++++ IP header ++++++++++++++++++++++++ */
struct ndpi_iphdr {
uint8_t ihl:4, version:4;
@@ -250,25 +258,25 @@ struct ndpi_vxlanhdr {
};
struct tinc_cache_entry {
- uint32_t src_address;
- uint32_t dst_address;
- uint16_t dst_port;
+ uint32_t src_address;
+ uint32_t dst_address;
+ uint16_t dst_port;
};
"""
cc_ndpi_stuctures = """
typedef enum {
- NDPI_LOG_ERROR,
- NDPI_LOG_TRACE,
- NDPI_LOG_DEBUG,
- NDPI_LOG_DEBUG_EXTRA
+ NDPI_LOG_ERROR,
+ NDPI_LOG_TRACE,
+ NDPI_LOG_DEBUG,
+ NDPI_LOG_DEBUG_EXTRA
} ndpi_log_level_t;
typedef enum {
- ndpi_l4_proto_unknown = 0,
- ndpi_l4_proto_tcp_only,
- ndpi_l4_proto_udp_only,
- ndpi_l4_proto_tcp_and_udp,
+ ndpi_l4_proto_unknown = 0,
+ ndpi_l4_proto_tcp_only,
+ ndpi_l4_proto_udp_only,
+ ndpi_l4_proto_tcp_and_udp,
} ndpi_l4_proto_info;
typedef enum {
@@ -280,18 +288,33 @@ typedef enum {
} ndpi_packet_tunnel;
typedef enum {
- ndpi_url_no_problem = 0,
- ndpi_url_possible_xss,
- ndpi_url_possible_sql_injection,
- ndpi_url_possible_rce_injection
-} ndpi_url_risk;
+ NDPI_NO_RISK = 0,
+ NDPI_URL_POSSIBLE_XSS,
+ NDPI_URL_POSSIBLE_SQL_INJECTION,
+ NDPI_URL_POSSIBLE_RCE_INJECTION,
+ NDPI_BINARY_APPLICATION_TRANSFER,
+ NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT,
+ NDPI_TLS_SELFSIGNED_CERTIFICATE,
+ NDPI_TLS_OBSOLETE_VERSION,
+ NDPI_TLS_WEAK_CIPHER,
+ NDPI_TLS_CERTIFICATE_EXPIRED,
+ NDPI_TLS_CERTIFICATE_MISMATCH,
+ NDPI_HTTP_SUSPICIOUS_USER_AGENT,
+ NDPI_HTTP_NUMERIC_IP_HOST,
+ NDPI_HTTP_SUSPICIOUS_URL,
+ NDPI_HTTP_SUSPICIOUS_HEADER,
+ /* Leave this as last member */
+ NDPI_MAX_RISK
+} ndpi_risk_enum;
+
+typedef uint32_t ndpi_risk;
/* NDPI_VISIT */
typedef enum {
- ndpi_preorder,
- ndpi_postorder,
- ndpi_endorder,
- ndpi_leaf
+ ndpi_preorder,
+ ndpi_postorder,
+ ndpi_endorder,
+ ndpi_leaf
} ndpi_VISIT;
/* NDPI_NODE */
@@ -353,16 +376,16 @@ struct bt_announce { // 192 bytes
#define TINC_CACHE_MAX_SIZE 10
typedef enum {
- NDPI_HTTP_METHOD_UNKNOWN = 0,
- NDPI_HTTP_METHOD_OPTIONS,
- NDPI_HTTP_METHOD_GET,
- NDPI_HTTP_METHOD_HEAD,
- NDPI_HTTP_METHOD_PATCH,
- NDPI_HTTP_METHOD_POST,
- NDPI_HTTP_METHOD_PUT,
- NDPI_HTTP_METHOD_DELETE,
- NDPI_HTTP_METHOD_TRACE,
- NDPI_HTTP_METHOD_CONNECT
+ NDPI_HTTP_METHOD_UNKNOWN = 0,
+ NDPI_HTTP_METHOD_OPTIONS,
+ NDPI_HTTP_METHOD_GET,
+ NDPI_HTTP_METHOD_HEAD,
+ NDPI_HTTP_METHOD_PATCH,
+ NDPI_HTTP_METHOD_POST,
+ NDPI_HTTP_METHOD_PUT,
+ NDPI_HTTP_METHOD_DELETE,
+ NDPI_HTTP_METHOD_TRACE,
+ NDPI_HTTP_METHOD_CONNECT
} ndpi_http_method;
struct ndpi_lru_cache_entry {
@@ -703,6 +726,7 @@ struct ndpi_packet_struct {
struct ndpi_int_one_line_struct forwarded_line;
struct ndpi_int_one_line_struct referer_line;
struct ndpi_int_one_line_struct content_line;
+ struct ndpi_int_one_line_struct content_disposition_line;
struct ndpi_int_one_line_struct accept_line;
struct ndpi_int_one_line_struct user_agent_line;
struct ndpi_int_one_line_struct http_url_name;
@@ -714,8 +738,7 @@ struct ndpi_packet_struct {
struct ndpi_int_one_line_struct http_x_session_type;
struct ndpi_int_one_line_struct server_line;
struct ndpi_int_one_line_struct http_method;
- struct ndpi_int_one_line_struct http_response; /* the first "word" in this pointer is the
- response code in the packet (200, etc) */
+ struct ndpi_int_one_line_struct http_response;
uint8_t http_num_headers; /* number of found (valid) header lines in HTTP request or response */
uint16_t l3_packet_len;
@@ -731,7 +754,7 @@ struct ndpi_packet_struct {
uint8_t tls_certificate_detected:4, tls_certificate_num_checks:4;
uint8_t packet_lines_parsed_complete:1,
- packet_direction:1, empty_line_position_set:1, pad:5;
+ packet_direction:1, empty_line_position_set:1, pad:5;
};
struct ndpi_detection_module_struct;
@@ -754,85 +777,87 @@ typedef struct {
} ndpi_port_range;
typedef enum {
- NDPI_PROTOCOL_SAFE = 0, /* Surely doesn't provide risks for the network. (e.g., a news site) */
- NDPI_PROTOCOL_ACCEPTABLE, /* Probably doesn't provide risks, but could be malicious (e.g., Dropbox) */
- NDPI_PROTOCOL_FUN, /* Pure fun protocol, which may be prohibited by the user policy (e.g., Netflix) */
- NDPI_PROTOCOL_UNSAFE, /* Probably provides risks, but could be a normal traffic. Unencrypted protocols with clear pass should be here (e.g., telnet) */
- NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, /* Possibly dangerous (ex. Tor). */
- NDPI_PROTOCOL_DANGEROUS, /* Surely is dangerous (ex. smbv1). Be prepared to troubles */
- NDPI_PROTOCOL_TRACKER_ADS, /* Trackers, Advertisements... */
- NDPI_PROTOCOL_UNRATED /* No idea, not implemented or impossible to classify */
+ NDPI_PROTOCOL_SAFE = 0, /* Surely doesn't provide risks for the network. (e.g., a news site) */
+ NDPI_PROTOCOL_ACCEPTABLE, /* Probably doesn't provide risks, but could be malicious (e.g., Dropbox) */
+ NDPI_PROTOCOL_FUN, /* Pure fun protocol, which may be prohibited by the user policy */
+ NDPI_PROTOCOL_UNSAFE, /* Probably provides risks, but could be a normal traffic. Unencrypted protocols
+ with clear pass should be here (e.g., telnet) */
+ NDPI_PROTOCOL_POTENTIALLY_DANGEROUS, /* Possibly dangerous (ex. Tor). */
+ NDPI_PROTOCOL_DANGEROUS, /* Surely is dangerous (ex. smbv1). Be prepared to troubles */
+ NDPI_PROTOCOL_TRACKER_ADS, /* Trackers, Advertisements... */
+ NDPI_PROTOCOL_UNRATED /* No idea, not implemented or impossible to classify */
} ndpi_protocol_breed_t;
#define NUM_BREEDS 8
/* Abstract categories to group the protocols. */
typedef enum {
- NDPI_PROTOCOL_CATEGORY_UNSPECIFIED = 0, /* For general services and unknown protocols */
- NDPI_PROTOCOL_CATEGORY_MEDIA, /* Multimedia and streaming */
- NDPI_PROTOCOL_CATEGORY_VPN, /* Virtual Private Networks */
- NDPI_PROTOCOL_CATEGORY_MAIL, /* Protocols to send/receive/sync emails */
- NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER, /* AFS/NFS and similar protocols */
- NDPI_PROTOCOL_CATEGORY_WEB, /* Web/mobile protocols and services */
- NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, /* Social networks */
- NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT, /* Download, FTP, file transfer/sharing */
- NDPI_PROTOCOL_CATEGORY_GAME, /* Online games */
- NDPI_PROTOCOL_CATEGORY_CHAT, /* Instant messaging */
- NDPI_PROTOCOL_CATEGORY_VOIP, /* Real-time communications and conferencing */
- NDPI_PROTOCOL_CATEGORY_DATABASE, /* Protocols for database communication */
- NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS, /* Remote access and control */
- NDPI_PROTOCOL_CATEGORY_CLOUD, /* Online cloud services */
- NDPI_PROTOCOL_CATEGORY_NETWORK, /* Network infrastructure protocols */
- NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, /* Software for collaborative development, including Webmail */
- NDPI_PROTOCOL_CATEGORY_RPC, /* High level network communication protocols */
- NDPI_PROTOCOL_CATEGORY_STREAMING, /* Streaming protocols */
- NDPI_PROTOCOL_CATEGORY_SYSTEM_OS, /* System/Operating System level applications */
- NDPI_PROTOCOL_CATEGORY_SW_UPDATE, /* Software update */
-
- /* See #define NUM_CUSTOM_CATEGORIES */
- NDPI_PROTOCOL_CATEGORY_CUSTOM_1, /* User custom category 1 */
- NDPI_PROTOCOL_CATEGORY_CUSTOM_2, /* User custom category 2 */
- NDPI_PROTOCOL_CATEGORY_CUSTOM_3, /* User custom category 3 */
- NDPI_PROTOCOL_CATEGORY_CUSTOM_4, /* User custom category 4 */
- NDPI_PROTOCOL_CATEGORY_CUSTOM_5, /* User custom category 5 */
-
- /* Further categories... */
- NDPI_PROTOCOL_CATEGORY_MUSIC,
- NDPI_PROTOCOL_CATEGORY_VIDEO,
- NDPI_PROTOCOL_CATEGORY_SHOPPING,
- NDPI_PROTOCOL_CATEGORY_PRODUCTIVITY,
- NDPI_PROTOCOL_CATEGORY_FILE_SHARING,
-
- /* Some custom categories */
- CUSTOM_CATEGORY_MINING = 99,
- CUSTOM_CATEGORY_MALWARE = 100,
- CUSTOM_CATEGORY_ADVERTISEMENT = 101,
- CUSTOM_CATEGORY_BANNED_SITE = 102,
- CUSTOM_CATEGORY_SITE_UNAVAILABLE = 103,
- CUSTOM_CATEGORY_ALLOWED_SITE = 104,
- /*
- The category below is used to track communications made by
- security applications (e.g. sophosxl.net, spamhaus.org)
- to track malware, spam etc.
- */
- CUSTOM_CATEGORY_ANTIMALWARE = 105,
-
- /*
- IMPORTANT
- Please keep in sync with
- static const char* categories[] = { ..}
- in ndpi_main.c
- */
-
- NDPI_PROTOCOL_NUM_CATEGORIES /*
- NOTE: Keep this as last member
- Unused as value but useful to getting the number of elements
- in this datastructure
- */
+ NDPI_PROTOCOL_CATEGORY_UNSPECIFIED = 0, /* For general services and unknown protocols */
+ NDPI_PROTOCOL_CATEGORY_MEDIA, /* Multimedia and streaming */
+ NDPI_PROTOCOL_CATEGORY_VPN, /* Virtual Private Networks */
+ NDPI_PROTOCOL_CATEGORY_MAIL, /* Protocols to send/receive/sync emails */
+ NDPI_PROTOCOL_CATEGORY_DATA_TRANSFER, /* AFS/NFS and similar protocols */
+ NDPI_PROTOCOL_CATEGORY_WEB, /* Web/mobile protocols and services */
+ NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, /* Social networks */
+ NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT, /* Download, FTP, file transfer/sharing */
+ NDPI_PROTOCOL_CATEGORY_GAME, /* Online games */
+ NDPI_PROTOCOL_CATEGORY_CHAT, /* Instant messaging */
+ NDPI_PROTOCOL_CATEGORY_VOIP, /* Real-time communications and conferencing */
+ NDPI_PROTOCOL_CATEGORY_DATABASE, /* Protocols for database communication */
+ NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS, /* Remote access and control */
+ NDPI_PROTOCOL_CATEGORY_CLOUD, /* Online cloud services */
+ NDPI_PROTOCOL_CATEGORY_NETWORK, /* Network infrastructure protocols */
+ NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, /* Software for collaborative development, including Webmail */
+ NDPI_PROTOCOL_CATEGORY_RPC, /* High level network communication protocols */
+ NDPI_PROTOCOL_CATEGORY_STREAMING, /* Streaming protocols */
+ NDPI_PROTOCOL_CATEGORY_SYSTEM_OS, /* System/Operating System level applications */
+ NDPI_PROTOCOL_CATEGORY_SW_UPDATE, /* Software update */
+
+ /* See #define NUM_CUSTOM_CATEGORIES */
+ NDPI_PROTOCOL_CATEGORY_CUSTOM_1, /* User custom category 1 */
+ NDPI_PROTOCOL_CATEGORY_CUSTOM_2, /* User custom category 2 */
+ NDPI_PROTOCOL_CATEGORY_CUSTOM_3, /* User custom category 3 */
+ NDPI_PROTOCOL_CATEGORY_CUSTOM_4, /* User custom category 4 */
+ NDPI_PROTOCOL_CATEGORY_CUSTOM_5, /* User custom category 5 */
+
+ /* Further categories... */
+ NDPI_PROTOCOL_CATEGORY_MUSIC,
+ NDPI_PROTOCOL_CATEGORY_VIDEO,
+ NDPI_PROTOCOL_CATEGORY_SHOPPING,
+ NDPI_PROTOCOL_CATEGORY_PRODUCTIVITY,
+ NDPI_PROTOCOL_CATEGORY_FILE_SHARING,
+
+ /* Some custom categories */
+ CUSTOM_CATEGORY_MINING = 99,
+ CUSTOM_CATEGORY_MALWARE = 100,
+ CUSTOM_CATEGORY_ADVERTISEMENT = 101,
+ CUSTOM_CATEGORY_BANNED_SITE = 102,
+ CUSTOM_CATEGORY_SITE_UNAVAILABLE = 103,
+ CUSTOM_CATEGORY_ALLOWED_SITE = 104,
+ /*
+ The category below is used to track communications made by
+ security applications (e.g. sophosxl.net, spamhaus.org)
+ to track malware, spam etc.
+ */
+ CUSTOM_CATEGORY_ANTIMALWARE = 105,
+
+ /*
+ IMPORTANT
+ Please keep in sync with
+ static const char* categories[] = { ..}
+ in ndpi_main.c
+ */
+
+ NDPI_PROTOCOL_NUM_CATEGORIES
+ /*
+ NOTE: Keep this as last member
+ Unused as value but useful to getting the number of elements
+ in this datastructure
+ */
} ndpi_protocol_category_t;
typedef enum {
- ndpi_pref_direction_detect_disable = 0,
+ ndpi_pref_direction_detect_disable = 0,
} ndpi_detection_preference;
/* ntop extensions */
@@ -842,6 +867,7 @@ typedef struct ndpi_proto_defaults {
uint8_t can_have_a_subprotocol;
uint16_t protoId, protoIdx;
uint16_t master_tcp_protoId[2], master_udp_protoId[2]; /* The main protocols on which this sub-protocol sits on */
+ uint16_t tcp_default_ports[5], udp_default_ports[5];
ndpi_protocol_breed_t protoBreed;
void (*func) (struct ndpi_detection_module_struct *, struct ndpi_flow_struct *flow);
} ndpi_proto_defaults_t;
@@ -965,12 +991,13 @@ struct ndpi_detection_module_struct {
/* NDPI_PROTOCOL_STUN and subprotocols */
struct ndpi_lru_cache *stun_cache;
+ /* NDPI_PROTOCOL_MSTEAMS */
+ struct ndpi_lru_cache *msteams_cache;
+
ndpi_proto_defaults_t proto_defaults[512];
uint8_t direction_detect_disable:1, /* disable internal detection of packet direction */
_pad:7;
-
- void *hyperscan; /* Intel Hyperscan */
};
#define NDPI_CIPHER_SAFE 0
@@ -978,9 +1005,9 @@ struct ndpi_detection_module_struct {
#define NDPI_CIPHER_INSECURE 2
typedef enum {
- ndpi_cipher_safe = NDPI_CIPHER_SAFE,
- ndpi_cipher_weak = NDPI_CIPHER_WEAK,
- ndpi_cipher_insecure = NDPI_CIPHER_INSECURE
+ ndpi_cipher_safe = NDPI_CIPHER_SAFE,
+ ndpi_cipher_weak = NDPI_CIPHER_WEAK,
+ ndpi_cipher_insecure = NDPI_CIPHER_INSECURE
} ndpi_cipher_weakness;
struct ndpi_flow_struct {
@@ -1019,6 +1046,9 @@ struct ndpi_flow_struct {
struct ndpi_id_struct *server_id;
/* HTTP host or DNS query */
uint8_t host_server_name[240];
+ uint8_t initial_binary_bytes[8], initial_binary_bytes_len;
+ uint8_t risk_checked;
+ uint32_t risk; /* Issues found with this flow [bitmask of ndpi_risk] */
/*
This structure below will not stay inside the protos
@@ -1064,8 +1094,8 @@ struct ndpi_flow_struct {
struct {
struct {
uint16_t ssl_version, server_names_len;
- char client_requested_server_name[64], *server_names, server_organization[64],
- *alpn, *tls_supported_versions;
+ char client_requested_server_name[64], *server_names,
+ *alpn, *tls_supported_versions, *issuerDN, *subjectDN;
uint32_t notBefore, notAfter;
char ja3_client[33], ja3_server[33];
uint16_t server_cipher;
@@ -1208,10 +1238,6 @@ struct ndpi_flow_struct {
/* NDPI_PROTOCOL_CSGO */
uint8_t csgo_strid[18],csgo_state,csgo_s2;
uint32_t csgo_id2;
-
- /* NDPI_PROTOCOL_1KXUN || NDPI_PROTOCOL_IQIYI */
- uint16_t kxun_counter, iqiyi_counter;
-
/* internal structures to save functions calls */
struct ndpi_packet_struct packet;
struct ndpi_flow_struct *flow;
@@ -1220,14 +1246,14 @@ struct ndpi_flow_struct {
};
typedef struct {
- char *string_to_match, *string2_to_match, *pattern_to_match, *proto_name;
+ char *string_to_match, *proto_name;
int protocol_id;
ndpi_protocol_category_t protocol_category;
ndpi_protocol_breed_t protocol_breed;
} ndpi_protocol_match;
typedef struct {
- char *string_to_match, *hyperscan_string_to_match;
+ char *string_to_match;
ndpi_protocol_category_t protocol_category;
} ndpi_category_match;
@@ -1239,11 +1265,10 @@ typedef struct {
typedef uint32_t ndpi_init_prefs;
-typedef enum
- {
- ndpi_no_prefs = 0,
- ndpi_dont_load_tor_hosts,
- } ndpi_prefs;
+typedef enum {
+ ndpi_no_prefs = 0,
+ ndpi_dont_load_tor_hosts,
+} ndpi_prefs;
typedef struct {
int protocol_id;
@@ -1272,8 +1297,6 @@ struct ndpi_analyze_struct {
#define MAX_SERIES_LEN 512
#define MIN_SERIES_LEN 8
-/* **************************************** */
-
typedef struct ndpi_ptree ndpi_ptree_t;
"""
@@ -1300,23 +1323,44 @@ void ndpi_free(void *ptr);
void * ndpi_flow_malloc(size_t size);
void ndpi_flow_free(void *ptr);
void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_struct);
-char* ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol proto, char *buf, unsigned buf_len);
+char* ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_mod,
+ ndpi_protocol proto,
+ char *buf, unsigned buf_len);
const char* ndpi_category_get_name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol_category_t category);
char* ndpi_revision(void);
void ndpi_finalize_initalization(struct ndpi_detection_module_struct *ndpi_str);
uint32_t ndpi_detection_get_sizeof_ndpi_flow_struct(void);
uint32_t ndpi_detection_get_sizeof_ndpi_id_struct(void);
+uint32_t ndpi_detection_get_sizeof_ndpi_flow_tcp_struct(void);
+uint32_t ndpi_detection_get_sizeof_ndpi_flow_udp_struct(void);
+uint8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow);
"""
+def check_structures_size(flow_struct_defined, flow_struct_loaded,
+ id_struct_defined, id_struct_loaded,
+ tcp_flow_struct_defined, tcp_flow_struct_loaded,
+ udp_flow_struct_defined, udp_flow_struct_loaded):
+ """ Function used to check loaded structures sizes againt defined ones """
+ errors = []
+ if flow_struct_defined != flow_struct_loaded:
+ errors.append('ndpi_flow_struct')
+ if id_struct_defined != id_struct_loaded:
+ errors.append('ndpi_id_struct')
+ if tcp_flow_struct_defined != tcp_flow_struct_loaded:
+ errors.append('ndpi_tcp_flow_struct')
+ if udp_flow_struct_defined != udp_flow_struct_loaded:
+ errors.append('ndpi_udp_flow_struct')
+ return errors
+
+
class NDPI():
- def __init__(self, libpath=None, max_tcp_dissections=10, max_udp_dissections=16):
+ """ ndpi module main class """
+
+ def __init__(self, libpath=None, max_tcp_dissections=80, max_udp_dissections=16, enable_guess=True):
self._ffi = cffi.FFI()
if libpath is None:
- if "win" in sys.platform[:3]:
- self._ndpi = self._ffi.dlopen(dirname(abspath(__file__)) + '/libs/libndpi.a')
- else:
- self._ndpi = self._ffi.dlopen(dirname(abspath(__file__)) + '/libs/libndpi.so')
+ self._ndpi = self._ffi.dlopen(dirname(abspath(__file__)) + '/libndpi.so')
else:
self._ndpi = self._ffi.dlopen(libpath)
self._ffi.cdef(cc_ndpi_network_headers, packed=True)
@@ -1329,47 +1373,81 @@ class NDPI():
all = self._ffi.new('NDPI_PROTOCOL_BITMASK*')
self._ndpi.memset(self._ffi.cast("char *", all), 0xFF, self._ffi.sizeof("NDPI_PROTOCOL_BITMASK"))
self._ndpi.ndpi_set_protocol_detection_bitmask2(self._mod, all)
- self.SIZEOF_FLOW_STRUCT = self._ffi.sizeof("struct ndpi_flow_struct")
- self.SIZEOF_ID_STRUCT = self._ffi.sizeof("struct ndpi_id_struct")
+ errors = check_structures_size(self._ffi.sizeof("struct ndpi_flow_struct"),
+ self._ndpi.ndpi_detection_get_sizeof_ndpi_flow_struct(),
+ self._ffi.sizeof("struct ndpi_id_struct"),
+ self._ndpi.ndpi_detection_get_sizeof_ndpi_id_struct(),
+ self._ffi.sizeof("struct ndpi_flow_tcp_struct"),
+ self._ndpi.ndpi_detection_get_sizeof_ndpi_flow_tcp_struct(),
+ self._ffi.sizeof("struct ndpi_flow_udp_struct"),
+ self._ndpi.ndpi_detection_get_sizeof_ndpi_flow_udp_struct())
+ if len(errors) != 0:
+ raise ValueError('nDPI error: mismatch in the headers of following structures{}'.format(', '.join(errors)))
+ else:
+ self.SIZEOF_FLOW_STRUCT = self._ffi.sizeof("struct ndpi_flow_struct")
+ self.SIZEOF_ID_STRUCT = self._ffi.sizeof("struct ndpi_id_struct")
self.NULL = self._ffi.NULL
self.max_tcp_dissections = max_tcp_dissections
self.max_udp_dissections = max_udp_dissections
+ self.enable_guess = enable_guess
def new_ndpi_flow(self):
+ """ Create a new nDPI flow object """
f = self._ffi.cast('struct ndpi_flow_struct*', self._ndpi.ndpi_flow_malloc(self.SIZEOF_FLOW_STRUCT))
self._ndpi.memset(f, 0, self.SIZEOF_FLOW_STRUCT)
return f
def new_ndpi_id(self):
+ """ Create a new nDPI id object """
i = self._ffi.cast('struct ndpi_id_struct*', self._ndpi.ndpi_malloc(self.SIZEOF_ID_STRUCT))
self._ndpi.memset(i, 0, self.SIZEOF_ID_STRUCT)
return i
def ndpi_detection_process_packet(self, flow, packet, packetlen, current_tick, src, dst):
- return self._ndpi.ndpi_detection_process_packet(self._mod, flow, packet, packetlen, current_tick, src, dst)
+ """ Main detection processing function """
+ p = self._ndpi.ndpi_detection_process_packet(self._mod, flow, packet, packetlen, current_tick, src, dst)
+ return p
def ndpi_detection_giveup(self, flow):
- return self._ndpi.ndpi_detection_giveup(self._mod, flow, 1, self._ffi.new("uint8_t*", 0))
+ """ Giveup detection function """
+ return self._ndpi.ndpi_detection_giveup(self._mod, flow, self.enable_guess, self._ffi.new("uint8_t*", 0))
def ndpi_flow_free(self, flow):
+ """ Free nDPI flow object """
return self._ndpi.ndpi_flow_free(flow)
def ndpi_free(self, ptr):
+ """ Free nDPI object """
return self._ndpi.ndpi_free(ptr)
def get_str_field(self, ptr):
- return self._ffi.string(ptr).decode('utf-8', errors='ignore')
+ """ Get fixed string size attribute """
+ if ptr == self._ffi.NULL:
+ return ''
+ else:
+ return self._ffi.string(ptr).decode('utf-8', errors='ignore')
- def get_buffer_field(self, ptr, l):
- return bytes(self._ffi.buffer(ptr, l)).decode('utf-8', errors='ignore')
+ def get_buffer_field(self, ptr, li):
+ """ Get variable string size attribute """
+ if ptr == self._ffi.NULL:
+ return ''
+ else:
+ return self._ffi.string(ptr, li).decode('utf-8', errors='ignore')
def ndpi_protocol2name(self, proto):
+ """ Convert nDPI protocol object to readable name """
buf = self._ffi.new("char[32]")
self._ndpi.ndpi_protocol2name(self._mod, proto, buf, self._ffi.sizeof(buf))
return self._ffi.string(buf).decode('utf-8', errors='ignore')
def ndpi_category_get_name(self, category):
+ """ Convert nDPI protocol object to readable name """
return self._ffi.string(self._ndpi.ndpi_category_get_name(self._mod, category)).decode('utf-8', errors='ignore')
+ def ndpi_extra_dissection_possible(self, flow):
+ return self._ndpi.ndpi_extra_dissection_possible(self._mod, flow)
+
def ndpi_exit_detection_module(self):
+ """ Exit function for nDPI module """
self._ndpi.ndpi_exit_detection_module(self._mod)
+ self._ffi.dlclose(self._ndpi)
diff --git a/src/include/ndpi_api.h.in b/src/include/ndpi_api.h.in
index 6495c6825..5f8604f8e 100644
--- a/src/include/ndpi_api.h.in
+++ b/src/include/ndpi_api.h.in
@@ -137,7 +137,7 @@ extern "C" {
* NULL if the substring is not found
*
*/
- char* ndpi_strncasestr(const char *s, const char *find, size_t slen);
+ const char* ndpi_strncasestr(const char *s, const char *find, size_t slen);
/**
* Returns the nDPI protocol id for IP-based protocol detection
@@ -191,7 +191,7 @@ extern "C" {
/**
* Completes the initialization (2nd step)
*
- * @return the initialized detection module
+ * @par ndpi_str = the struct created for the protocol detection
*
*/
void ndpi_finalize_initalization(struct ndpi_detection_module_struct *ndpi_str);
@@ -258,7 +258,7 @@ extern "C" {
*/
void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct,
const NDPI_PROTOCOL_BITMASK * detection_bitmask);
-
+
/**
* Function to be called before we give up with detection for a given flow.
* This function reduces the NDPI_UNKNOWN_PROTOCOL detection
@@ -330,7 +330,7 @@ extern "C" {
*/
u_int16_t ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow);
-
+
/**
* API call that is called internally by ndpi_detection_process_packet or by apps
* that want to avoid calling ndpi_detection_process_packet as they have already
@@ -431,7 +431,7 @@ extern "C" {
char *string_to_match,
u_int string_to_match_len,
ndpi_protocol_match_result *ret_match,
- u_int16_t master_protocol_id);
+ u_int16_t master_protocol_id);
/**
* Check if the string content passed match with a protocol
@@ -558,7 +558,7 @@ extern "C" {
*/
int ndpi_match_hostname_protocol(struct ndpi_detection_module_struct *ndpi_mod,
struct ndpi_flow_struct *flow,
- u_int16_t master_protocol,
+ u_int16_t master_protocol,
char *name, u_int name_len);
/**
@@ -838,7 +838,7 @@ extern "C" {
/* Tells to called on what l4 protocol given application protocol can be found */
ndpi_l4_proto_info ndpi_get_l4_proto_info(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t ndpi_proto_id);
const char* ndpi_get_l4_proto_name(ndpi_l4_proto_info proto);
-
+
ndpi_proto_defaults_t* ndpi_get_proto_defaults(struct ndpi_detection_module_struct *ndpi_mod);
u_int ndpi_get_ndpi_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_mod);
u_int ndpi_get_ndpi_num_custom_protocols(struct ndpi_detection_module_struct *ndpi_mod);
@@ -851,7 +851,7 @@ extern "C" {
u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key,
u_int16_t *value, u_int8_t clean_key_when_found);
void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t value);
-
+
/**
* Find a protocol id associated with a string automata
*
@@ -886,7 +886,7 @@ extern "C" {
u_int16_t src_port, u_int16_t dst_port, u_int8_t icmp_type, u_int8_t icmp_code,
u_char *hash_buf, u_int8_t hash_buf_len);
u_int8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow);
+ struct ndpi_flow_struct *flow);
u_int8_t ndpi_is_safe_ssl_cipher(u_int32_t cipher);
const char* ndpi_cipher2str(u_int32_t cipher);
const char* ndpi_tunnel2str(ndpi_packet_tunnel tt);
@@ -904,7 +904,10 @@ extern "C" {
char* ndpi_base64_encode(unsigned char const* bytes_to_encode, size_t in_len);
int ndpi_load_ipv4_ptree(struct ndpi_detection_module_struct *ndpi_str,
const char *path, u_int16_t protocol_id);
-
+ int ndpi_dpi2json(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol l7_protocol,
+ ndpi_serializer *serializer);
int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
u_int8_t ip_version,
@@ -949,7 +952,7 @@ extern "C" {
int ndpi_serialize_string_int32(ndpi_serializer *serializer,
const char *key, int32_t value);
int ndpi_serialize_string_int64(ndpi_serializer *serializer,
- const char *key, int64_t value);
+ const char *key, int64_t value);
int ndpi_serialize_string_uint32(ndpi_serializer *serializer,
const char *key, u_int32_t value);
int ndpi_serialize_string_uint32_format(ndpi_serializer *serializer,
@@ -973,6 +976,9 @@ extern "C" {
int ndpi_serialize_raw_record(ndpi_serializer *_serializer,
u_char *record, u_int32_t record_len);
int ndpi_serialize_end_of_record(ndpi_serializer *serializer);
+ int ndpi_serialize_start_of_list(ndpi_serializer *serializer,
+ const char *key);
+ int ndpi_serialize_end_of_list(ndpi_serializer *serializer);
int ndpi_serialize_start_of_block(ndpi_serializer *serializer,
const char *key);
int ndpi_serialize_end_of_block(ndpi_serializer *serializer);
@@ -981,17 +987,18 @@ extern "C" {
u_int32_t ndpi_serializer_get_internal_buffer_size(ndpi_serializer *serializer);
int ndpi_serializer_set_buffer_len(ndpi_serializer *serializer, u_int32_t l);
void ndpi_serializer_set_csv_separator(ndpi_serializer *serializer, char separator);
+ char* ndpi_serializer_get_header(ndpi_serializer *serializer, u_int32_t *buffer_len);
void ndpi_serializer_create_snapshot(ndpi_serializer *serializer);
void ndpi_serializer_rollback_snapshot(ndpi_serializer *serializer);
-
+
/* Deserializer */
int ndpi_init_deserializer(ndpi_deserializer *deserializer,
ndpi_serializer *serializer);
int ndpi_init_deserializer_buf(ndpi_deserializer *deserializer,
u_int8_t *serialized_buffer,
u_int32_t serialized_buffer_len);
-
+
ndpi_serialization_format ndpi_deserialize_get_format(ndpi_deserializer *_deserializer);
ndpi_serialization_type ndpi_deserialize_get_item_type(ndpi_deserializer *deserializer, ndpi_serialization_type *key_type);
int ndpi_deserialize_next(ndpi_deserializer *deserializer);
@@ -1017,22 +1024,23 @@ extern "C" {
float ndpi_data_average(struct ndpi_analyze_struct *s);
float ndpi_data_window_average(struct ndpi_analyze_struct *s);
-
+
float ndpi_data_entropy(struct ndpi_analyze_struct *s);
float ndpi_data_variance(struct ndpi_analyze_struct *s);
float ndpi_data_stddev(struct ndpi_analyze_struct *s);
u_int32_t ndpi_data_min(struct ndpi_analyze_struct *s);
u_int32_t ndpi_data_max(struct ndpi_analyze_struct *s);
float ndpi_data_ratio(u_int32_t sent, u_int32_t rcvd);
-
+
const char* ndpi_data_ratio2str(float ratio);
-
+
void ndpi_data_print_window_values(struct ndpi_analyze_struct *s); /* debug */
ndpi_risk_enum ndpi_validate_url(char *url);
u_int8_t ndpi_is_protocol_detected(struct ndpi_detection_module_struct *ndpi_str,
ndpi_protocol proto);
+ void ndpi_serialize_risk(ndpi_serializer *serializer, struct ndpi_flow_struct *flow);
const char* ndpi_risk2str(ndpi_risk_enum risk);
#ifdef __cplusplus
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index bdcfebbe2..dc1aa208e 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -65,6 +65,7 @@ typedef enum {
NDPI_HTTP_SUSPICIOUS_USER_AGENT,
NDPI_HTTP_NUMERIC_IP_HOST,
NDPI_HTTP_SUSPICIOUS_URL,
+ NDPI_HTTP_SUSPICIOUS_HEADER,
/* Leave this as last member */
NDPI_MAX_RISK
@@ -1111,6 +1112,9 @@ struct ndpi_detection_module_struct {
/* NDPI_PROTOCOL_STUN and subprotocols */
struct ndpi_lru_cache *stun_cache;
+ /* NDPI_PROTOCOL_MSTEAMS */
+ struct ndpi_lru_cache *msteams_cache;
+
ndpi_proto_defaults_t proto_defaults[NDPI_MAX_SUPPORTED_PROTOCOLS+NDPI_MAX_NUM_CUSTOM_PROTOCOLS];
u_int8_t direction_detect_disable:1, /* disable internal detection of packet direction */
@@ -1223,6 +1227,11 @@ struct ndpi_flow_struct {
u_int32_t notBefore, notAfter;
char ja3_client[33], ja3_server[33];
u_int16_t server_cipher;
+
+ struct {
+ u_int16_t cipher_suite;
+ char *esni;
+ } encrypted_sni;
ndpi_cipher_weakness server_unsafe_cipher;
} ssl;
@@ -1426,6 +1435,7 @@ typedef enum {
ndpi_serialization_string
} ndpi_serialization_type;
+#define NDPI_SERIALIZER_DEFAULT_HEADER_SIZE 1024
#define NDPI_SERIALIZER_DEFAULT_BUFFER_SIZE 8192
#define NDPI_SERIALIZER_DEFAULT_BUFFER_INCR 1024
@@ -1434,18 +1444,31 @@ typedef enum {
#define NDPI_SERIALIZER_STATUS_EOR (1 << 2)
#define NDPI_SERIALIZER_STATUS_SOB (1 << 3)
#define NDPI_SERIALIZER_STATUS_NOT_EMPTY (1 << 4)
+#define NDPI_SERIALIZER_STATUS_LIST (1 << 5)
+#define NDPI_SERIALIZER_STATUS_SOL (1 << 6)
+#define NDPI_SERIALIZER_STATUS_HDR_DONE (1 << 7)
typedef struct {
- u_int32_t flags;
u_int32_t size_used;
+} ndpi_private_serializer_buffer_status;
+
+typedef struct {
+ u_int32_t flags;
+ ndpi_private_serializer_buffer_status buffer;
+ ndpi_private_serializer_buffer_status header;
} ndpi_private_serializer_status;
typedef struct {
+ u_int32_t initial_size;
+ u_int32_t size;
+ u_int8_t *data;
+} ndpi_private_serializer_buffer;
+
+typedef struct {
ndpi_private_serializer_status status;
- u_int32_t initial_buffer_size;
- u_int32_t buffer_size;
+ ndpi_private_serializer_buffer buffer;
+ ndpi_private_serializer_buffer header;
ndpi_serialization_format fmt;
- u_int8_t *buffer;
char csv_separator[2];
u_int8_t has_snapshot;
ndpi_private_serializer_status snapshot;
diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc
index 4b6daa50b..32a6e840c 100644
--- a/src/lib/ndpi_content_match.c.inc
+++ b/src/lib/ndpi_content_match.c.inc
@@ -8390,8 +8390,11 @@ static ndpi_network host_protocol_list[] = {
{ 0xD0163900 /* 208.22.57.0/24 */, 24, NDPI_PROTOCOL_BLOOMBERG },
{ 0x45BFC000 /* 69.191.192.0/18 */, 18, NDPI_PROTOCOL_BLOOMBERG },
- /* Microsoft
- https://docs.microsoft.com/en-us/office365/enterprise/urls-and-ip-address-ranges
+ /*
+ Microsoft
+
+ [JSON] https://endpoints.office.com/endpoints/worldwide?clientrequestid=b10c5ed1-bad1-445f-b386-b919946339a7
+ [HTML] https://docs.microsoft.com/en-us/office365/enterprise/urls-and-ip-address-ranges
*/
{ 0x0D6B0698 /* 13.107.6.152/31 */, 31, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x0D6B120A /* 13.107.18.10/31 */, 31, NDPI_PROTOCOL_MICROSOFT_365 },
@@ -8411,7 +8414,6 @@ static ndpi_network host_protocol_list[] = {
{ 0x1767A000 /* 23.103.160.0/20 */, 20, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x28600000 /* 40.96.0.0/13 */, 13, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x28680000 /* 40.104.0.0/15 */, 15, NDPI_PROTOCOL_MICROSOFT_365 },
- { 0x34600000 /* 52.96.0.0/14 */, 14, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x83FD21D7 /* 131.253.33.215/32 */, 32, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x84F50000 /* 132.245.0.0/16 */, 16, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x96AB2000 /* 150.171.32.0/22 */, 22, NDPI_PROTOCOL_MICROSOFT_365 },
@@ -8423,7 +8425,6 @@ static ndpi_network host_protocol_list[] = {
{ 0x1767A000 /* 23.103.160.0/20 */, 20, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x28600000 /* 40.96.0.0/13 */, 13, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x28680000 /* 40.104.0.0/15 */, 15, NDPI_PROTOCOL_MICROSOFT_365 },
- { 0x34600000 /* 52.96.0.0/14 */, 14, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x83FD21D7 /* 131.253.33.215/32 */, 32, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x84F50000 /* 132.245.0.0/16 */, 16, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x96AB2000 /* 150.171.32.0/22 */, 22, NDPI_PROTOCOL_MICROSOFT_365 },
@@ -8435,7 +8436,6 @@ static ndpi_network host_protocol_list[] = {
{ 0x1767A000 /* 23.103.160.0/20 */, 20, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x28600000 /* 40.96.0.0/13 */, 13, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x28680000 /* 40.104.0.0/15 */, 15, NDPI_PROTOCOL_MICROSOFT_365 },
- { 0x34600000 /* 52.96.0.0/14 */, 14, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x83FD21D7 /* 131.253.33.215/32 */, 32, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x84F50000 /* 132.245.0.0/16 */, 16, NDPI_PROTOCOL_MICROSOFT_365 },
{ 0x96AB2000 /* 150.171.32.0/22 */, 22, NDPI_PROTOCOL_MICROSOFT_365 },
@@ -8673,6 +8673,8 @@ static ndpi_protocol_match host_match[] =
{ ".cloudfront.net", "Amazon", NDPI_PROTOCOL_AMAZON, NDPI_PROTOCOL_CATEGORY_WEB, NDPI_PROTOCOL_ACCEPTABLE },
{ ".us-west-2.compute.amazonaws.com","Amazon", NDPI_PROTOCOL_AMAZON, NDPI_PROTOCOL_CATEGORY_WEB, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".teamviewer.com", "Teamviewer", NDPI_PROTOCOL_TEAMVIEWER, NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS, NDPI_PROTOCOL_ACCEPTABLE },
+
/* Microsoft + Azure */
{ ".azure.com", "Microsoft", NDPI_PROTOCOL_MICROSOFT, NDPI_PROTOCOL_CATEGORY_CLOUD, NDPI_PROTOCOL_SAFE },
{ ".windows.net", "Microsoft", NDPI_PROTOCOL_MICROSOFT, NDPI_PROTOCOL_CATEGORY_CLOUD, NDPI_PROTOCOL_SAFE },
@@ -8768,6 +8770,10 @@ static ndpi_protocol_match host_match[] =
/* http://check.googlezip.net/connect [check browser connectivity] */
// { ".googlezip.net", "Google", NDPI_PROTOCOL_GOOGLE, NDPI_PROTOCOL_CATEGORY_WEB, NDPI_PROTOCOL_SAFE },
+ /*
+ https://github.com/bambenek/block-doh/blob/master/db.doh-redirect
+ https://github.com/curl/curl/wiki/DNS-over-HTTPS
+ */
{ "dns.google", "DoH_DoT", NDPI_PROTOCOL_DOH_DOT, NDPI_PROTOCOL_CATEGORY_NETWORK, NDPI_PROTOCOL_ACCEPTABLE },
{ "mozilla.cloudflare-dns.com", "DoH_DoT", NDPI_PROTOCOL_DOH_DOT, NDPI_PROTOCOL_CATEGORY_NETWORK, NDPI_PROTOCOL_ACCEPTABLE }, /* Firefox */
{ "cloudflare-dns.com", "DoH_DoT", NDPI_PROTOCOL_DOH_DOT, NDPI_PROTOCOL_CATEGORY_NETWORK, NDPI_PROTOCOL_ACCEPTABLE },
@@ -8932,6 +8938,7 @@ static ndpi_protocol_match host_match[] =
{ ".spotify.", "Spotify", NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN },
{ "audio-fa.scdn.co", "Spotify", NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN },
+ { "spotifycdn.net", "Spotify", NDPI_PROTOCOL_SPOTIFY, NDPI_PROTOCOL_CATEGORY_MUSIC, NDPI_PROTOCOL_FUN },
{ "edge-mqtt.facebook.com", "Messenger", NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_CATEGORY_CHAT, NDPI_PROTOCOL_ACCEPTABLE },
{ "mqtt-mini.facebook.com", "Messenger", NDPI_PROTOCOL_MESSENGER, NDPI_PROTOCOL_CATEGORY_CHAT, NDPI_PROTOCOL_ACCEPTABLE }, /* Messenger Lite */
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index ca557ea31..fed3c9831 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -1626,7 +1626,7 @@ u_int16_t ndpi_network_port_ptree_match(struct ndpi_detection_module_struct *ndp
|| (node->value.uv.additional_user_value == port))
return(node->value.uv.user_value);
}
-
+
return(NDPI_PROTOCOL_UNKNOWN);
}
@@ -2198,10 +2198,10 @@ int ndpi_match_custom_category(struct ndpi_detection_module_struct *ndpi_str,
char *name, u_int name_len,
ndpi_protocol_category_t *category) {
ndpi_protocol_breed_t breed;
- u_int16_t id;
+ u_int16_t id;
int rc = ndpi_match_string_protocol_id(ndpi_str->custom_categories.hostnames.ac_automa,
name, name_len, &id, category, &breed);
-
+
return(rc);
}
@@ -2277,6 +2277,9 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) {
if(ndpi_str->stun_cache)
ndpi_lru_free_cache(ndpi_str->stun_cache);
+ if(ndpi_str->msteams_cache)
+ ndpi_lru_free_cache(ndpi_str->msteams_cache);
+
if(ndpi_str->protocols_ptree)
ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->protocols_ptree, free_ptree_data);
@@ -2315,7 +2318,7 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) {
#ifdef CUSTOM_NDPI_PROTOCOLS
#include "../../../nDPI-custom/ndpi_exit_detection_module.c"
#endif
-
+
ndpi_free(ndpi_str);
}
}
@@ -3491,12 +3494,17 @@ static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_stru
return(0);
}
+/* ************************************************ */
+
void ndpi_apply_flow_protocol_to_packet(struct ndpi_flow_struct *flow, struct ndpi_packet_struct *packet) {
memcpy(&packet->detected_protocol_stack, &flow->detected_protocol_stack, sizeof(packet->detected_protocol_stack));
memcpy(&packet->protocol_stack_info, &flow->protocol_stack_info, sizeof(packet->protocol_stack_info));
}
-static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
+/* ************************************************ */
+
+static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str,
+ struct ndpi_flow_struct *flow,
unsigned short packetlen) {
const struct ndpi_iphdr *decaps_iph = NULL;
u_int16_t l3len;
@@ -3634,7 +3642,10 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str
return(0);
}
-void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) {
+/* ************************************************ */
+
+void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str,
+ struct ndpi_flow_struct *flow) {
if(!flow) {
return;
} else {
@@ -3756,10 +3767,12 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, str
}
}
+/* ************************************************ */
+
void check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
if(!flow)
- return;
+ return;
void *func = NULL;
u_int32_t a;
@@ -3797,6 +3810,8 @@ void check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str, s
}
}
+/* ************************************************ */
+
void check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
void *func = NULL;
@@ -3838,7 +3853,10 @@ void check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_str, str
}
}
-void check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow,
+/* ************************************************ */
+
+void check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_str,
+ struct ndpi_flow_struct *flow,
NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) {
void *func = NULL;
u_int32_t a;
@@ -3931,16 +3949,16 @@ u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_
if(flow->packet.iph) {
struct in_addr addr;
u_int16_t sport, dport;
-
+
addr.s_addr = flow->packet.iph->saddr;
-
+
if((flow->l4_proto == IPPROTO_TCP) && flow->packet.tcp)
sport = flow->packet.tcp->source, dport = flow->packet.tcp->dest;
else if((flow->l4_proto == IPPROTO_UDP) && flow->packet.udp)
sport = flow->packet.udp->source, dport = flow->packet.udp->dest;
else
sport = dport = 0;
-
+
/* guess host protocol */
ret = ndpi_network_port_ptree_match(ndpi_str, &addr, sport);
@@ -4342,11 +4360,79 @@ static void ndpi_reset_packet_line_info(struct ndpi_packet_struct *packet) {
/* ********************************************************************************* */
-#if 0
-static u_int16_t ndpi_checK_flow_port(, u_int16_t sport, u_int16_t dport) {
+static int ndpi_check_protocol_port_mismatch_exceptions(struct ndpi_detection_module_struct *ndpi_str,
+ struct ndpi_flow_struct *flow,
+ ndpi_default_ports_tree_node_t *expected_proto,
+ ndpi_protocol *returned_proto) {
+ /*
+ For TLS (and other protocols) it is not simple to guess the exact protocol so before
+ triggering an alert we need to make sure what we have exhausted all the possible
+ options available
+ */
+ if(returned_proto->master_protocol == NDPI_PROTOCOL_TLS) {
+ switch(expected_proto->proto->protoId) {
+ case NDPI_PROTOCOL_MAIL_IMAPS:
+ case NDPI_PROTOCOL_MAIL_POPS:
+ case NDPI_PROTOCOL_MAIL_SMTPS:
+ return(1); /* This is a reasonable exception */
+ break;
+ }
+ }
+
+ return(0);
+}
+
+/* ********************************************************************************* */
+
+static void ndpi_reconcile_protocols(struct ndpi_detection_module_struct *ndpi_str,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol *ret) {
+ /*
+ Skype for a host doing MS Teams means MS Teams
+ (MS Teams uses Skype as transport protocol for voice/video)
+ */
+
+ switch(ret->app_protocol) {
+ case NDPI_PROTOCOL_MSTEAMS:
+ if(flow->packet.iph && flow->packet.tcp) {
+ // printf("====>> NDPI_PROTOCOL_MSTEAMS\n");
+
+ if(ndpi_str->msteams_cache == NULL)
+ ndpi_str->msteams_cache = ndpi_lru_cache_init(1024);
+
+ if(ndpi_str->msteams_cache)
+ ndpi_lru_add_to_cache(ndpi_str->msteams_cache,
+ flow->packet.iph->saddr,
+ flow->packet.tick_timestamp & 0xFFFF /* 16 bit */);
+ }
+ break;
+
+ case NDPI_PROTOCOL_SKYPE:
+ case NDPI_PROTOCOL_SKYPE_CALL:
+ if(flow->packet.iph
+ && flow->packet.udp
+ && ndpi_str->msteams_cache) {
+ u_int16_t when;
+
+ if(ndpi_lru_find_cache(ndpi_str->msteams_cache, flow->packet.iph->saddr,
+ &when, 0 /* Don't remove it as it can be used for other connections */)) {
+ u_int16_t tdiff = (flow->packet.tick_timestamp & 0xFFFF) - when;
+
+ if(tdiff < 60 /* sec */) {
+ // printf("====>> NDPI_PROTOCOL_SKYPE(_CALL) -> NDPI_PROTOCOL_MSTEAMS [%u]\n", tdiff);
+ ret->app_protocol = NDPI_PROTOCOL_MSTEAMS;
+
+ /* Refresh cache */
+ ndpi_lru_add_to_cache(ndpi_str->msteams_cache,
+ flow->packet.iph->saddr,
+ flow->packet.tick_timestamp & 0xFFFF /* 16 bit */);
+ }
+ }
+ }
+ break;
+ } /* switch */
}
-#endif
/* ********************************************************************************* */
@@ -4586,7 +4672,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
if((!flow->risk_checked) && (ret.master_protocol != NDPI_PROTOCOL_UNKNOWN)) {
ndpi_default_ports_tree_node_t *found;
u_int16_t *default_ports, sport, dport;
-
+
if(flow->packet.udp)
found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_UDP,
sport = ntohs(flow->packet.udp->source),
@@ -4596,7 +4682,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_TCP,
sport = ntohs(flow->packet.tcp->source),
dport = ntohs(flow->packet.tcp->dest)),
- default_ports = ndpi_str->proto_defaults[ret.master_protocol].tcp_default_ports;
+ default_ports = ndpi_str->proto_defaults[ret.master_protocol].tcp_default_ports;
else
found = NULL, default_ports = NULL;
@@ -4604,10 +4690,12 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
&& (found->proto->protoId != NDPI_PROTOCOL_UNKNOWN)
&& (found->proto->protoId != ret.master_protocol)) {
// printf("******** %u / %u\n", found->proto->protoId, ret.master_protocol);
- NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
+
+ if(!ndpi_check_protocol_port_mismatch_exceptions(ndpi_str, flow, found, &ret))
+ NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
} else if(default_ports && (default_ports[0] != 0)) {
u_int8_t found = 0, i;
-
+
for(i=0; (i<MAX_DEFAULT_PORTS) && (default_ports[i] != 0); i++) {
if((default_ports[i] == sport) || (default_ports[i] == dport)) {
found = 1;
@@ -4620,10 +4708,11 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT);
}
}
-
+
flow->risk_checked = 1;
}
-
+
+ ndpi_reconcile_protocols(ndpi_str, flow, &ret);
invalidate_ptr:
/*
@@ -4749,29 +4838,34 @@ u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t *str, u_int16_t max_chars_to_re
u_int16_t read = 0;
u_int16_t oldread;
u_int32_t c;
+
/* ip address must be X.X.X.X with each X between 0 and 255 */
oldread = read;
c = ndpi_bytestream_to_number(str, max_chars_to_read, &read);
if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
return(0);
+
read++;
val = c << 24;
oldread = read;
c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
return(0);
+
read++;
val = val + (c << 16);
oldread = read;
c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.')
return(0);
+
read++;
val = val + (c << 8);
oldread = read;
c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read);
if(c > 255 || oldread == read || max_chars_to_read == read)
return(0);
+
val = val + c;
*bytes_read = *bytes_read + read;
@@ -4805,14 +4899,16 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str,
if(get_u_int16_t(packet->payload, a) == ntohs(0x0d0a)) {
/* If end of line char sequence CR+NL "\r\n", process line */
- if(get_u_int16_t(packet->payload, a+2) == ntohs(0x0d0a)) {
+ if(((a + 3) <= packet->payload_packet_len)
+ && (get_u_int16_t(packet->payload, a+2) == ntohs(0x0d0a))) {
/* \r\n\r\n */
int diff; /* No unsigned ! */
u_int32_t a1 = a + 4;
- diff = ndpi_min(packet->payload_packet_len-a1, sizeof(flow->initial_binary_bytes));
-
+ diff = packet->payload_packet_len - a1;
+
if(diff > 0) {
+ diff = ndpi_min(diff, sizeof(flow->initial_binary_bytes));
memcpy(&flow->initial_binary_bytes, &packet->payload[a1], diff);
flow->initial_binary_bytes_len = diff;
}
@@ -5814,27 +5910,21 @@ char *ndpi_strnstr(const char *s, const char *find, size_t slen) {
/*
* Same as ndpi_strnstr but case-insensitive
*/
-char *ndpi_strncasestr(const char *s, const char *find, size_t slen) {
- char c;
- size_t len;
-
- if((c = *find++) != '\0') {
- len = strlen(find);
- do {
- char sc;
-
- do {
- if(slen-- < 1 || (sc = *s++) == '\0')
- return(NULL);
- } while (sc != c);
-
- if(len > slen)
- return(NULL);
- } while (strncasecmp(s, find, len) != 0);
-
- s--;
+const char * ndpi_strncasestr(const char *str1, const char *str2, size_t len) {
+ size_t str1_len = strnlen(str1, len);
+ size_t str2_len = strlen(str2);
+ size_t i;
+
+ for(i = 0; i < (str1_len - str2_len + 1); i++){
+ if(str1[0] == '\0')
+ return NULL;
+ else if(strncasecmp(str1, str2, str2_len) == 0)
+ return(str1);
+
+ str1++;
}
- return((char *) s);
+
+ return NULL;
}
/* ****************************************************** */
@@ -6065,6 +6155,9 @@ void ndpi_free_flow(struct ndpi_flow_struct *flow) {
if(flow->l4.tcp.tls.srv_cert_fingerprint_ctx)
ndpi_free(flow->l4.tcp.tls.srv_cert_fingerprint_ctx);
+
+ if(flow->protos.stun_ssl.ssl.encrypted_sni.esni)
+ ndpi_free(flow->protos.stun_ssl.ssl.encrypted_sni.esni);
}
if(flow->l4_proto == IPPROTO_TCP) {
diff --git a/src/lib/ndpi_serializer.c b/src/lib/ndpi_serializer.c
index d8a0d13fc..a50f98860 100644
--- a/src/lib/ndpi_serializer.c
+++ b/src/lib/ndpi_serializer.c
@@ -146,15 +146,27 @@ void ndpi_reset_serializer(ndpi_serializer *_serializer) {
if(serializer->fmt == ndpi_serialization_format_json) {
u_int32_t buff_diff;
- serializer->status.size_used = 0;
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ serializer->status.buffer.size_used = 0;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
/* Note: please keep a space at the beginning as it is used for arrays when an end-of-record is used */
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, " {}");
- } else if(serializer->fmt == ndpi_serialization_format_csv)
- serializer->status.size_used = 0;
- else /* ndpi_serialization_format_tlv */
- serializer->status.size_used = 2 * sizeof(u_int8_t);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, " {}");
+ } else if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->status.header.size_used = 0;
+ serializer->status.buffer.size_used = 0;
+ } else { /* ndpi_serialization_format_tlv */
+ serializer->status.buffer.size_used = 2 * sizeof(u_int8_t);
+ }
+}
+
+/* ********************************** */
+
+static int ndpi_init_serializer_buffer(ndpi_private_serializer_buffer *buffer, u_int32_t buffer_size) {
+ buffer->initial_size = buffer->size = buffer_size;
+ buffer->data = (u_int8_t *) calloc(buffer->size, sizeof(u_int8_t));
+ if(buffer->data == NULL)
+ return -1;
+ return 0;
}
/* ********************************** */
@@ -166,16 +178,22 @@ int ndpi_init_serializer_ll(ndpi_serializer *_serializer,
memset(serializer, 0, sizeof(ndpi_private_serializer));
- serializer->initial_buffer_size = serializer->buffer_size = buffer_size;
- serializer->buffer = (u_int8_t *) calloc(serializer->buffer_size, sizeof(u_int8_t));
+ serializer->fmt = fmt;
- if(serializer->buffer == NULL)
+ if (ndpi_init_serializer_buffer(&serializer->buffer, buffer_size) != 0)
return(-1);
+
+ if(serializer->fmt == ndpi_serialization_format_json) {
+ /* nothing to do */
- serializer->fmt = fmt;
+ } else if (fmt == ndpi_serialization_format_csv) {
+ if (ndpi_init_serializer_buffer(&serializer->header, NDPI_SERIALIZER_DEFAULT_HEADER_SIZE) != 0)
+ return(-1);
- serializer->buffer[0] = 1; /* version */
- serializer->buffer[1] = (u_int8_t) fmt;
+ } else /* ndpi_serialization_format_tlv */ {
+ serializer->buffer.data[0] = 1; /* version */
+ serializer->buffer.data[1] = (u_int8_t) fmt;
+ }
serializer->csv_separator[0] = ',';
serializer->csv_separator[1] = '\0';
@@ -194,45 +212,106 @@ int ndpi_init_serializer(ndpi_serializer *_serializer,
/* ********************************** */
-static inline int ndpi_extend_serializer_buffer(ndpi_serializer *_serializer, u_int32_t min_len) {
+static inline int ndpi_extend_serializer_buffer(ndpi_private_serializer_buffer *buffer, u_int32_t min_len) {
u_int32_t new_size;
void *r;
- ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
if(min_len < NDPI_SERIALIZER_DEFAULT_BUFFER_INCR) {
- if(serializer->initial_buffer_size < NDPI_SERIALIZER_DEFAULT_BUFFER_INCR) {
- if(min_len < serializer->initial_buffer_size)
- min_len = serializer->initial_buffer_size;
+ if(buffer->initial_size < NDPI_SERIALIZER_DEFAULT_BUFFER_INCR) {
+ if(min_len < buffer->initial_size)
+ min_len = buffer->initial_size;
} else {
min_len = NDPI_SERIALIZER_DEFAULT_BUFFER_INCR;
}
}
- new_size = serializer->buffer_size + min_len;
+ new_size = buffer->size + min_len;
new_size = ((new_size / 4) + 1) * 4; /* required by zmq encryption */
- r = realloc((void *) serializer->buffer, new_size);
+ r = realloc((void *) buffer->data, new_size);
if(r == NULL)
return(-1);
- serializer->buffer = r;
- serializer->buffer_size = new_size;
+ buffer->data = r;
+ buffer->size = new_size;
return(0);
}
/* ********************************** */
+static inline int ndpi_serializer_check_header_room(ndpi_private_serializer *serializer, u_int32_t needed) {
+ u_int32_t buff_diff = serializer->header.size - serializer->status.header.size_used;
+
+ if (buff_diff < needed)
+ if (ndpi_extend_serializer_buffer(&serializer->header, needed - buff_diff) < 0)
+ return -1;
+
+ buff_diff = serializer->header.size - serializer->status.header.size_used;
+
+ return buff_diff;
+}
+
+/* ********************************** */
+
+static inline int ndpi_serializer_header_uint32(ndpi_private_serializer *serializer, u_int32_t key) {
+ int room;
+
+ if (serializer->status.flags & NDPI_SERIALIZER_STATUS_HDR_DONE)
+ return 0;
+
+ room = ndpi_serializer_check_header_room(serializer, 12);
+
+ if (room < 0)
+ return -1;
+
+ serializer->status.header.size_used += snprintf((char *) &serializer->header.data[serializer->status.header.size_used],
+ room, "%s%u", (serializer->status.header.size_used > 0) ? serializer->csv_separator : "", key);
+
+ return 0;
+}
+
+/* ********************************** */
+
+static inline int ndpi_serializer_header_string(ndpi_private_serializer *serializer, const char *key, u_int16_t klen) {
+ int room;
+
+ if (serializer->status.flags & NDPI_SERIALIZER_STATUS_HDR_DONE)
+ return 0;
+
+ room = ndpi_serializer_check_header_room(serializer, klen + 4);
+
+ if (room < 0)
+ return -1;
+
+ if (serializer->status.header.size_used > 0) {
+ int slen = strlen(serializer->csv_separator);
+ memcpy(&serializer->header.data[serializer->status.header.size_used], serializer->csv_separator, slen);
+ serializer->status.header.size_used += slen;
+ }
+
+ if (klen > 0) {
+ memcpy(&serializer->header.data[serializer->status.header.size_used], key, klen);
+ serializer->status.header.size_used += klen;
+ }
+
+ serializer->header.data[serializer->status.header.size_used] = '\0';
+
+ return 0;
+}
+
+/* ********************************** */
+
char* ndpi_serializer_get_buffer(ndpi_serializer *_serializer, u_int32_t *buffer_len) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- char *buf = (char*)serializer->buffer;
+ char *buf = (char*)serializer->buffer.data;
- /* NULL terminate the buffer if there is space available */
- if(serializer->buffer_size > serializer->status.size_used)
- serializer->buffer[serializer->status.size_used] = '\0';
+ /* NULL terminate the buffer */
+ if(serializer->buffer.size > serializer->status.buffer.size_used) /* safety check */
+ serializer->buffer.data[serializer->status.buffer.size_used] = '\0';
- *buffer_len = serializer->status.size_used;
+ *buffer_len = serializer->status.buffer.size_used;
if(serializer->fmt == ndpi_serialization_format_json) {
while((buf[0] == '\0') || (buf[0] == ' '))
@@ -245,13 +324,13 @@ char* ndpi_serializer_get_buffer(ndpi_serializer *_serializer, u_int32_t *buffer
/* ********************************** */
u_int32_t ndpi_serializer_get_buffer_len(ndpi_serializer *_serializer) {
- return(((ndpi_private_serializer*)_serializer)->status.size_used);
+ return(((ndpi_private_serializer*)_serializer)->status.buffer.size_used);
}
/* ********************************** */
u_int32_t ndpi_serializer_get_internal_buffer_size(ndpi_serializer *_serializer) {
- return(((ndpi_private_serializer*)_serializer)->buffer_size);
+ return(((ndpi_private_serializer*)_serializer)->buffer.size);
}
/* ********************************** */
@@ -260,10 +339,10 @@ int ndpi_serializer_set_buffer_len(ndpi_serializer *_serializer, u_int32_t l) {
ndpi_private_serializer *p = (ndpi_private_serializer*)_serializer;
if(p) {
- if(p->buffer_size <= l)
+ if(p->buffer.size <= l)
return(-1); /* Invalid size */
- p->status.size_used = l;
+ p->status.buffer.size_used = l;
return(0);
}
@@ -272,6 +351,27 @@ int ndpi_serializer_set_buffer_len(ndpi_serializer *_serializer, u_int32_t l) {
/* ********************************** */
+/* Return the header automatically built from keys (CSV only) */
+char* ndpi_serializer_get_header(ndpi_serializer *_serializer, u_int32_t *buffer_len) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ char *buf = (char*)serializer->header.data;
+
+ if(buf == NULL) {
+ *buffer_len = 0;
+ return "";
+ }
+
+ /* NULL terminate the buffer */
+ if(serializer->header.size > serializer->status.header.size_used) /* safety check */
+ serializer->header.data[serializer->status.header.size_used] = '\0';
+
+ *buffer_len = serializer->status.header.size_used;
+
+ return(buf);
+}
+
+/* ********************************** */
+
void ndpi_serializer_set_csv_separator(ndpi_serializer *_serializer, char separator) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
@@ -283,10 +383,16 @@ void ndpi_serializer_set_csv_separator(ndpi_serializer *_serializer, char separa
void ndpi_term_serializer(ndpi_serializer *_serializer) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- if(serializer->buffer) {
- free(serializer->buffer);
- serializer->buffer_size = 0;
- serializer->buffer = NULL;
+ if(serializer->buffer.data) {
+ free(serializer->buffer.data);
+ serializer->buffer.size = 0;
+ serializer->buffer.data = NULL;
+ }
+
+ if(serializer->header.data) {
+ free(serializer->header.data);
+ serializer->header.size = 0;
+ serializer->header.data = NULL;
}
}
@@ -296,8 +402,8 @@ static inline void ndpi_serialize_single_uint8(ndpi_private_serializer *serializ
u_int8_t s) {
u_int8_t v = s;
- memcpy(&serializer->buffer[serializer->status.size_used], &v, sizeof(u_int8_t));
- serializer->status.size_used += sizeof(u_int8_t);
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int8_t));
+ serializer->status.buffer.size_used += sizeof(u_int8_t);
}
/* ********************************** */
@@ -306,8 +412,8 @@ static inline void ndpi_serialize_single_uint16(ndpi_private_serializer *seriali
u_int16_t s) {
u_int16_t v = htons(s);
- memcpy(&serializer->buffer[serializer->status.size_used], &v, sizeof(u_int16_t));
- serializer->status.size_used += sizeof(u_int16_t);
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int16_t));
+ serializer->status.buffer.size_used += sizeof(u_int16_t);
}
/* ********************************** */
@@ -316,8 +422,8 @@ static inline void ndpi_serialize_single_uint32(ndpi_private_serializer *seriali
u_int32_t s) {
u_int32_t v = htonl(s);
- memcpy(&serializer->buffer[serializer->status.size_used], &v, sizeof(u_int32_t));
- serializer->status.size_used += sizeof(u_int32_t);
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int32_t));
+ serializer->status.buffer.size_used += sizeof(u_int32_t);
}
/* ********************************** */
@@ -326,8 +432,8 @@ static inline void ndpi_serialize_single_uint64(ndpi_private_serializer *seriali
u_int64_t s) {
u_int64_t v = ndpi_htonll(s);
- memcpy(&serializer->buffer[serializer->status.size_used], &v, sizeof(u_int64_t));
- serializer->status.size_used += sizeof(u_int64_t);
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &v, sizeof(u_int64_t));
+ serializer->status.buffer.size_used += sizeof(u_int64_t);
}
/* ********************************** */
@@ -335,8 +441,8 @@ static inline void ndpi_serialize_single_uint64(ndpi_private_serializer *seriali
/* TODO: fix portability across platforms */
static inline void ndpi_serialize_single_float(ndpi_private_serializer *serializer,
float s) {
- memcpy(&serializer->buffer[serializer->status.size_used], &s, sizeof(s));
- serializer->status.size_used += sizeof(float);
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &s, sizeof(s));
+ serializer->status.buffer.size_used += sizeof(float);
}
/* ********************************** */
@@ -345,69 +451,69 @@ static inline void ndpi_serialize_single_string(ndpi_private_serializer *seriali
const char *s, u_int16_t slen) {
u_int16_t l = htons(slen);
- memcpy(&serializer->buffer[serializer->status.size_used], &l, sizeof(u_int16_t));
- serializer->status.size_used += sizeof(u_int16_t);
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], &l, sizeof(u_int16_t));
+ serializer->status.buffer.size_used += sizeof(u_int16_t);
if(slen > 0)
- memcpy(&serializer->buffer[serializer->status.size_used], s, slen);
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], s, slen);
- serializer->status.size_used += slen;
+ serializer->status.buffer.size_used += slen;
}
/* ********************************** */
static inline void ndpi_deserialize_single_uint8(ndpi_private_deserializer *deserializer,
u_int32_t offset, u_int8_t *s) {
- *s = (*((u_int8_t *) &deserializer->buffer[offset]));
+ *s = (*((u_int8_t *) &deserializer->buffer.data[offset]));
}
/* ********************************** */
static inline void ndpi_deserialize_single_uint16(ndpi_private_deserializer *deserializer,
u_int32_t offset, u_int16_t *s) {
- *s = ntohs(*((u_int16_t *) &deserializer->buffer[offset]));
+ *s = ntohs(*((u_int16_t *) &deserializer->buffer.data[offset]));
}
/* ********************************** */
static inline void ndpi_deserialize_single_uint32(ndpi_private_deserializer *deserializer,
u_int32_t offset, u_int32_t *s) {
- *s = ntohl(*((u_int32_t *) &deserializer->buffer[offset]));
+ *s = ntohl(*((u_int32_t *) &deserializer->buffer.data[offset]));
}
/* ********************************** */
static inline void ndpi_deserialize_single_int8(ndpi_private_deserializer *deserializer,
u_int32_t offset, int8_t *s) {
- *s = (*((int8_t *) &deserializer->buffer[offset]));
+ *s = (*((int8_t *) &deserializer->buffer.data[offset]));
}
/* ********************************** */
static inline void ndpi_deserialize_single_int16(ndpi_private_deserializer *deserializer,
u_int32_t offset, int16_t *s) {
- *s = ntohs(*((int16_t *) &deserializer->buffer[offset]));
+ *s = ntohs(*((int16_t *) &deserializer->buffer.data[offset]));
}
/* ********************************** */
static inline void ndpi_deserialize_single_int32(ndpi_private_deserializer *deserializer,
u_int32_t offset, int32_t *s) {
- *s = ntohl(*((int32_t *) &deserializer->buffer[offset]));
+ *s = ntohl(*((int32_t *) &deserializer->buffer.data[offset]));
}
/* ********************************** */
static inline void ndpi_deserialize_single_uint64(ndpi_private_deserializer *deserializer,
u_int32_t offset, u_int64_t *s) {
- *s = ndpi_ntohll(*(u_int64_t*)&deserializer->buffer[offset]);
+ *s = ndpi_ntohll(*(u_int64_t*)&deserializer->buffer.data[offset]);
}
/* ********************************** */
static inline void ndpi_deserialize_single_int64(ndpi_private_deserializer *deserializer,
u_int32_t offset, int64_t *s) {
- *s = ndpi_ntohll(*(int64_t*)&deserializer->buffer[offset]);
+ *s = ndpi_ntohll(*(int64_t*)&deserializer->buffer.data[offset]);
}
/* ********************************** */
@@ -415,15 +521,15 @@ static inline void ndpi_deserialize_single_int64(ndpi_private_deserializer *dese
/* TODO: fix portability across platforms */
static inline void ndpi_deserialize_single_float(ndpi_private_deserializer *deserializer,
u_int32_t offset, float *s) {
- *s = *(float*)&deserializer->buffer[offset];
+ *s = *(float*)&deserializer->buffer.data[offset];
}
/* ********************************** */
static inline void ndpi_deserialize_single_string(ndpi_private_deserializer *deserializer,
u_int32_t offset, ndpi_string *v) {
- v->str_len = ntohs(*((u_int16_t *) &deserializer->buffer[offset]));
- v->str = (char *) &deserializer->buffer[offset + sizeof(u_int16_t)];
+ v->str_len = ntohs(*((u_int16_t *) &deserializer->buffer.data[offset]));
+ v->str = (char *) &deserializer->buffer.data[offset + sizeof(u_int16_t)];
}
/* ********************************** */
@@ -436,39 +542,39 @@ static inline void ndpi_deserialize_single_string(ndpi_private_deserializer *des
int ndpi_serialize_raw_record(ndpi_serializer *_serializer,
u_char *record, u_int32_t record_len) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t needed = record_len;
u_int8_t add_comma = 0;
if(serializer->fmt == ndpi_serialization_format_json) {
needed += 1;
- if(serializer->status.size_used == 3) /* Empty buffer [{} */
- serializer->status.size_used = 2; /* Remove {} */
+ if(serializer->status.buffer.size_used == 3) /* Empty buffer [{} */
+ serializer->status.buffer.size_used = 2; /* Remove {} */
else
needed += 2, add_comma = 1;
}
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
if(add_comma)
- serializer->buffer[serializer->status.size_used-1] = ',';
+ serializer->buffer.data[serializer->status.buffer.size_used-1] = ',';
else
- serializer->status.size_used--;
+ serializer->status.buffer.size_used--;
}
- memcpy(&serializer->buffer[serializer->status.size_used], record, record_len);
- serializer->status.size_used += record_len;
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used], record, record_len);
+ serializer->status.buffer.size_used += record_len;
if(serializer->fmt == ndpi_serialization_format_json) {
- serializer->buffer[serializer->status.size_used] = ']';
- if(add_comma) serializer->status.size_used++;
+ serializer->buffer.data[serializer->status.buffer.size_used] = ']';
+ if(add_comma) serializer->status.buffer.size_used++;
}
ndpi_serialize_end_of_record(_serializer);
@@ -480,29 +586,31 @@ int ndpi_serialize_raw_record(ndpi_serializer *_serializer,
int ndpi_serialize_end_of_record(ndpi_serializer *_serializer) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t needed = sizeof(u_int8_t) /* type */;
if(serializer->fmt == ndpi_serialization_format_json)
needed += 1;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
- if(serializer->fmt == ndpi_serialization_format_json) {
+ if(serializer->fmt == ndpi_serialization_format_csv) {
+ serializer->status.flags |= NDPI_SERIALIZER_STATUS_HDR_DONE;
+ } else if(serializer->fmt == ndpi_serialization_format_json) {
if(!(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY)) {
- serializer->buffer[0] = '[';
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used],
+ serializer->buffer.data[0] = '[';
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used],
buff_diff, "]");
}
serializer->status.flags |= NDPI_SERIALIZER_STATUS_ARRAY | NDPI_SERIALIZER_STATUS_EOR;
serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_COMMA;
} else {
- serializer->buffer[serializer->status.size_used++] = ndpi_serialization_end_of_record;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = ndpi_serialization_end_of_record;
}
serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_NOT_EMPTY;
@@ -516,19 +624,28 @@ static inline void ndpi_serialize_json_pre(ndpi_serializer *_serializer) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
if(serializer->status.flags & NDPI_SERIALIZER_STATUS_EOR) {
- serializer->status.size_used--; /* Remove ']' */
+ serializer->status.buffer.size_used--; /* Remove ']' */
serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_EOR;
- serializer->buffer[serializer->status.size_used++] = ',';
- serializer->buffer[serializer->status.size_used++] = '{';
+ serializer->buffer.data[serializer->status.buffer.size_used++] = ',';
+ serializer->buffer.data[serializer->status.buffer.size_used++] = '{';
} else {
if(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY)
- serializer->status.size_used--; /* Remove ']'*/
- serializer->status.size_used--; /* Remove '}'*/
+ serializer->status.buffer.size_used--; /* Remove ']' */
- if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOB)
- serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOB;
- else if(serializer->status.flags & NDPI_SERIALIZER_STATUS_COMMA)
- serializer->buffer[serializer->status.size_used++] = ',';
+ serializer->status.buffer.size_used--; /* Remove '}' */
+
+ if(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST) {
+ serializer->status.buffer.size_used--; /* Remove ']' */
+ if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOL)
+ serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOL;
+ else
+ serializer->buffer.data[serializer->status.buffer.size_used++] = ',';
+ } else {
+ if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOB)
+ serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOB;
+ else if(serializer->status.flags & NDPI_SERIALIZER_STATUS_COMMA)
+ serializer->buffer.data[serializer->status.buffer.size_used++] = ',';
+ }
}
}
@@ -537,9 +654,13 @@ static inline void ndpi_serialize_json_pre(ndpi_serializer *_serializer) {
static inline void ndpi_serialize_json_post(ndpi_serializer *_serializer) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- serializer->buffer[serializer->status.size_used++] = '}';
+ if(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)
+ serializer->buffer.data[serializer->status.buffer.size_used++] = ']';
+
+ serializer->buffer.data[serializer->status.buffer.size_used++] = '}';
+
if(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY)
- serializer->buffer[serializer->status.size_used++] = ']';
+ serializer->buffer.data[serializer->status.buffer.size_used++] = ']';
serializer->status.flags |= NDPI_SERIALIZER_STATUS_COMMA;
}
@@ -568,7 +689,7 @@ static inline ndpi_serialization_type ndpi_serialize_key_uint32(ndpi_private_ser
int ndpi_serialize_uint32_uint32(ndpi_serializer *_serializer,
u_int32_t key, u_int32_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t needed =
sizeof(u_int8_t) /* type */ +
sizeof(u_int32_t) /* key */ +
@@ -578,23 +699,34 @@ int ndpi_serialize_uint32_uint32(ndpi_serializer *_serializer,
needed += 24;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "\"%u\":%u", key, value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "\"%u\":", key);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "%u", value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%u", (serializer->status.size_used > 0) ? serializer->csv_separator : "", value);
+ if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%u", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "", value);
} else {
ndpi_serialization_type kt;
u_int8_t type = 0;
- u_int32_t type_offset = serializer->status.size_used++;
+ u_int32_t type_offset = serializer->status.buffer.size_used++;
kt = ndpi_serialize_key_uint32(serializer, key);
type = (kt << 4);
@@ -610,7 +742,7 @@ int ndpi_serialize_uint32_uint32(ndpi_serializer *_serializer,
type |= ndpi_serialization_uint32;
}
- serializer->buffer[type_offset] = type;
+ serializer->buffer.data[type_offset] = type;
}
serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
@@ -622,7 +754,7 @@ int ndpi_serialize_uint32_uint32(ndpi_serializer *_serializer,
int ndpi_serialize_uint32_uint64(ndpi_serializer *_serializer,
u_int32_t key, u_int64_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t needed =
sizeof(u_int8_t) /* type */ +
sizeof(u_int32_t) /* key */ +
@@ -632,20 +764,31 @@ int ndpi_serialize_uint32_uint64(ndpi_serializer *_serializer,
needed += 32;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "\"%u\":%llu", key, (unsigned long long)value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "\"%u\":", key);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%llu", (unsigned long long)value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
+ if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
"%s%llu",
- (serializer->status.size_used > 0) ? serializer->csv_separator : "",
+ (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "",
(unsigned long long)value);
} else {
if(value <= 0xffffffff) {
@@ -653,7 +796,7 @@ int ndpi_serialize_uint32_uint64(ndpi_serializer *_serializer,
} else {
ndpi_serialization_type kt;
u_int8_t type = 0;
- u_int32_t type_offset = serializer->status.size_used++;
+ u_int32_t type_offset = serializer->status.buffer.size_used++;
kt = ndpi_serialize_key_uint32(serializer, key);
type = (kt << 4);
@@ -661,7 +804,7 @@ int ndpi_serialize_uint32_uint64(ndpi_serializer *_serializer,
ndpi_serialize_single_uint64(serializer, value);
type |= ndpi_serialization_uint64;
- serializer->buffer[type_offset] = type;
+ serializer->buffer.data[type_offset] = type;
}
}
@@ -674,7 +817,7 @@ int ndpi_serialize_uint32_uint64(ndpi_serializer *_serializer,
int ndpi_serialize_uint32_int32(ndpi_serializer *_serializer,
u_int32_t key, int32_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t needed =
sizeof(u_int8_t) /* type */ +
sizeof(u_int32_t) /* key */ +
@@ -684,23 +827,34 @@ int ndpi_serialize_uint32_int32(ndpi_serializer *_serializer,
needed += 24;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "\"%u\":%d", key, value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "\"%u\":", key);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "%d", value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%d", (serializer->status.size_used > 0) ? serializer->csv_separator : "", value);
+ if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%d", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "", value);
} else {
ndpi_serialization_type kt;
u_int8_t type = 0;
- u_int32_t type_offset = serializer->status.size_used++;
+ u_int32_t type_offset = serializer->status.buffer.size_used++;
kt = ndpi_serialize_key_uint32(serializer, key);
type = (kt << 4);
@@ -716,7 +870,7 @@ int ndpi_serialize_uint32_int32(ndpi_serializer *_serializer,
type |= ndpi_serialization_int32;
}
- serializer->buffer[type_offset] = type;
+ serializer->buffer.data[type_offset] = type;
}
serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
@@ -728,7 +882,7 @@ int ndpi_serialize_uint32_int32(ndpi_serializer *_serializer,
int ndpi_serialize_uint32_int64(ndpi_serializer *_serializer,
u_int32_t key, int64_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t needed =
sizeof(u_int8_t) /* type */ +
sizeof(u_int32_t) /* key */ +
@@ -738,20 +892,31 @@ int ndpi_serialize_uint32_int64(ndpi_serializer *_serializer,
needed += 32;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "\"%u\":%lld", key, (long long int)value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "\"%u\":", key);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "%lld", (long long int)value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
+ if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
"%s%lld",
- (serializer->status.size_used > 0) ? serializer->csv_separator : "",
+ (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "",
(long long int)value);
}
@@ -761,7 +926,7 @@ int ndpi_serialize_uint32_int64(ndpi_serializer *_serializer,
} else {
ndpi_serialization_type kt;
u_int8_t type = 0;
- u_int32_t type_offset = serializer->status.size_used++;
+ u_int32_t type_offset = serializer->status.buffer.size_used++;
kt = ndpi_serialize_key_uint32(serializer, key);
type = (kt << 4);
@@ -769,7 +934,7 @@ int ndpi_serialize_uint32_int64(ndpi_serializer *_serializer,
ndpi_serialize_single_uint64(serializer, value);
type |= ndpi_serialization_int64;
- serializer->buffer[type_offset] = type;
+ serializer->buffer.data[type_offset] = type;
}
}
@@ -783,7 +948,7 @@ int ndpi_serialize_uint32_float(ndpi_serializer *_serializer,
u_int32_t key, float value,
const char *format /* e.f. "%.2f" */) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t needed =
sizeof(u_int8_t) /* type */ +
sizeof(u_int32_t) /* key */ +
@@ -793,25 +958,32 @@ int ndpi_serialize_uint32_float(ndpi_serializer *_serializer,
needed += 32;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, "\"%u\":", key);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, format, value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "\"%u\":", key);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, "%s",
- (serializer->status.size_used > 0) ? serializer->csv_separator : "");
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, format, value);
+ if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%s",
+ (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "");
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
} else {
ndpi_serialization_type kt;
u_int8_t type = 0;
- u_int32_t type_offset = serializer->status.size_used++;
+ u_int32_t type_offset = serializer->status.buffer.size_used++;
kt = ndpi_serialize_key_uint32(serializer, key);
type = (kt << 4);
@@ -819,7 +991,7 @@ int ndpi_serialize_uint32_float(ndpi_serializer *_serializer,
ndpi_serialize_single_float(serializer, value);
type |= ndpi_serialization_float;
- serializer->buffer[type_offset] = type;
+ serializer->buffer.data[type_offset] = type;
}
serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
@@ -831,7 +1003,7 @@ int ndpi_serialize_uint32_float(ndpi_serializer *_serializer,
static int ndpi_serialize_uint32_binary(ndpi_serializer *_serializer,
u_int32_t key, const char *value, u_int16_t slen) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed =
sizeof(u_int8_t) /* type */ +
sizeof(u_int32_t) /* key */ +
@@ -842,27 +1014,31 @@ static int ndpi_serialize_uint32_binary(ndpi_serializer *_serializer,
needed += 24 + slen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "\"%u\":", key);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += ndpi_json_string_escape(value, slen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "\"%u\":", key);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+ serializer->status.buffer.size_used += ndpi_json_string_escape(value, slen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%s", (serializer->status.size_used > 0) ? serializer->csv_separator : "", value);
+ if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%s", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "", value);
} else {
ndpi_serialization_type kt;
u_int8_t type = 0;
- u_int32_t type_offset = serializer->status.size_used++;
+ u_int32_t type_offset = serializer->status.buffer.size_used++;
kt = ndpi_serialize_key_uint32(serializer, key);
type = (kt << 4);
@@ -870,7 +1046,7 @@ static int ndpi_serialize_uint32_binary(ndpi_serializer *_serializer,
ndpi_serialize_single_string(serializer, value, slen);
type |= ndpi_serialization_string;
- serializer->buffer[type_offset] = type;
+ serializer->buffer.data[type_offset] = type;
}
serializer->status.flags |= NDPI_SERIALIZER_STATUS_NOT_EMPTY;
@@ -890,7 +1066,7 @@ int ndpi_serialize_uint32_string(ndpi_serializer *_serializer,
int ndpi_serialize_uint32_boolean(ndpi_serializer *_serializer,
u_int32_t key, u_int8_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed = 24;
if(serializer->fmt != ndpi_serialization_format_json &&
@@ -898,19 +1074,30 @@ int ndpi_serialize_uint32_boolean(ndpi_serializer *_serializer,
return -1;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "\"%u\":%s", key, value ? "true" : "false");
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "\"%u\":", key);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "%s", value ? "true" : "false");
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%s", (serializer->status.size_used > 0) ? serializer->csv_separator : "",
+ if (ndpi_serializer_header_uint32(serializer, key) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%s", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "",
value ? "true" : "false");
}
@@ -924,7 +1111,7 @@ static int ndpi_serialize_binary_int32(ndpi_serializer *_serializer,
const char *key, u_int16_t klen,
int32_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed;
if(ndpi_is_number(key, klen))
@@ -940,33 +1127,42 @@ static int ndpi_serialize_binary_int32(ndpi_serializer *_serializer,
needed += 16 + klen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- ":%d", value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ":");
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%d", value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%d", (serializer->status.size_used > 0) ? serializer->csv_separator : "", value);
+ if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%d", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "", value);
} else {
if(value <= 127 && value >= -128) {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int8;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int8;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint8(serializer, value);
} else if(value <= 32767 && value >= -32768) {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int16;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int16;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint16(serializer, value);
} else {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int32;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int32;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint32(serializer, value);
}
@@ -990,7 +1186,7 @@ int ndpi_serialize_binary_int64(ndpi_serializer *_serializer,
const char *key, u_int16_t klen,
int64_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed;
if(ndpi_is_number(key, klen))
@@ -1006,28 +1202,39 @@ int ndpi_serialize_binary_int64(ndpi_serializer *_serializer,
needed += 16 + klen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- ":%lld", (long long int)value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ ":");
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%lld", (long long int)value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%lld", (serializer->status.size_used > 0) ? serializer->csv_separator : "",
+ if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%lld", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "",
(long long int)value);
} else {
if ((value & 0xFFFFFFFF) == value) {
return(ndpi_serialize_string_int32(_serializer, key, value));
} else {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int64;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_int64;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint32(serializer, value);
}
@@ -1049,7 +1256,7 @@ int ndpi_serialize_string_int64(ndpi_serializer *_serializer,
static int ndpi_serialize_binary_uint32(ndpi_serializer *_serializer,
const char *key, u_int16_t klen, u_int32_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed;
if(ndpi_is_number(key, klen))
@@ -1065,33 +1272,45 @@ static int ndpi_serialize_binary_uint32(ndpi_serializer *_serializer,
needed += 16 + klen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- ":%u", value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, ":");
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used],
+ buff_diff, "%u", value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%u", (serializer->status.size_used > 0) ? serializer->csv_separator : "", value);
+ if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%u", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "", value);
} else {
if(value <= 0xff) {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint8;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint8;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint8(serializer, value);
} else if(value <= 0xffff) {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint16;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint16;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint16(serializer, value);
} else {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint32;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint32;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint32(serializer, value);
}
@@ -1136,7 +1355,7 @@ static int ndpi_serialize_binary_uint64(ndpi_serializer *_serializer,
const char *key, u_int16_t klen,
u_int64_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed;
if(ndpi_is_number(key, klen))
@@ -1152,28 +1371,39 @@ static int ndpi_serialize_binary_uint64(ndpi_serializer *_serializer,
needed += 32 + klen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- ":%llu", (unsigned long long)value);
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ ":");
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%llu", (unsigned long long)value);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
- "%s%llu", (serializer->status.size_used > 0) ? serializer->csv_separator : "",
+ if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
+ "%s%llu", (serializer->status.buffer.size_used > 0) ? serializer->csv_separator : "",
(unsigned long long)value);
} else {
if(value <= 0xffffffff) {
return(ndpi_serialize_string_uint32(_serializer, key, value));
} else {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint64;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_uint64;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_uint64(serializer, value);
}
@@ -1198,7 +1428,7 @@ static int ndpi_serialize_binary_float(ndpi_serializer *_serializer,
float value,
const char *format /* e.f. "%.2f" */) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed;
if(ndpi_is_number(key, klen))
@@ -1214,30 +1444,32 @@ static int ndpi_serialize_binary_float(ndpi_serializer *_serializer,
needed += 32 + klen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->buffer[serializer->status.size_used] = ':';
- serializer->status.size_used++;
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->buffer.data[serializer->status.buffer.size_used] = ':';
+ serializer->status.buffer.size_used++;
+ }
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, format, value);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- if(serializer->status.size_used > 0)
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, "%s", serializer->csv_separator);
-
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, format, value);
+ if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
+ if(serializer->status.buffer.size_used > 0)
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%s", serializer->csv_separator);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, format, value);
} else {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_float;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_float;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_float(serializer, value);
@@ -1266,7 +1498,7 @@ static int ndpi_serialize_binary_raw(ndpi_serializer *_serializer,
u_int16_t vlen,
u_int8_t escape) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed;
needed =
@@ -1280,32 +1512,37 @@ static int ndpi_serialize_binary_raw(ndpi_serializer *_serializer,
needed += 16 + klen + vlen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, ":");
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ":");
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
if (escape)
- serializer->status.size_used += ndpi_json_string_escape(value, vlen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
+ serializer->status.buffer.size_used += ndpi_json_string_escape(value, vlen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
else
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
value, vlen);
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
+ if (ndpi_serializer_header_string(serializer, key, klen) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
"%s%s", ndpi_serialize_is_not_empty(_serializer) ? serializer->csv_separator : "",
value);
} else {
- serializer->buffer[serializer->status.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_string;
+ serializer->buffer.data[serializer->status.buffer.size_used++] = (ndpi_serialization_string << 4) | ndpi_serialization_string;
ndpi_serialize_single_string(serializer, key, klen);
ndpi_serialize_single_string(serializer, value, vlen);
@@ -1362,7 +1599,7 @@ int ndpi_serialize_string_raw(ndpi_serializer *_serializer,
int ndpi_serialize_string_boolean(ndpi_serializer *_serializer,
const char *key, u_int8_t value) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int16_t klen = strlen(key);
u_int32_t needed;
@@ -1376,21 +1613,31 @@ int ndpi_serialize_string_boolean(ndpi_serializer *_serializer,
needed = klen + 16;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->fmt == ndpi_serialization_format_json) {
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, ":%s",
+
+ if (!(serializer->status.flags & NDPI_SERIALIZER_STATUS_LIST)) {
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ":");
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ serializer->status.buffer.size_used += snprintf((char *)
+ &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, "%s",
value ? "true" : "false");
+
ndpi_serialize_json_post(_serializer);
} else if(serializer->fmt == ndpi_serialization_format_csv) {
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff,
+ if (ndpi_serializer_header_string(serializer, key, strlen(key)) < 0) return(-1);
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff,
"%s%s", ndpi_serialize_is_not_empty(_serializer) ? serializer->csv_separator : "",
value ? "true" : "false");
}
@@ -1401,11 +1648,63 @@ int ndpi_serialize_string_boolean(ndpi_serializer *_serializer,
/* ********************************** */
+/* Serialize start of simple list (JSON only)*/
+int ndpi_serialize_start_of_list(ndpi_serializer *_serializer,
+ const char *key) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ u_int32_t needed, klen = strlen(key);
+
+ if(serializer->fmt != ndpi_serialization_format_json)
+ return(-1);
+
+ needed = 16 + klen;
+
+ if(buff_diff < needed) {
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ }
+
+ ndpi_serialize_json_pre(_serializer);
+
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ": [");
+
+ serializer->status.flags |= NDPI_SERIALIZER_STATUS_LIST | NDPI_SERIALIZER_STATUS_SOL;
+
+ ndpi_serialize_json_post(_serializer);
+
+ return(0);
+}
+
+/* ********************************** */
+
+/* Serialize start of simple list (JSON only)*/
+int ndpi_serialize_end_of_list(ndpi_serializer *_serializer) {
+ ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
+
+ if(serializer->fmt != ndpi_serialization_format_json)
+ return(-1);
+
+ if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOL) /* Empty list */
+ serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOL;
+
+ serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_LIST;
+
+ return(0);
+}
+
+/* ********************************** */
+
/* Serialize start of nested block (JSON only)*/
int ndpi_serialize_start_of_block(ndpi_serializer *_serializer,
const char *key) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed, klen = strlen(key);
if(serializer->fmt != ndpi_serialization_format_json)
@@ -1414,17 +1713,17 @@ int ndpi_serialize_start_of_block(ndpi_serializer *_serializer,
needed = 16 + klen;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
ndpi_serialize_json_pre(_serializer);
- serializer->status.size_used += ndpi_json_string_escape(key, klen,
- (char *) &serializer->buffer[serializer->status.size_used], buff_diff);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
- serializer->status.size_used += snprintf((char *) &serializer->buffer[serializer->status.size_used], buff_diff, ": {");
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ serializer->status.buffer.size_used += ndpi_json_string_escape(key, klen,
+ (char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff);
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
+ serializer->status.buffer.size_used += snprintf((char *) &serializer->buffer.data[serializer->status.buffer.size_used], buff_diff, ": {");
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
ndpi_serialize_json_post(_serializer);
serializer->status.flags |= NDPI_SERIALIZER_STATUS_SOB;
@@ -1434,10 +1733,10 @@ int ndpi_serialize_start_of_block(ndpi_serializer *_serializer,
/* ********************************** */
-/* Serialize start of nested block (JSON only)*/
+/* Serialize end of nested block (JSON only)*/
int ndpi_serialize_end_of_block(ndpi_serializer *_serializer) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
u_int32_t needed;
if(serializer->fmt != ndpi_serialization_format_json)
@@ -1446,15 +1745,15 @@ int ndpi_serialize_end_of_block(ndpi_serializer *_serializer) {
needed = 4;
if(buff_diff < needed) {
- if(ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, needed - buff_diff) < 0)
return(-1);
- buff_diff = serializer->buffer_size - serializer->status.size_used;
+ buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
if(serializer->status.flags & NDPI_SERIALIZER_STATUS_SOB) /* Empty block */
serializer->status.flags &= ~NDPI_SERIALIZER_STATUS_SOB;
- // buff_diff = serializer->buffer_size - serializer->status.size_used;
+ // buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
ndpi_serialize_json_post(_serializer);
return(0);
@@ -1488,10 +1787,10 @@ void ndpi_serializer_rollback_snapshot(ndpi_serializer *_serializer) {
if(serializer->fmt == ndpi_serialization_format_json) {
if(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY) {
- serializer->buffer[serializer->status.size_used-1] = ']';
+ serializer->buffer.data[serializer->status.buffer.size_used-1] = ']';
} else {
- serializer->buffer[0] = ' ';
- serializer->buffer[serializer->status.size_used-1] = '}';
+ serializer->buffer.data[0] = ' ';
+ serializer->buffer.data[serializer->status.buffer.size_used-1] = '}';
}
}
}
@@ -1508,13 +1807,13 @@ int ndpi_init_deserializer_buf(ndpi_deserializer *_deserializer,
if(serialized_buffer_len < (2 * sizeof(u_int8_t)))
return(-1);
- deserializer->buffer = serialized_buffer;
+ deserializer->buffer.data = serialized_buffer;
- if(deserializer->buffer[0] != 1)
+ if(deserializer->buffer.data[0] != 1)
return(-2); /* Invalid version */
- deserializer->buffer_size = serialized_buffer_len;
- deserializer->fmt = deserializer->buffer[1];
+ deserializer->buffer.size = serialized_buffer_len;
+ deserializer->fmt = deserializer->buffer.data[1];
ndpi_reset_serializer(_deserializer);
return(0);
@@ -1527,8 +1826,8 @@ int ndpi_init_deserializer(ndpi_deserializer *deserializer,
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
return(ndpi_init_deserializer_buf(deserializer,
- serializer->buffer,
- serializer->status.size_used));
+ serializer->buffer.data,
+ serializer->status.buffer.size_used));
}
/* ********************************** */
@@ -1543,10 +1842,10 @@ ndpi_serialization_format ndpi_deserialize_get_format(ndpi_deserializer *_deseri
static inline ndpi_serialization_type ndpi_deserialize_get_key_subtype(ndpi_private_deserializer *deserializer) {
u_int8_t type;
- if(deserializer->status.size_used >= deserializer->buffer_size)
+ if(deserializer->status.buffer.size_used >= deserializer->buffer.size)
return(ndpi_serialization_unknown);
- type = deserializer->buffer[deserializer->status.size_used];
+ type = deserializer->buffer.data[deserializer->status.buffer.size_used];
return((ndpi_serialization_type) (type >> 4));
}
@@ -1556,10 +1855,10 @@ static inline ndpi_serialization_type ndpi_deserialize_get_key_subtype(ndpi_priv
static inline ndpi_serialization_type ndpi_deserialize_get_value_subtype(ndpi_private_deserializer *deserializer) {
u_int8_t type;
- if(deserializer->status.size_used >= deserializer->buffer_size)
+ if(deserializer->status.buffer.size_used >= deserializer->buffer.size)
return(ndpi_serialization_unknown);
- type = deserializer->buffer[deserializer->status.size_used];
+ type = deserializer->buffer.data[deserializer->status.buffer.size_used];
return(ndpi_serialization_type) (type & 0xf);
}
@@ -1605,13 +1904,13 @@ ndpi_serialization_type ndpi_deserialize_get_item_type(ndpi_deserializer *_deser
/* ********************************** */
static inline int ndpi_deserialize_get_single_string_size(ndpi_private_deserializer *deserializer, u_int32_t offset) {
- u_int32_t buff_diff = deserializer->buffer_size - offset;
+ u_int32_t buff_diff = deserializer->buffer.size - offset;
u_int16_t expected, str_len;
expected = sizeof(u_int16_t) /* len */;
if(buff_diff < expected) return(-2);
- str_len = ntohs(*((u_int16_t *) &deserializer->buffer[offset]));
+ str_len = ntohs(*((u_int16_t *) &deserializer->buffer.data[offset]));
expected += str_len;
if(buff_diff < expected) return(-2);
@@ -1663,7 +1962,7 @@ static inline int ndpi_deserialize_get_single_size(ndpi_private_deserializer *de
int ndpi_deserialize_next(ndpi_deserializer *_deserializer) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer *) _deserializer;
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
ndpi_serialization_type kt, et;
u_int16_t expected;
int size;
@@ -1673,20 +1972,20 @@ int ndpi_deserialize_next(ndpi_deserializer *_deserializer) {
if(buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
- deserializer->status.size_used += expected;
+ deserializer->status.buffer.size_used += expected;
return(0);
}
@@ -1696,7 +1995,7 @@ int ndpi_deserialize_next(ndpi_deserializer *_deserializer) {
int ndpi_deserialize_key_uint32(ndpi_deserializer *_deserializer,
u_int32_t *key) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
- u_int32_t offset, buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t offset, buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
ndpi_serialization_type kt;
u_int16_t expected;
u_int16_t v16;
@@ -1708,10 +2007,10 @@ int ndpi_deserialize_key_uint32(ndpi_deserializer *_deserializer,
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
- offset = deserializer->status.size_used + expected;
+ offset = deserializer->status.buffer.size_used + expected;
switch(kt) {
case ndpi_serialization_uint32:
@@ -1739,7 +2038,7 @@ int ndpi_deserialize_key_string(ndpi_deserializer *_deserializer,
ndpi_string *key) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
ndpi_serialization_type kt;
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
u_int16_t expected;
int size;
@@ -1748,10 +2047,10 @@ int ndpi_deserialize_key_string(ndpi_deserializer *_deserializer,
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
- ndpi_deserialize_single_string(deserializer, deserializer->status.size_used + expected, key);
+ ndpi_deserialize_single_string(deserializer, deserializer->status.buffer.size_used + expected, key);
return(0);
}
@@ -1762,7 +2061,7 @@ int ndpi_deserialize_value_uint32(ndpi_deserializer *_deserializer,
u_int32_t *value) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
ndpi_serialization_type kt, et;
- u_int32_t offset, buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t offset, buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
u_int16_t v16;
u_int8_t v8;
u_int16_t expected;
@@ -1772,16 +2071,16 @@ int ndpi_deserialize_value_uint32(ndpi_deserializer *_deserializer,
if(buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
- offset = deserializer->status.size_used + expected;
+ offset = deserializer->status.buffer.size_used + expected;
switch(et) {
case ndpi_serialization_uint32:
@@ -1808,7 +2107,7 @@ int ndpi_deserialize_value_uint64(ndpi_deserializer *_deserializer,
u_int64_t *value) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
ndpi_serialization_type kt, et;
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
u_int32_t v32;
u_int16_t expected;
int size;
@@ -1818,13 +2117,13 @@ int ndpi_deserialize_value_uint64(ndpi_deserializer *_deserializer,
if(buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
if(et != ndpi_serialization_uint64) {
@@ -1834,7 +2133,7 @@ int ndpi_deserialize_value_uint64(ndpi_deserializer *_deserializer,
return(rc);
}
- ndpi_deserialize_single_uint64(deserializer, deserializer->status.size_used + expected, value);
+ ndpi_deserialize_single_uint64(deserializer, deserializer->status.buffer.size_used + expected, value);
return(0);
}
@@ -1845,7 +2144,7 @@ int ndpi_deserialize_value_int32(ndpi_deserializer *_deserializer,
int32_t *value) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
ndpi_serialization_type kt, et;
- u_int32_t offset, buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t offset, buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
int16_t v16;
int8_t v8;
u_int16_t expected;
@@ -1855,16 +2154,16 @@ int ndpi_deserialize_value_int32(ndpi_deserializer *_deserializer,
if(buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
- offset = deserializer->status.size_used + expected;
+ offset = deserializer->status.buffer.size_used + expected;
switch(et) {
case ndpi_serialization_int32:
@@ -1891,7 +2190,7 @@ int ndpi_deserialize_value_int64(ndpi_deserializer *_deserializer,
int64_t *value) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
ndpi_serialization_type kt, et;
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
int32_t v32;
u_int16_t expected;
int size;
@@ -1901,13 +2200,13 @@ int ndpi_deserialize_value_int64(ndpi_deserializer *_deserializer,
if(buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
if(et != ndpi_serialization_int64) {
@@ -1917,7 +2216,7 @@ int ndpi_deserialize_value_int64(ndpi_deserializer *_deserializer,
return(rc);
}
- ndpi_deserialize_single_int64(deserializer, deserializer->status.size_used + expected, value);
+ ndpi_deserialize_single_int64(deserializer, deserializer->status.buffer.size_used + expected, value);
return(0);
}
@@ -1928,7 +2227,7 @@ int ndpi_deserialize_value_float(ndpi_deserializer *_deserializer,
float *value) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
ndpi_serialization_type kt, et;
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
u_int16_t expected;
int size;
@@ -1936,19 +2235,19 @@ int ndpi_deserialize_value_float(ndpi_deserializer *_deserializer,
if(buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
if(et != ndpi_serialization_float)
return(-1);
- ndpi_deserialize_single_float(deserializer, deserializer->status.size_used + expected, value);
+ ndpi_deserialize_single_float(deserializer, deserializer->status.buffer.size_used + expected, value);
return(0);
}
@@ -1959,7 +2258,7 @@ int ndpi_deserialize_value_string(ndpi_deserializer *_deserializer,
ndpi_string *value) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer*)_deserializer;
ndpi_serialization_type kt, et;
- u_int32_t buff_diff = deserializer->buffer_size - deserializer->status.size_used;
+ u_int32_t buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
u_int16_t expected;
int size;
@@ -1967,19 +2266,19 @@ int ndpi_deserialize_value_string(ndpi_deserializer *_deserializer,
if(buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
if(et != ndpi_serialization_string)
return(-1);
- ndpi_deserialize_single_string(deserializer, deserializer->status.size_used + expected, value);
+ ndpi_deserialize_single_string(deserializer, deserializer->status.buffer.size_used + expected, value);
return(0);
}
@@ -1990,8 +2289,8 @@ int ndpi_deserialize_value_string(ndpi_deserializer *_deserializer,
int ndpi_deserialize_clone_item(ndpi_deserializer *_deserializer, ndpi_serializer *_serializer) {
ndpi_private_deserializer *deserializer = (ndpi_private_deserializer *) _deserializer;
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
- u_int32_t src_buff_diff = deserializer->buffer_size - deserializer->status.size_used;
- u_int32_t dst_buff_diff = serializer->buffer_size - serializer->status.size_used;
+ u_int32_t src_buff_diff = deserializer->buffer.size - deserializer->status.buffer.size_used;
+ u_int32_t dst_buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
ndpi_serialization_type kt, et;
u_int16_t expected;
int size;
@@ -2004,30 +2303,30 @@ int ndpi_deserialize_clone_item(ndpi_deserializer *_deserializer, ndpi_serialize
if(src_buff_diff < expected) return(-2);
kt = ndpi_deserialize_get_key_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, kt, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
et = ndpi_deserialize_get_value_subtype(deserializer);
- size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.size_used + expected);
+ size = ndpi_deserialize_get_single_size(deserializer, et, deserializer->status.buffer.size_used + expected);
if(size < 0) return(-2);
expected += size;
if(dst_buff_diff < expected) {
- if(ndpi_extend_serializer_buffer(_serializer, expected - dst_buff_diff) < 0)
+ if(ndpi_extend_serializer_buffer(&serializer->buffer, expected - dst_buff_diff) < 0)
return(-1);
- dst_buff_diff = serializer->buffer_size - serializer->status.size_used;
+ dst_buff_diff = serializer->buffer.size - serializer->status.buffer.size_used;
}
- memcpy(&serializer->buffer[serializer->status.size_used],
- &deserializer->buffer[deserializer->status.size_used],
+ memcpy(&serializer->buffer.data[serializer->status.buffer.size_used],
+ &deserializer->buffer.data[deserializer->status.buffer.size_used],
expected);
- serializer->status.size_used += expected;
+ serializer->status.buffer.size_used += expected;
return(0);
}
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index 4a30b1954..00fb47dad 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -902,63 +902,44 @@ char* ndpi_base64_encode(unsigned char const* bytes_to_encode, size_t in_len) {
}
/* ********************************** */
-/* ********************************** */
-int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct,
- struct ndpi_flow_struct *flow,
- u_int8_t ip_version,
- u_int8_t l4_protocol, u_int16_t vlan_id,
- u_int32_t src_v4, u_int32_t dst_v4,
- struct ndpi_in6_addr *src_v6, struct ndpi_in6_addr *dst_v6,
- u_int16_t src_port, u_int16_t dst_port,
- ndpi_protocol l7_protocol,
- ndpi_serializer *serializer) {
- char buf[64], src_name[32], dst_name[32];
-
- if(ndpi_init_serializer(serializer, ndpi_serialization_format_json) == -1)
- return(-1);
+void ndpi_serialize_risk(ndpi_serializer *serializer,
+ struct ndpi_flow_struct *flow) {
+ if(flow->risk != 0) {
+ u_int32_t i;
- if(ip_version == 4) {
- inet_ntop(AF_INET, &src_v4, src_name, sizeof(src_name));
- inet_ntop(AF_INET, &dst_v4, dst_name, sizeof(dst_name));
- } else {
- inet_ntop(AF_INET6, src_v6, src_name, sizeof(src_name));
- inet_ntop(AF_INET6, dst_v6, dst_name, sizeof(dst_name));
- /* For consistency across platforms replace :0: with :: */
- ndpi_patchIPv6Address(src_name), ndpi_patchIPv6Address(dst_name);
+ ndpi_serialize_start_of_block(serializer, "flow_risk");
+
+ for(i = 0; i < NDPI_MAX_RISK; i++) {
+ ndpi_risk_enum r = (ndpi_risk_enum)i;
+
+ if(NDPI_ISSET_BIT(flow->risk, r))
+ ndpi_serialize_uint32_string(serializer, i, ndpi_risk2str(r));
+ }
+
+ ndpi_serialize_end_of_block(serializer);
}
+}
- ndpi_serialize_string_string(serializer, "src_ip", src_name);
- ndpi_serialize_string_string(serializer, "dest_ip", dst_name);
- if(src_port) ndpi_serialize_string_uint32(serializer, "src_port", src_port);
- if(dst_port) ndpi_serialize_string_uint32(serializer, "dst_port", dst_port);
-
- switch(l4_protocol) {
- case IPPROTO_TCP:
- ndpi_serialize_string_string(serializer, "proto", "TCP");
- break;
-
- case IPPROTO_UDP:
- ndpi_serialize_string_string(serializer, "proto", "UDP");
- break;
-
- case IPPROTO_ICMP:
- ndpi_serialize_string_string(serializer, "proto", "ICMP");
- break;
+/* ********************************** */
+/* ********************************** */
- default:
- ndpi_serialize_string_uint32(serializer, "proto", l4_protocol);
- break;
- }
+/* NOTE: serializer must have been already initialized */
+int ndpi_dpi2json(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ ndpi_protocol l7_protocol,
+ ndpi_serializer *serializer) {
+ char buf[64];
+ if(flow == NULL) return(-1);
+
ndpi_serialize_start_of_block(serializer, "ndpi");
+ ndpi_serialize_risk(serializer, flow);
ndpi_serialize_string_string(serializer, "proto", ndpi_protocol2name(ndpi_struct, l7_protocol, buf, sizeof(buf)));
if(l7_protocol.category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)
ndpi_serialize_string_string(serializer, "category", ndpi_category_get_name(ndpi_struct, l7_protocol.category));
ndpi_serialize_end_of_block(serializer);
- if(flow == NULL) return(0);
-
switch(l7_protocol.master_protocol ? l7_protocol.master_protocol : l7_protocol.app_protocol) {
case NDPI_PROTOCOL_DHCP:
ndpi_serialize_start_of_block(serializer, "dhcp");
@@ -1148,6 +1129,59 @@ int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct,
/* ********************************** */
+/* NOTE: serializer is initialized by the function */
+int ndpi_flow2json(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ u_int8_t ip_version,
+ u_int8_t l4_protocol, u_int16_t vlan_id,
+ u_int32_t src_v4, u_int32_t dst_v4,
+ struct ndpi_in6_addr *src_v6, struct ndpi_in6_addr *dst_v6,
+ u_int16_t src_port, u_int16_t dst_port,
+ ndpi_protocol l7_protocol,
+ ndpi_serializer *serializer) {
+ char src_name[32], dst_name[32];
+
+ if(ndpi_init_serializer(serializer, ndpi_serialization_format_json) == -1)
+ return(-1);
+
+ if(ip_version == 4) {
+ inet_ntop(AF_INET, &src_v4, src_name, sizeof(src_name));
+ inet_ntop(AF_INET, &dst_v4, dst_name, sizeof(dst_name));
+ } else {
+ inet_ntop(AF_INET6, src_v6, src_name, sizeof(src_name));
+ inet_ntop(AF_INET6, dst_v6, dst_name, sizeof(dst_name));
+ /* For consistency across platforms replace :0: with :: */
+ ndpi_patchIPv6Address(src_name), ndpi_patchIPv6Address(dst_name);
+ }
+
+ ndpi_serialize_string_string(serializer, "src_ip", src_name);
+ ndpi_serialize_string_string(serializer, "dest_ip", dst_name);
+ if(src_port) ndpi_serialize_string_uint32(serializer, "src_port", src_port);
+ if(dst_port) ndpi_serialize_string_uint32(serializer, "dst_port", dst_port);
+
+ switch(l4_protocol) {
+ case IPPROTO_TCP:
+ ndpi_serialize_string_string(serializer, "proto", "TCP");
+ break;
+
+ case IPPROTO_UDP:
+ ndpi_serialize_string_string(serializer, "proto", "UDP");
+ break;
+
+ case IPPROTO_ICMP:
+ ndpi_serialize_string_string(serializer, "proto", "ICMP");
+ break;
+
+ default:
+ ndpi_serialize_string_uint32(serializer, "proto", l4_protocol);
+ break;
+ }
+
+ return(ndpi_dpi2json(ndpi_struct, flow, l7_protocol, serializer));
+}
+
+/* ********************************** */
+
const char* ndpi_tunnel2str(ndpi_packet_tunnel tt) {
switch(tt) {
case ndpi_no_tunnel:
@@ -1457,6 +1491,9 @@ const char* ndpi_risk2str(ndpi_risk_enum risk) {
case NDPI_HTTP_SUSPICIOUS_URL:
return("HTTP Suspicious URL");
+
+ case NDPI_HTTP_SUSPICIOUS_HEADER:
+ return("HTTP Suspicious Header");
default:
snprintf(buf, sizeof(buf), "%d", (int)risk);
diff --git a/src/lib/protocols/bittorrent.c b/src/lib/protocols/bittorrent.c
index f1c62d431..9f7620558 100644
--- a/src/lib/protocols/bittorrent.c
+++ b/src/lib/protocols/bittorrent.c
@@ -43,7 +43,7 @@ struct ndpi_utp_hdr {
u_int16_t sequence_nr, ack_nr;
};
-static u_int8_t is_utp_pkt(const u_int8_t *payload, u_int payload_len) {
+static u_int8_t is_utpv1_pkt(const u_int8_t *payload, u_int payload_len) {
struct ndpi_utp_hdr *h = (struct ndpi_utp_hdr*)payload;
if(payload_len < sizeof(struct ndpi_utp_hdr)) return(0);
@@ -52,6 +52,9 @@ static u_int8_t is_utp_pkt(const u_int8_t *payload, u_int payload_len) {
if(h->next_extension > 2) return(0);
if(ntohl(h->window_size) > 65565) return(0);
+ if((h->window_size == 0) && (payload_len != sizeof(struct ndpi_utp_hdr)))
+ return(0);
+
return(1);
}
@@ -433,14 +436,10 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st
u_int8_t v0_extension = packet->payload[17];
u_int8_t v0_flags = packet->payload[18];
- /* Check if this is protocol v1 */
- u_int8_t v1_version = packet->payload[0];
- u_int8_t v1_extension = packet->payload[1];
- u_int32_t v1_window_size = *((u_int32_t*)&packet->payload[12]);
-
- if(is_utp_pkt(packet->payload, packet->payload_packet_len))
+ if(is_utpv1_pkt(packet->payload, packet->payload_packet_len)) {
+ bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20);
goto bittorrent_found;
- else if((packet->payload[0]== 0x60)
+ } else if((packet->payload[0]== 0x60)
&& (packet->payload[1]== 0x0)
&& (packet->payload[2]== 0x0)
&& (packet->payload[3]== 0x0)
@@ -448,14 +447,7 @@ void ndpi_search_bittorrent(struct ndpi_detection_module_struct *ndpi_struct, st
/* Heuristic */
bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20);
goto bittorrent_found;
- /* CSGO/DOTA conflict */
- } else if(flow->packet_counter > 8 && ((v1_version & 0x0f) == 1)
- && ((v1_version >> 4) < 5 /* ST_NUM_STATES */)
- && (v1_extension < 3 /* EXT_NUM_EXT */)
- && (v1_window_size < 32768 /* 32k */)
- ) {
- bt_proto = ndpi_strnstr((const char *)&packet->payload[20], "BitTorrent protocol", packet->payload_packet_len-20);
- goto bittorrent_found;
+ /* CSGO/DOTA conflict */
} else if((v0_flags < 6 /* ST_NUM_STATES */) && (v0_extension < 3 /* EXT_NUM_EXT */)) {
u_int32_t ts = ntohl(*((u_int32_t*)&(packet->payload[4])));
u_int32_t now;
diff --git a/src/lib/protocols/http.c b/src/lib/protocols/http.c
index abd422007..7b83b91e7 100644
--- a/src/lib/protocols/http.c
+++ b/src/lib/protocols/http.c
@@ -28,20 +28,16 @@
#include "ndpi_api.h"
#include <stdlib.h>
-static const char* binary_file_mimes[] = {
- "exe",
- "vnd.ms-cab-compressed",
- "vnd.microsoft.portable-executable"
- "x-msdownload",
- "x-dosexec",
- NULL
-};
+static const char* binary_file_mimes_e[] = { "exe", NULL };
+static const char* binary_file_mimes_v[] = { "vnd.ms-cab-compressed", "vnd.microsoft.portable-executable", NULL };
+static const char* binary_file_mimes_x[] = { "x-msdownload", "x-dosexec", NULL };
+#define ATTACHMENT_LEN 3
static const char* binary_file_ext[] = {
- ".exe",
- ".msi",
- ".cab",
- NULL
+ "exe",
+ "msi",
+ "cab",
+ NULL
};
static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
@@ -49,7 +45,7 @@ static void ndpi_search_http_tcp(struct ndpi_detection_module_struct *ndpi_struc
/* *********************************************** */
-static void ndpi_analyze_content_signature(struct ndpi_flow_struct *flow) {
+static void ndpi_analyze_content_signature(struct ndpi_flow_struct *flow) {
if((flow->initial_binary_bytes_len >= 2) && (flow->initial_binary_bytes[0] == 0x4D) && (flow->initial_binary_bytes[1] == 0x5A))
NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Win executable */
else if((flow->initial_binary_bytes_len >= 4) && (flow->initial_binary_bytes[0] == 0x7F) && (flow->initial_binary_bytes[1] == 'E')
@@ -65,7 +61,7 @@ static void ndpi_analyze_content_signature(struct ndpi_flow_struct *flow) {
NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Unix script (e.g. #!/bin/sh) */
else if(flow->initial_binary_bytes_len >= 8) {
u_int8_t exec_pattern[] = { 0x64, 0x65, 0x78, 0x0A, 0x30, 0x33, 0x35, 0x00 };
-
+
if(memcmp(flow->initial_binary_bytes, exec_pattern, 8) == 0)
NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER); /* Dalvik Executable (Android) */
}
@@ -85,7 +81,7 @@ static int ndpi_search_http_tcp_again(struct ndpi_detection_module_struct *ndpi_
&& (flow->http.response_status_code != 0)
) {
/* stop extra processing */
-
+
if(flow->initial_binary_bytes_len) ndpi_analyze_content_signature(flow);
flow->extra_packets_func = NULL; /* We're good now */
return(0);
@@ -106,47 +102,69 @@ static ndpi_protocol_category_t ndpi_http_check_content(struct ndpi_detection_mo
u_int app_len = sizeof("application");
if(packet->content_line.len > app_len) {
- const char *app = (const char *)&packet->content_line.ptr[app_len];
- u_int app_len_avail = packet->content_line.len-app_len;
-
- if(ndpi_strncasestr(app, "mpeg", app_len_avail) != NULL) {
+ const char *app = (const char *)&packet->content_line.ptr[app_len];
+ u_int app_len_avail = packet->content_line.len-app_len;
+
+ if(strncasecmp(app, "mpeg", app_len_avail) == 0) {
flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_STREAMING;
return(flow->category);
- } else {
- for (int i = 0; binary_file_mimes[i] != NULL; i++) {
- if (ndpi_strncasestr(app, binary_file_mimes[i], app_len_avail) != NULL) {
- flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
- NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
- NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
- return(flow->category);
- }
- }
+ } else if(app_len_avail > 3) {
+ const char** cmp_mimes = NULL;
+
+ switch(app[0]) {
+ case 'e': cmp_mimes = binary_file_mimes_e; break;
+ case 'v': cmp_mimes = binary_file_mimes_v; break;
+ case 'x': cmp_mimes = binary_file_mimes_x; break;
+ }
+
+ if(cmp_mimes != NULL) {
+ u_int8_t i;
+
+ for(i = 0; cmp_mimes[i] != NULL; i++) {
+ if(strncasecmp(app, cmp_mimes[i], app_len_avail) == 0) {
+ flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
+ NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
+ NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
+ return(flow->category);
+ }
+ }
+ }
}
}
/* check for attachment */
- if (packet->content_disposition_line.len > 0) {
- uint8_t attachment_len = sizeof("attachment; filename");
- if (packet->content_disposition_line.len > attachment_len) {
- uint8_t filename_len = packet->content_disposition_line.len - attachment_len;
- for (int i = 0; binary_file_ext[i] != NULL; i++) {
- if (ndpi_strncasestr((const char*)&packet->content_disposition_line.ptr[attachment_len],
- binary_file_ext[i], filename_len)) {
- flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
- NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
- NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
- return(flow->category);
- }
+ if (packet->content_disposition_line.len > 0) {
+ u_int8_t attachment_len = sizeof("attachment; filename");
+
+ if(packet->content_disposition_line.len > attachment_len) {
+ u_int8_t filename_len = packet->content_disposition_line.len - attachment_len;
+
+ if(filename_len > ATTACHMENT_LEN) {
+ attachment_len += filename_len-ATTACHMENT_LEN-1;
+
+ if((attachment_len+ATTACHMENT_LEN) <= packet->content_disposition_line.len) {
+ for(int i = 0; binary_file_ext[i] != NULL; i++) {
+ /* Use memcmp in case content-disposition contains binary data */
+ if(memcmp((const char*)&packet->content_disposition_line.ptr[attachment_len],
+ binary_file_ext[i], ATTACHMENT_LEN) == 0) {
+ flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT;
+ NDPI_SET_BIT(flow->risk, NDPI_BINARY_APPLICATION_TRANSFER);
+ NDPI_LOG_INFO(ndpi_struct, "found executable HTTP transfer");
+ return(flow->category);
+ }
+ }
+ }
+ }
}
}
- }
+
switch(packet->content_line.ptr[0]) {
case 'a':
if(strncasecmp((const char *)packet->content_line.ptr, "audio",
ndpi_min(packet->content_line.len, 5)) == 0)
flow->guessed_category = flow->category = NDPI_PROTOCOL_CATEGORY_MEDIA;
break;
-
+
case 'v':
if(strncasecmp((const char *)packet->content_line.ptr, "video",
ndpi_min(packet->content_line.len, 5)) == 0)
@@ -178,7 +196,6 @@ static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *nd
if((flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) || (http_protocol != NDPI_PROTOCOL_HTTP))
flow->guessed_host_protocol_id = http_protocol;
- category = ndpi_http_check_content(ndpi_struct, flow);
ndpi_int_reset_protocol(flow);
ndpi_set_detected_protocol(ndpi_struct, flow, flow->guessed_host_protocol_id, NDPI_PROTOCOL_HTTP);
@@ -186,7 +203,7 @@ static void ndpi_int_http_add_connection(struct ndpi_detection_module_struct *nd
flow->check_extra_packets = 1;
flow->max_extra_packets_to_check = 5;
flow->extra_packets_func = ndpi_search_http_tcp_again;
- flow->http_detected = 1, flow->guessed_category = flow->category = category;
+ flow->http_detected = 1;
}
/* ************************************************************* */
@@ -220,7 +237,7 @@ static void setHttpUserAgent(struct ndpi_detection_module_struct *ndpi_struct,
* https://github.com/ua-parser/uap-core/blob/master/regexes.yaml */
snprintf((char*)flow->protos.http.detected_os,
- sizeof(flow->protos.http.detected_os), "%s", ua);
+ sizeof(flow->protos.http.detected_os), "%s", ua);
}
/* ************************************************************* */
@@ -232,7 +249,7 @@ static void ndpi_http_parse_subprotocol(struct ndpi_detection_module_struct *ndp
if(double_col) double_col[0] = '\0';
- ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HTTP,
+ ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_HTTP,
(char *)flow->host_server_name,
strlen((const char *)flow->host_server_name));
}
@@ -246,7 +263,7 @@ static void ndpi_check_user_agent(struct ndpi_detection_module_struct *ndpi_stru
if((!ua) || (ua[0] == '\0')) return;
// printf("[%s:%d] ==> '%s'\n", __FILE__, __LINE__, ua);
-
+
if((strlen(ua) < 4)
|| (!strcmp(ua, "test"))
|| (!strcmp(ua, "<?"))
@@ -262,13 +279,13 @@ static void ndpi_check_numeric_ip(struct ndpi_detection_module_struct *ndpi_stru
char *ip, u_int ip_len) {
char buf[22];
struct in_addr ip_addr;
-
+
strncpy(buf, ip, ip_len);
buf[ip_len] = '\0';
ip_addr.s_addr = inet_addr(buf);
if(strcmp(inet_ntoa(ip_addr), buf) == 0) {
- NDPI_SET_BIT(flow->risk, NDPI_HTTP_NUMERIC_IP_HOST);
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_NUMERIC_IP_HOST);
}
}
@@ -301,9 +318,9 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
int len = packet->http_url_name.len + packet->host_line.len + 1;
if(isdigit(packet->host_line.ptr[0])
- && (packet->host_line.len < 21))
+ && (packet->host_line.len < 21))
ndpi_check_numeric_ip(ndpi_struct, flow, (char*)packet->host_line.ptr, packet->host_line.len);
-
+
flow->http.url = ndpi_malloc(len);
if(flow->http.url) {
strncpy(flow->http.url, (char*)packet->host_line.ptr, packet->host_line.len);
@@ -352,7 +369,7 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
strncpy(ua, (const char *)packet->user_agent_line.ptr, mlen);
ua[mlen] = '\0';
-
+
if(strncmp(ua, "Mozilla", 7) == 0) {
char *parent = strchr(ua, '(');
@@ -517,7 +534,8 @@ static void check_content_type_and_change_protocol(struct ndpi_detection_module_
strncpy(flow->http.content_type, (char*)packet->content_line.ptr,
packet->content_line.len);
flow->http.content_type[packet->content_line.len] = '\0';
- }
+
+ flow->guessed_category = flow->category = ndpi_http_check_content(ndpi_struct, flow);}
}
if(flow->http_detected) {
@@ -595,6 +613,106 @@ static void http_bitmask_exclude_other(struct ndpi_flow_struct *flow)
NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_XBOX);
}
+/* *********************************************************************************************** */
+
+/* Trick to speed-up detection */
+static const char* suspicious_http_header_keys_A[] = { "Arch", NULL};
+static const char* suspicious_http_header_keys_C[] = { "Cores", NULL};
+static const char* suspicious_http_header_keys_M[] = { "Mem", NULL};
+static const char* suspicious_http_header_keys_O[] = { "Os", "Osname", "Osversion", NULL};
+static const char* suspicious_http_header_keys_R[] = { "Root", NULL};
+static const char* suspicious_http_header_keys_S[] = { "S", NULL};
+static const char* suspicious_http_header_keys_T[] = { "TLS_version", NULL};
+static const char* suspicious_http_header_keys_U[] = { "Uuid", NULL};
+static const char* suspicious_http_header_keys_X[] = { "X-Hire-Me", NULL};
+
+static int is_a_suspicious_header(const char* suspicious_headers[], struct ndpi_int_one_line_struct packet_line){
+ int i;
+ unsigned int header_len;
+ const u_int8_t* header_limit;
+
+ if((header_limit = memchr(packet_line.ptr, ':', packet_line.len))) {
+ header_len = header_limit - packet_line.ptr;
+ for(i=0; suspicious_headers[i] != NULL; i++){
+ if(!strncasecmp((const char*) packet_line.ptr,
+ suspicious_headers[i], header_len))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* *********************************************************************************************** */
+
+static void ndpi_check_http_header(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+ u_int32_t i;
+ struct ndpi_packet_struct *packet = &flow->packet;
+
+ for(i=0; (i < packet->parsed_lines)
+ && (packet->line[i].ptr != NULL)
+ && (packet->line[i].len > 0); i++) {
+ switch(packet->line[i].ptr[0]){
+ case 'A':
+ if(is_a_suspicious_header(suspicious_http_header_keys_A, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'C':
+ if(is_a_suspicious_header(suspicious_http_header_keys_C, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'M':
+ if(is_a_suspicious_header(suspicious_http_header_keys_M, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'O':
+ if(is_a_suspicious_header(suspicious_http_header_keys_O, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'R':
+ if(is_a_suspicious_header(suspicious_http_header_keys_R, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'S':
+ if(is_a_suspicious_header(suspicious_http_header_keys_S, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'T':
+ if(is_a_suspicious_header(suspicious_http_header_keys_T, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'U':
+ if(is_a_suspicious_header(suspicious_http_header_keys_U, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+ break;
+ case 'X':
+ if(is_a_suspicious_header(suspicious_http_header_keys_X, packet->line[i])) {
+ NDPI_SET_BIT(flow->risk, NDPI_HTTP_SUSPICIOUS_HEADER);
+ return;
+ }
+
+ break;
+ }
+ }
+}
+
/*************************************************************************************************/
static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct,
@@ -694,6 +812,7 @@ static void ndpi_check_http_tcp(struct ndpi_detection_module_struct *ndpi_struct
"Filename HTTP found: %d, we look for line info..\n", filename_start);
ndpi_parse_packet_line_info(ndpi_struct, flow);
+ ndpi_check_http_header(ndpi_struct, flow);
if(packet->parsed_lines <= 1) {
NDPI_LOG_DBG2(ndpi_struct,
diff --git a/src/lib/protocols/kerberos.c b/src/lib/protocols/kerberos.c
index ff16545f5..f4c1a175a 100644
--- a/src/lib/protocols/kerberos.c
+++ b/src/lib/protocols/kerberos.c
@@ -202,11 +202,13 @@ void ndpi_search_kerberos(struct ndpi_detection_module_struct *ndpi_struct,
if(body_offset < packet->payload_packet_len) {
- u_int16_t name_offset;
-
- name_offset = body_offset + 13;
- for(i=0; i<20; i++) if(packet->payload[name_offset] != 0x1b) name_offset++; /* ASN.1 */
-
+ u_int16_t name_offset = body_offset + 13;
+
+ for(i=0; (i<20) && (name_offset < packet->payload_packet_len); i++) {
+ if(packet->payload[name_offset] != 0x1b)
+ name_offset++; /* ASN.1 */
+ }
+
#ifdef KERBEROS_DEBUG
printf("name_offset=%u [%02X %02X] [byte 0 must be 0x1b]\n", name_offset, packet->payload[name_offset], packet->payload[name_offset+1]);
#endif
@@ -256,30 +258,38 @@ void ndpi_search_kerberos(struct ndpi_detection_module_struct *ndpi_struct,
} else
snprintf(flow->protos.kerberos.username, sizeof(flow->protos.kerberos.username), "%s", cname_str);
- for(i=0; i<14; i++) if(packet->payload[realm_offset] != 0x1b) realm_offset++; /* ASN.1 */
+ for(i=0; (i < 14) && (realm_offset < packet->payload_packet_len); i++) {
+ if(packet->payload[realm_offset] != 0x1b)
+ realm_offset++; /* ASN.1 */
+ }
+
#ifdef KERBEROS_DEBUG
- printf("realm_offset=%u [%02X %02X] [byte 0 must be 0x1b]\n", realm_offset, packet->payload[realm_offset], packet->payload[realm_offset+1]);
+ printf("realm_offset=%u [%02X %02X] [byte 0 must be 0x1b]\n", realm_offset,
+ packet->payload[realm_offset], packet->payload[realm_offset+1]);
#endif
+
realm_offset += 1;
//if(num_cname == 2) realm_offset++;
- realm_len = packet->payload[realm_offset];
+ if(realm_offset < packet->payload_packet_len) {
+ realm_len = packet->payload[realm_offset];
- if((realm_offset+realm_len) < packet->payload_packet_len) {
- char realm_str[48];
+ if((realm_offset+realm_len) < packet->payload_packet_len) {
+ char realm_str[48];
- if(realm_len > sizeof(realm_str)-1)
- realm_len = sizeof(realm_str)-1;
+ if(realm_len > sizeof(realm_str)-1)
+ realm_len = sizeof(realm_str)-1;
- realm_offset += 1;
+ realm_offset += 1;
- strncpy(realm_str, (char*)&packet->payload[realm_offset], realm_len);
- realm_str[realm_len] = '\0';
- for(i=0; i<realm_len; i++) realm_str[i] = tolower(realm_str[i]);
+ strncpy(realm_str, (char*)&packet->payload[realm_offset], realm_len);
+ realm_str[realm_len] = '\0';
+ for(i=0; i<realm_len; i++) realm_str[i] = tolower(realm_str[i]);
#ifdef KERBEROS_DEBUG
- printf("[AS-REQ][Kerberos Realm][len: %u][%s]\n", realm_len, realm_str);
+ printf("[AS-REQ][Kerberos Realm][len: %u][%s]\n", realm_len, realm_str);
#endif
- snprintf(flow->protos.kerberos.domain, sizeof(flow->protos.kerberos.domain), "%s", realm_str);
+ snprintf(flow->protos.kerberos.domain, sizeof(flow->protos.kerberos.domain), "%s", realm_str);
+ }
}
}
}
diff --git a/src/lib/protocols/spotify.c b/src/lib/protocols/spotify.c
index a180a1ea7..d66109016 100644
--- a/src/lib/protocols/spotify.c
+++ b/src/lib/protocols/spotify.c
@@ -47,7 +47,7 @@ static void ndpi_check_spotify(struct ndpi_detection_module_struct *ndpi_struct,
if((packet->udp->source == spotify_port)
&& (packet->udp->dest == spotify_port)) {
- if(payload_len > 2) {
+ if(payload_len >= 7) {
if(memcmp(packet->payload, "SpotUdp", 7) == 0) {
NDPI_LOG_INFO(ndpi_struct, "found spotify udp dissector\n");
ndpi_int_spotify_add_connection(ndpi_struct, flow, 0);
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
index fd783d099..87d090daf 100644
--- a/src/lib/protocols/stun.c
+++ b/src/lib/protocols/stun.c
@@ -161,7 +161,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
/* This looks like an invalid packet */
if(flow->protos.stun_ssl.stun.num_udp_pkts > 0) {
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
+ // flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
return(NDPI_IS_STUN);
} else
return(NDPI_IS_NOT_STUN);
diff --git a/src/lib/protocols/tls.c b/src/lib/protocols/tls.c
index 62b2e3cf8..222fa480d 100644
--- a/src/lib/protocols/tls.c
+++ b/src/lib/protocols/tls.c
@@ -34,13 +34,13 @@ extern char *strptime(const char *s, const char *format, struct tm *tm);
extern int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow);
-// #define DEBUG_TLS_MEMORY 1
-// #define DEBUG_TLS 1
-
+// #define DEBUG_TLS_MEMORY 1
+// #define DEBUG_TLS 1
// #define DEBUG_CERTIFICATE_HASH
-/* #define DEBUG_FINGERPRINT 1 */
+/* #define DEBUG_FINGERPRINT 1 */
+/* #define DEBUG_ENCRYPTED_SNI 1 */
/*
NOTE
@@ -390,77 +390,83 @@ static void processCertificateElements(struct ndpi_detection_module_struct *ndpi
i += 3 /* skip the initial patten 55 1D 11 */;
i++; /* skip the first type, 0x04 == BIT STRING, and jump to it's length */
- i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip BIT STRING length */
- i += 2; /* skip the second type, 0x30 == SEQUENCE, and jump to it's length */
- i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip SEQUENCE length */
- i++;
-
- while(i < packet->payload_packet_len) {
- if(packet->payload[i] == 0x82) {
- if((i < (packet->payload_packet_len - 1))
- && ((i + packet->payload[i + 1] + 2) < packet->payload_packet_len)) {
- u_int8_t len = packet->payload[i + 1];
- char dNSName[256];
-
- i += 2;
-
- /* The check "len > sizeof(dNSName) - 1" will be always false. If we add it,
- the compiler is smart enough to detect it and throws a warning */
- if(len == 0 /* Looks something went wrong */)
- break;
+ if(i < packet->payload_packet_len) {
+ i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip BIT STRING length */
+ if(i < packet->payload_packet_len) {
+ i += 2; /* skip the second type, 0x30 == SEQUENCE, and jump to it's length */
+ if(i < packet->payload_packet_len) {
+ i += (packet->payload[i] & 0x80) ? (packet->payload[i] & 0x7F) : 0; /* skip SEQUENCE length */
+ i++;
+
+ while(i < packet->payload_packet_len) {
+ if(packet->payload[i] == 0x82) {
+ if((i < (packet->payload_packet_len - 1))
+ && ((i + packet->payload[i + 1] + 2) < packet->payload_packet_len)) {
+ u_int8_t len = packet->payload[i + 1];
+ char dNSName[256];
+
+ i += 2;
+
+ /* The check "len > sizeof(dNSName) - 1" will be always false. If we add it,
+ the compiler is smart enough to detect it and throws a warning */
+ if(len == 0 /* Looks something went wrong */)
+ break;
- strncpy(dNSName, (const char*)&packet->payload[i], len);
- dNSName[len] = '\0';
+ strncpy(dNSName, (const char*)&packet->payload[i], len);
+ dNSName[len] = '\0';
- cleanupServerName(dNSName, len);
+ cleanupServerName(dNSName, len);
#if DEBUG_TLS
- printf("[TLS] dNSName %s [%s]\n", dNSName, flow->protos.stun_ssl.ssl.client_requested_server_name);
+ printf("[TLS] dNSName %s [%s]\n", dNSName, flow->protos.stun_ssl.ssl.client_requested_server_name);
#endif
- if(matched_name == 0) {
- if((dNSName[0] == '*') && strstr(flow->protos.stun_ssl.ssl.client_requested_server_name, &dNSName[1]))
- matched_name = 1;
- else if(strcmp(flow->protos.stun_ssl.ssl.client_requested_server_name, dNSName) == 0)
- matched_name = 1;
- }
+ if(matched_name == 0) {
+ if((dNSName[0] == '*') && strstr(flow->protos.stun_ssl.ssl.client_requested_server_name, &dNSName[1]))
+ matched_name = 1;
+ else if(strcmp(flow->protos.stun_ssl.ssl.client_requested_server_name, dNSName) == 0)
+ matched_name = 1;
+ }
- if(flow->protos.stun_ssl.ssl.server_names == NULL)
- flow->protos.stun_ssl.ssl.server_names = ndpi_strdup(dNSName),
- flow->protos.stun_ssl.ssl.server_names_len = strlen(dNSName);
- else {
- u_int16_t dNSName_len = strlen(dNSName);
- u_int16_t newstr_len = flow->protos.stun_ssl.ssl.server_names_len + dNSName_len + 1;
- char *newstr = (char*)ndpi_realloc(flow->protos.stun_ssl.ssl.server_names,
- flow->protos.stun_ssl.ssl.server_names_len+1, newstr_len+1);
-
- if(newstr) {
- flow->protos.stun_ssl.ssl.server_names = newstr;
- flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len] = ',';
- strncpy(&flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len+1],
- dNSName, dNSName_len+1);
- flow->protos.stun_ssl.ssl.server_names[newstr_len] = '\0';
- flow->protos.stun_ssl.ssl.server_names_len = newstr_len;
- }
- }
+ if(flow->protos.stun_ssl.ssl.server_names == NULL)
+ flow->protos.stun_ssl.ssl.server_names = ndpi_strdup(dNSName),
+ flow->protos.stun_ssl.ssl.server_names_len = strlen(dNSName);
+ else {
+ u_int16_t dNSName_len = strlen(dNSName);
+ u_int16_t newstr_len = flow->protos.stun_ssl.ssl.server_names_len + dNSName_len + 1;
+ char *newstr = (char*)ndpi_realloc(flow->protos.stun_ssl.ssl.server_names,
+ flow->protos.stun_ssl.ssl.server_names_len+1, newstr_len+1);
+
+ if(newstr) {
+ flow->protos.stun_ssl.ssl.server_names = newstr;
+ flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len] = ',';
+ strncpy(&flow->protos.stun_ssl.ssl.server_names[flow->protos.stun_ssl.ssl.server_names_len+1],
+ dNSName, dNSName_len+1);
+ flow->protos.stun_ssl.ssl.server_names[newstr_len] = '\0';
+ flow->protos.stun_ssl.ssl.server_names_len = newstr_len;
+ }
+ }
- if(!flow->l4.tcp.tls.subprotocol_detected)
- if(ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TLS, dNSName, len))
- flow->l4.tcp.tls.subprotocol_detected = 1;
+ if(!flow->l4.tcp.tls.subprotocol_detected)
+ if(ndpi_match_hostname_protocol(ndpi_struct, flow, NDPI_PROTOCOL_TLS, dNSName, len))
+ flow->l4.tcp.tls.subprotocol_detected = 1;
- i += len;
- } else {
+ i += len;
+ } else {
#if DEBUG_TLS
- printf("[TLS] Leftover %u bytes", packet->payload_packet_len - i);
+ printf("[TLS] Leftover %u bytes", packet->payload_packet_len - i);
#endif
- break;
+ break;
+ }
+ } else {
+ break;
+ }
+ } /* while */
+
+ if(!matched_name)
+ NDPI_SET_BIT(flow->risk, NDPI_TLS_CERTIFICATE_MISMATCH); /* Certificate mismatch */
}
- } else {
- break;
}
- } /* while */
-
- if(!matched_name)
- NDPI_SET_BIT(flow->risk, NDPI_TLS_CERTIFICATE_MISMATCH); /* Certificate mismatch */
+ }
}
}
@@ -1252,10 +1258,59 @@ int processClientServerHello(struct ndpi_detection_module_struct *ndpi_struct,
if(flow->protos.stun_ssl.ssl.tls_supported_versions == NULL)
flow->protos.stun_ssl.ssl.tls_supported_versions = ndpi_strdup(version_str);
}
-
+ } else if(extension_id == 65486 /* encrypted server name */) {
+ /*
+ - https://tools.ietf.org/html/draft-ietf-tls-esni-06
+ - https://blog.cloudflare.com/encrypted-sni/
+ */
+ u_int16_t e_offset = offset+extension_offset;
+ u_int16_t initial_offset = e_offset;
+ u_int16_t e_sni_len, cipher_suite = ntohs(*((u_int16_t*)&packet->payload[e_offset]));
+
+ flow->protos.stun_ssl.ssl.encrypted_sni.cipher_suite = cipher_suite;
+
+ e_offset += 2; /* Cipher suite len */
+
+ /* Key Share Entry */
+ e_offset += 2; /* Group */
+ e_offset += ntohs(*((u_int16_t*)&packet->payload[e_offset])) + 2; /* Lenght */
+
+ if((e_offset+4) < packet->payload_packet_len) {
+ /* Record Digest */
+ e_offset += ntohs(*((u_int16_t*)&packet->payload[e_offset])) + 2; /* Lenght */
+
+ if((e_offset+4) < packet->payload_packet_len) {
+ e_sni_len = ntohs(*((u_int16_t*)&packet->payload[e_offset]));
+ e_offset += 2;
+
+ if((e_offset+e_sni_len-extension_len-initial_offset) >= 0) {
+#ifdef DEBUG_ENCRYPTED_SNI
+ printf("Client SSL [Encrypted Server Name len: %u]\n", e_sni_len);
+#endif
+
+ if(flow->protos.stun_ssl.ssl.encrypted_sni.esni == NULL) {
+ flow->protos.stun_ssl.ssl.encrypted_sni.esni = (char*)ndpi_malloc(e_sni_len*2+1);
+
+ if(flow->protos.stun_ssl.ssl.encrypted_sni.esni) {
+ u_int16_t i, off;
+
+ for(i=e_offset, off=0; i<(e_offset+e_sni_len); i++) {
+ int rc = sprintf(&flow->protos.stun_ssl.ssl.encrypted_sni.esni[off], "%02X", packet->payload[i] & 0XFF);
+
+ if(rc <= 0) {
+ flow->protos.stun_ssl.ssl.encrypted_sni.esni[off] = '\0';
+ break;
+ } else
+ off += rc;
+ }
+ }
+ }
+ }
+ }
+ }
}
- extension_offset += extension_len;
+ extension_offset += extension_len; /* Move to the next extension */
#ifdef DEBUG_TLS
printf("Client SSL [extension_offset/len: %u/%u]\n", extension_offset, extension_len);
diff --git a/tests/pcap/encrypted_sni.pcap b/tests/pcap/encrypted_sni.pcap
new file mode 100644
index 000000000..9f9f55dee
--- /dev/null
+++ b/tests/pcap/encrypted_sni.pcap
Binary files differ
diff --git a/tests/pcap/imaps.pcap b/tests/pcap/imaps.pcap
new file mode 100644
index 000000000..c038b57e2
--- /dev/null
+++ b/tests/pcap/imaps.pcap
Binary files differ
diff --git a/tests/result/encrypted_sni.pcap.out b/tests/result/encrypted_sni.pcap.out
new file mode 100644
index 000000000..979a98615
--- /dev/null
+++ b/tests/result/encrypted_sni.pcap.out
@@ -0,0 +1,10 @@
+Cloudflare 3 2310 3
+
+JA3 Host Stats:
+ IP Address # JA3C
+ 1 192.168.1.12 1
+
+
+ 1 TCP 192.168.1.12:49886 -> 104.27.129.77:443 [proto: 91.220/TLS.Cloudflare][cat: Web/5][1 pkts/770 bytes -> 0 pkts/0 bytes][Goodput ratio: 93/0][< 1 sec][ALPN: h2;http/1.1][TLS Supported Versions: TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][TLSv1.2][JA3C: e5ef852e686954ba9fe060fbfa881e15][ESNI: 9624CB3C4E230827F78CF5BF640D22DEA33FCC598EA6A32D939905586FBE997B9E68661F8956D4893072E19DE24CD1FB88A9F71FC4CC01BAB5C914FDF96A647D671B5E89859BAEEAB122218688496DF4DF0C328C3D5F940B109CEB2A2743D5CBE3594288A229B8C7E2F88303E3FE1A26A89E5001F2BD936890FEF78F06E05ECC063A68BDB8C18DFAC114CF1FECDB8BE1FC2FEECB2315D27998D682B129FD1E3EB5D7985DCBDC452A1082CCC038E0BF69570FEFAC6BC6FB951F89B6792CADA76403C02CEB5DCE1CE6EDDD16D5F7FB6B85D2B92485448DE0088E421E83F1E28B267FBE3B59AE0496FB845213C271D4C5AC5E9E7E5F6A3072445307FCCEB7306710459991C40CC4DC1FC325154C7974DD780371397805456A19AE23EE88475C1DF07697B666][ESNI Cipher: TLS_AES_128_GCM_SHA256][PLAIN TEXT (http/1.1)]
+ 2 TCP 192.168.1.12:49887 -> 104.16.125.175:443 [proto: 91.220/TLS.Cloudflare][cat: Web/5][1 pkts/770 bytes -> 0 pkts/0 bytes][Goodput ratio: 93/0][< 1 sec][ALPN: h2;http/1.1][TLS Supported Versions: TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][TLSv1.2][JA3C: e5ef852e686954ba9fe060fbfa881e15][ESNI: B900004E39E84B98F5AE87B0A020EC49FED86F2B488B6AB28BDE9F957621F2774366DE90E65C4CA808668911624685EC4C6DC6C161A97CBE82281BC08427697AA3BE6A40E5F00ACF8B63E329317B0E4E85642D50AB8790E6197DA62D9F5B3239DCC59437797FE768A520C9D471FEABA1375DF61E4A39B09363CB109E7B24A793844896DDD16B6EE7DBE576D767161D782D7BF6FEC453A05A923D8D8E9BEFFC97E8E56C4F1AAB70FE99BC97819E1D908A5F3B3094F4BF25EB7A24A94FDBC3E107A423B8BB341F22900F7BBD87780E30B6ECF393FEB8FBFFEB54C79FA0673FE1AAD17B221D4BFF6450AA0CD4AF513066B66080B602147F3ACB7145A436C5689DA20BACB8BF9BABD851012556EC8F7BB9D74BFAAF25DCF4362A5775607C3CE5C2C29F183969][ESNI Cipher: TLS_AES_128_GCM_SHA256][PLAIN TEXT (http/1.1)]
+ 3 TCP 192.168.1.12:49897 -> 104.22.71.197:443 [proto: 91.220/TLS.Cloudflare][cat: Web/5][1 pkts/770 bytes -> 0 pkts/0 bytes][Goodput ratio: 93/0][< 1 sec][ALPN: h2;http/1.1][TLS Supported Versions: TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][TLSv1.2][JA3C: e5ef852e686954ba9fe060fbfa881e15][ESNI: CD69AC727FFAA0EA70A12AA46E71537EB99234B996818C913C72A0AC1184BFA5DD3B617E013E4CA092B2E9CFB78BCD8D33CBAF12A974DFB78E49B8BF9A57997418EF14C87830961E3C8480D2A4BF27D61D911CEF4300924A9F36105748BAED845FF585E40406545BB35C6DAAD7896433EC4DFD6B6F49728DA85D707DB7AC784F55A6658DC6ADE3087B1E46BBBEDFA44F3E8754B31A6BCF8519D291D3629805FA826E43799EA6E33021CF0A83CA05717B00F37D69841934F5B5BF254C6467888A592C38A3007DB3B7D5CBB8DB742B657F8F973C050BAA817AA571393CD8A4BC0B2312460A77DD0510F4BBCE43D53BCF334E4E8C7570255BBD17714403F4B6925434CD67F96FA9E05D700776810EEB5786B1C8188A4D73F8208B614B93284A8093929594BE][ESNI Cipher: TLS_AES_128_GCM_SHA256][PLAIN TEXT (http/1.1)]
diff --git a/tests/result/imaps.pcap.out b/tests/result/imaps.pcap.out
new file mode 100644
index 000000000..85fa9f3ec
--- /dev/null
+++ b/tests/result/imaps.pcap.out
@@ -0,0 +1,8 @@
+ntop 20 5196 1
+
+JA3 Host Stats:
+ IP Address # JA3C
+ 1 192.168.1.8 1
+
+
+ 1 TCP 192.168.1.8:50506 <-> 167.99.215.164:993 [proto: 91.26/TLS.ntop][cat: Network/14][10 pkts/1220 bytes <-> 10 pkts/3976 bytes][Goodput ratio: 45/83][0.33 sec][bytes ratio: -0.530 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 33/22 77/43 26/19][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 122/398 293/1506 78/557][TLSv1.2][Client: mail.ntop.org][JA3C: 4923a265be4d81c68ecda45bb89cdf6a][ServerNames: mail.ntop.org][JA3S: b653c251b0ee54c3088fe7bb997cf59d][Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3][Subject: CN=mail.ntop.org][Certificate SHA-1: F1:9A:35:30:96:57:5E:56:81:28:2C:D9:45:A5:83:21:9E:E8:C5:DF][Validity: 2020-04-18 00:15:22 - 2020-07-17 00:15:22][Cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
diff --git a/tests/result/teams.pcap.out b/tests/result/teams.pcap.out
index 92e596e91..ae3ed7fd0 100644
--- a/tests/result/teams.pcap.out
+++ b/tests/result/teams.pcap.out
@@ -2,7 +2,7 @@ Unknown 35 14201 2
DNS 14 1947 7
DHCP 7 2323 2
ntop 40 9816 3
-SkypeCall 93 19649 12
+SkypeCall 49 10800 4
ICMP 2 140 1
TLS 107 45011 5
Dropbox 18 11162 3
@@ -12,7 +12,7 @@ Spotify 1 82 1
Telegram 3 186 1
Microsoft 403 283797 11
Microsoft365 136 52120 6
-Teams 1870 1025774 25
+Teams 1914 1034623 33
JA3 Host Stats:
IP Address # JA3C
@@ -59,17 +59,17 @@ JA3 Host Stats:
38 TCP 192.168.1.6:50014 <-> 52.114.250.152:443 [proto: 91.250/TLS.Teams][cat: Collaborative/15][14 pkts/1347 bytes <-> 11 pkts/6975 bytes][Goodput ratio: 42/91][0.22 sec][bytes ratio: -0.676 (Download)][IAT c2s/s2c min/avg/max/stddev: 0/0 16/22 43/84 20/30][Pkt Len c2s/s2c min/avg/max/stddev: 54/60 96/634 289/1506 73/570][Risk: ** TLS Certificate Mismatch **][TLSv1.2][Client: 52.114.250.152][JA3C: e4d448cdfe06dc1243c1eb026c74ac9a][ServerNames: tr.teams.microsoft.com,*.tr.teams.microsoft.com,turn.teams.microsoft.com,*.turn.teams.microsoft.com,*.relay.teams.microsoft.com][JA3S: 986571066668055ae9481cb84fda634a][Issuer: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, OU=Microsoft IT, CN=Microsoft IT TLS CA 5][Subject: CN=tr.teams.microsoft.com][Certificate SHA-1: A7:90:8D:41:ED:24:D2:83:48:95:90:CE:18:D3:A6:C2:62:7A:07:75][Validity: 2019-05-24 14:10:26 - 2021-05-24 14:10:26][Cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
39 TCP 192.168.1.6:60566 <-> 167.99.215.164:4434 [proto: 91.26/TLS.ntop][cat: Network/14][9 pkts/3029 bytes <-> 8 pkts/2213 bytes][Goodput ratio: 80/76][2.73 sec][ALPN: h2;http/1.1][TLS Supported Versions: TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][bytes ratio: 0.156 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 0/1 351/431 1977/2053 668/728][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 337/277 1012/1291 385/397][Risk: ** Known protocol on non standard port **][TLSv1.2][Client: dati.ntop.org][JA3C: 7120d65624bcd2e02ed4b01388d84cdb][JA3S: 410b9bedaf65dd26c6fe547154d60db4][Cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
40 TCP 192.168.1.6:60546 <-> 167.99.215.164:4434 [proto: 91.26/TLS.ntop][cat: Network/14][10 pkts/2195 bytes <-> 10 pkts/2077 bytes][Goodput ratio: 69/68][5.38 sec][ALPN: h2;http/1.1][TLS Supported Versions: TLSv1.3;TLSv1.2;TLSv1.1;TLSv1][bytes ratio: 0.028 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 0/0 650/754 5000/5000 1645/1734][Pkt Len c2s/s2c min/avg/max/stddev: 66/66 220/208 1021/1292 308/364][Risk: ** Known protocol on non standard port **][TLSv1.2][Client: dati.ntop.org][JA3C: 7120d65624bcd2e02ed4b01388d84cdb][JA3S: 410b9bedaf65dd26c6fe547154d60db4][Cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
- 41 UDP 192.168.1.6:50036 <-> 52.114.250.137:3478 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][5 pkts/1390 bytes <-> 4 pkts/733 bytes][Goodput ratio: 85/77][4.06 sec][bytes ratio: 0.309 (Upload)][IAT c2s/s2c min/avg/max/stddev: 0/100 1003/774 2235/2092 994/932][Pkt Len c2s/s2c min/avg/max/stddev: 228/174 278/183 314/198 33/10][PLAIN TEXT (rtcmedia)]
+ 41 UDP 192.168.1.6:50036 <-> 52.114.250.137:3478 [proto: 78.250/STUN.Teams][cat: VoIP/10][5 pkts/1390 bytes <-> 4 pkts/733 bytes][Goodput ratio: 85/77][4.06 sec][bytes ratio: 0.309 (Upload)][IAT c2s/s2c min/avg/max/stddev: 0/100 1003/774 2235/2092 994/932][Pkt Len c2s/s2c min/avg/max/stddev: 228/174 278/183 314/198 33/10][PLAIN TEXT (rtcmedia)]
42 UDP 192.168.0.1:68 -> 255.255.255.255:67 [proto: 18/DHCP][cat: Network/14][6 pkts/1926 bytes -> 0 pkts/0 bytes][Goodput ratio: 87/0][25.01 sec][Host: tl-sg116e][bytes ratio: 1.000 (Upload)][IAT c2s/s2c min/avg/max/stddev: 4986/0 5001/0 5018/0 11/0][Pkt Len c2s/s2c min/avg/max/stddev: 321/0 321/0 321/0 0/0][DHCP Fingerprint: 1,3]
- 43 UDP 192.168.1.6:50016 <-> 52.114.250.141:3478 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][4 pkts/1162 bytes <-> 3 pkts/546 bytes][Goodput ratio: 85/77][1.99 sec][bytes ratio: 0.361 (Upload)][IAT c2s/s2c min/avg/max/stddev: 0/98 611/101 1783/104 829/3][Pkt Len c2s/s2c min/avg/max/stddev: 256/174 290/182 314/198 25/11][PLAIN TEXT (rtcmedia)]
+ 43 UDP 192.168.1.6:50016 <-> 52.114.250.141:3478 [proto: 78.250/STUN.Teams][cat: VoIP/10][4 pkts/1162 bytes <-> 3 pkts/546 bytes][Goodput ratio: 85/77][1.99 sec][bytes ratio: 0.361 (Upload)][IAT c2s/s2c min/avg/max/stddev: 0/98 611/101 1783/104 829/3][Pkt Len c2s/s2c min/avg/max/stddev: 256/174 290/182 314/198 25/11][PLAIN TEXT (rtcmedia)]
44 TCP 93.62.150.157:443 <-> 192.168.1.6:60512 [proto: 91/TLS][cat: Web/5][2 pkts/1258 bytes <-> 2 pkts/108 bytes][Goodput ratio: 89/0][< 1 sec]
- 45 UDP 192.168.1.6:50017 <-> 52.114.250.141:3478 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][3 pkts/594 bytes <-> 3 pkts/611 bytes][Goodput ratio: 79/79][4.05 sec][bytes ratio: -0.014 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 99/97 2002/2002 3906/3906 1904/1904][Pkt Len c2s/s2c min/avg/max/stddev: 110/187 198/204 256/229 63/18][PLAIN TEXT (The request did not contain a M)]
- 46 UDP 192.168.1.6:50037 <-> 52.114.250.137:3478 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][3 pkts/594 bytes <-> 3 pkts/611 bytes][Goodput ratio: 79/79][4.05 sec][bytes ratio: -0.014 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 95/94 2000/2000 3905/3905 1905/1906][Pkt Len c2s/s2c min/avg/max/stddev: 110/187 198/204 256/229 63/18][PLAIN TEXT (The request did not contain a M)]
+ 45 UDP 192.168.1.6:50017 <-> 52.114.250.141:3478 [proto: 78.250/STUN.Teams][cat: VoIP/10][3 pkts/594 bytes <-> 3 pkts/611 bytes][Goodput ratio: 79/79][4.05 sec][bytes ratio: -0.014 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 99/97 2002/2002 3906/3906 1904/1904][Pkt Len c2s/s2c min/avg/max/stddev: 110/187 198/204 256/229 63/18][PLAIN TEXT (The request did not contain a M)]
+ 46 UDP 192.168.1.6:50037 <-> 52.114.250.137:3478 [proto: 78.250/STUN.Teams][cat: VoIP/10][3 pkts/594 bytes <-> 3 pkts/611 bytes][Goodput ratio: 79/79][4.05 sec][bytes ratio: -0.014 (Mixed)][IAT c2s/s2c min/avg/max/stddev: 95/94 2000/2000 3905/3905 1905/1906][Pkt Len c2s/s2c min/avg/max/stddev: 110/187 198/204 256/229 63/18][PLAIN TEXT (The request did not contain a M)]
47 UDP 93.71.110.205:16333 <-> 192.168.1.6:50036 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][3 pkts/414 bytes <-> 5 pkts/634 bytes][Goodput ratio: 69/67][2.31 sec][bytes ratio: -0.210 (Download)][IAT c2s/s2c min/avg/max/stddev: 101/15 634/572 1166/1168 532/565][Pkt Len c2s/s2c min/avg/max/stddev: 130/88 138/127 154/158 11/27][Risk: ** Known protocol on non standard port **]
- 48 UDP 192.168.1.6:50016 -> 192.168.0.4:50005 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][5 pkts/770 bytes -> 0 pkts/0 bytes][Goodput ratio: 73/0][1.22 sec][Risk: ** Known protocol on non standard port **]
- 49 UDP 192.168.1.6:50036 -> 192.168.0.4:50020 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][5 pkts/770 bytes -> 0 pkts/0 bytes][Goodput ratio: 73/0][1.22 sec][Risk: ** Known protocol on non standard port **]
- 50 UDP 192.168.1.6:50016 <-> 52.114.250.123:3478 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][1 pkts/110 bytes <-> 2 pkts/424 bytes][Goodput ratio: 61/80][0.12 sec][PLAIN TEXT (The request did not contain a M)]
- 51 UDP 192.168.1.6:50036 <-> 52.114.250.123:3478 [proto: 78.38/STUN.SkypeCall][cat: VoIP/10][1 pkts/110 bytes <-> 2 pkts/424 bytes][Goodput ratio: 61/80][0.12 sec][PLAIN TEXT (The request did not contain a M)]
+ 48 UDP 192.168.1.6:50016 -> 192.168.0.4:50005 [proto: 78.250/STUN.Teams][cat: VoIP/10][5 pkts/770 bytes -> 0 pkts/0 bytes][Goodput ratio: 73/0][1.22 sec][Risk: ** Known protocol on non standard port **]
+ 49 UDP 192.168.1.6:50036 -> 192.168.0.4:50020 [proto: 78.250/STUN.Teams][cat: VoIP/10][5 pkts/770 bytes -> 0 pkts/0 bytes][Goodput ratio: 73/0][1.22 sec][Risk: ** Known protocol on non standard port **]
+ 50 UDP 192.168.1.6:50016 <-> 52.114.250.123:3478 [proto: 78.250/STUN.Teams][cat: VoIP/10][1 pkts/110 bytes <-> 2 pkts/424 bytes][Goodput ratio: 61/80][0.12 sec][PLAIN TEXT (The request did not contain a M)]
+ 51 UDP 192.168.1.6:50036 <-> 52.114.250.123:3478 [proto: 78.250/STUN.Teams][cat: VoIP/10][1 pkts/110 bytes <-> 2 pkts/424 bytes][Goodput ratio: 61/80][0.12 sec][PLAIN TEXT (The request did not contain a M)]
52 UDP 192.168.1.6:17500 -> 192.168.1.255:17500 [proto: 121/Dropbox][cat: Cloud/13][1 pkts/527 bytes -> 0 pkts/0 bytes][Goodput ratio: 92/0][< 1 sec][PLAIN TEXT (version)]
53 UDP 192.168.1.6:17500 -> 255.255.255.255:17500 [proto: 121/Dropbox][cat: Cloud/13][1 pkts/527 bytes -> 0 pkts/0 bytes][Goodput ratio: 92/0][< 1 sec][PLAIN TEXT (version)]
54 UDP 0.0.0.0:68 -> 255.255.255.255:67 [proto: 18/DHCP][cat: Network/14][1 pkts/397 bytes -> 0 pkts/0 bytes][Goodput ratio: 89/0][< 1 sec][PLAIN TEXT (6.10.1)]