aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h6
-rw-r--r--src/include/ndpi_protocol_ids.h4
-rw-r--r--src/include/ndpi_typedefs.h1
-rw-r--r--src/lib/ndpi_content_match.c.inc92
-rw-r--r--src/lib/ndpi_main.c197
-rw-r--r--src/lib/ndpi_serializer.c63
-rw-r--r--src/lib/protocols/ciscovpn.c28
-rw-r--r--src/lib/protocols/dns.c373
-rw-r--r--src/lib/protocols/skype.c15
-rw-r--r--src/lib/protocols/steam.c76
-rw-r--r--src/lib/protocols/stun.c396
11 files changed, 744 insertions, 507 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index 285629035..34b1fed67 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -807,7 +807,8 @@ extern "C" {
int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struct ndpi_in6_addr *dst_ip,
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);
u_int8_t ndpi_is_safe_ssl_cipher(u_int32_t cipher);
const char* ndpi_cipher2str(u_int32_t cipher);
u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_struct,
@@ -858,6 +859,9 @@ extern "C" {
const char *key, float value,
const char *format /* e.f. "%.2f" */);
int ndpi_serialize_end_of_record(ndpi_serializer *serializer);
+ int ndpi_serialize_start_of_block(ndpi_serializer *_serializer,
+ const char *key);
+ int ndpi_serialize_end_of_block(ndpi_serializer *_serializer);
char* ndpi_serializer_get_buffer(ndpi_serializer *_serializer, u_int32_t *buffer_len);
u_int32_t ndpi_serializer_get_buffer_len(ndpi_serializer *_serializer);
int ndpi_serializer_set_buffer_len(ndpi_serializer *_serializer, u_int32_t l);
diff --git a/src/include/ndpi_protocol_ids.h b/src/include/ndpi_protocol_ids.h
index c22c6f815..77b244bca 100644
--- a/src/include/ndpi_protocol_ids.h
+++ b/src/include/ndpi_protocol_ids.h
@@ -98,7 +98,7 @@ typedef enum {
NDPI_PROTOCOL_QQLIVE = 61,
NDPI_PROTOCOL_THUNDER = 62,
NDPI_PROTOCOL_SOULSEEK = 63,
- NDPI_PROTOCOL_FREE_64 = 64,
+ NDPI_PROTOCOL_PS_VUE = 64,
NDPI_PROTOCOL_IRC = 65,
NDPI_PROTOCOL_AYIYA = 66,
NDPI_PROTOCOL_UNENCRYPTED_JABBER = 67,
@@ -223,7 +223,7 @@ typedef enum {
NDPI_PROTOCOL_VEVO = 186,
NDPI_PROTOCOL_PANDORA = 187,
NDPI_PROTOCOL_QUIC = 188, /* Andrea Buscarinu <andrea.buscarinu@gmail.com> - Michele Campus <michelecampus5@gmail.com> */
- NDPI_PROTOCOL_FREE_189 = 189,
+ NDPI_PROTOCOL_ZOOM = 189, /* Zoom video conference. */
NDPI_PROTOCOL_EAQ = 190,
NDPI_PROTOCOL_OOKLA = 191,
NDPI_PROTOCOL_AMQP = 192,
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 3cf7c07b3..ccc4faec7 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -1379,6 +1379,7 @@ typedef enum {
#define NDPI_SERIALIZER_STATUS_COMMA (1 << 0)
#define NDPI_SERIALIZER_STATUS_ARRAY (1 << 1)
#define NDPI_SERIALIZER_STATUS_EOR (1 << 2)
+#define NDPI_SERIALIZER_STATUS_SOB (1 << 3)
typedef struct {
u_int32_t flags;
diff --git a/src/lib/ndpi_content_match.c.inc b/src/lib/ndpi_content_match.c.inc
index 1693db9fd..c6e753de6 100644
--- a/src/lib/ndpi_content_match.c.inc
+++ b/src/lib/ndpi_content_match.c.inc
@@ -8220,6 +8220,92 @@ static ndpi_network host_protocol_list[] = {
/* Line */
{ 0x7DD1FC00 /* 125.209.252.0/24 */, 24, NDPI_PROTOCOL_LINE },
+ /* Zoom video conference app. */
+ { 0x03501480 /* 3.80.20.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x03787900 /* 3.120.121.0/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x03682280 /* 3.104.34.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x03D04800 /* 3.208.72.0/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x03D3F100 /* 3.211.241.0/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x04227D80 /* 4.34.125.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x04234080 /* 4.35.64.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x08058000 /* 8.5.128.0/23 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x0D340680 /* 13.52.6.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x0D349200 /* 13.52.146.0/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x0D726AA6 /* 13.114.106.166/32 */, 32, NDPI_PROTOCOL_ZOOM },
+ { 0x12CD5D80 /* 18.205.93.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x32EFCA00 /* 50.239.202.0/23 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x32EFCC00 /* 50.239.204.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0x343D6480 /* 52.61.100.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x34519780 /* 52.81.151.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x34C56115 /* 52.197.97.21/32 */, 32, NDPI_PROTOCOL_ZOOM },
+ { 0x34CA3EC0 /* 52.202.62.192/26 */, 26, NDPI_PROTOCOL_ZOOM },
+ { 0x34D7A800 /* 52.215.168.0/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x40454A00 /* 64.69.74.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0x407D3E00 /* 64.125.62.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0x40D39000 /* 64.211.144.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0x41279800 /* 65.39.152.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0x45AE3900 /* 69.174.57.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0x45AE6C00 /* 69.174.108.0/22 */, 22, NDPI_PROTOCOL_ZOOM },
+ { 0x634F1400 /* 99.79.20.0/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0x677AA600 /* 103.122.166.0/23 */, 23, NDPI_PROTOCOL_ZOOM },
+ { 0x6D5EA000 /* 109.94.160.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0x736E9AC0 /* 115.110.154.192/26 */, 26, NDPI_PROTOCOL_ZOOM },
+ { 0x737238C0 /* 115.114.56.192/26 */, 26, NDPI_PROTOCOL_ZOOM },
+ { 0x73727300 /* 115.114.115.0/26 */, 26, NDPI_PROTOCOL_ZOOM },
+ { 0x73728300 /* 115.114.131.0/26 */, 26, NDPI_PROTOCOL_ZOOM },
+ { 0x781D9400 /* 120.29.148.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xA0013880 /* 160.1.56.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0xA1C78800 /* 161.199.136.0/22 */, 22, NDPI_PROTOCOL_ZOOM },
+ { 0xA20CE800 /* 162.12.232.0/22 */, 22, NDPI_PROTOCOL_ZOOM },
+ { 0xA2FF2400 /* 162.255.36.0/22 */, 22, NDPI_PROTOCOL_ZOOM },
+ { 0xA5FE5800 /* 165.254.88.0/23 */, 23, NDPI_PROTOCOL_ZOOM },
+ { 0xC0CC0C00 /* 192.204.12.0/22 */, 22, NDPI_PROTOCOL_ZOOM },
+ { 0xCAB1CF80 /* 202.177.207.128/27 */, 27, NDPI_PROTOCOL_ZOOM },
+ { 0xCAB1D560 /* 202.177.213.96/27 */, 27, NDPI_PROTOCOL_ZOOM },
+ { 0xCC506800 /* 204.80.104.0/21 */, 21, NDPI_PROTOCOL_ZOOM },
+ { 0xCC8D1C00 /* 204.141.28.0/22 */, 22, NDPI_PROTOCOL_ZOOM },
+ { 0xCFE28400 /* 207.226.132.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xD109D300 /* 209.9.211.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xD109D700 /* 209.9.215.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xD2393700 /* 210.57.55.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xD5139000 /* 213.19.144.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xD5139900 /* 213.19.153.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xD5F48C00 /* 213.244.140.0/24 */, 24, NDPI_PROTOCOL_ZOOM },
+ { 0xDD7A5840 /* 221.122.88.64/27 */, 27, NDPI_PROTOCOL_ZOOM },
+ { 0xDD7A5880 /* 221.122.88.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ { 0xDD7A5980 /* 221.122.89.128/25 */, 25, NDPI_PROTOCOL_ZOOM },
+ /* 2620:123:2000::/44 IPV6 */
+
+ { 0x08F8DA14 /* 8.248.218.20/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FA6E14 /* 8.250.110.20/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FC028B /* 8.252.2.139/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FD6803 /* 8.253.104.3/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FE6813 /* 8.253.104.19/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FE8C0F /* 8.253.140.15/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FE8C10 /* 8.253.140.16/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FE8C77 /* 8.253.140.119/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FC8CA8 /* 8.253.140.168/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x08FC8CA9 /* 8.253.140.169/32 */, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x4318881E /* 67.24.136.30/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x431889FE /* 67.24.137.254/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x43188DFE /* 67.24.141.254/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x43188E1E /* 67.24.142.30/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x4318901E /* 67.24.144.30/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x4318921E /* 67.24.146.30/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0x43189630 /* 67.24.150.30/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA2D83A20 /* 162.216.58.32/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA2D83A2B /* 162.216.58.43/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA2D83A39 /* 162.216.58.57/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA2D83A40 /* 162.216.58.64/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA2D83A48 /* 162.216.58.72/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA2D83A51 /* 162.216.58.81/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA7CE74AA /* 167.206.116.170/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA7CEDA60 /* 167.206.218.96/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA7CEDA72 /* 167.206.218.114/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA7CEDA7B /* 167.206.218.123/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA7CEDA82 /* 167.206.218.130/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+ { 0xA7CEDA8A /* 167.206.218.138/32*/, 32, NDPI_PROTOCOL_PS_VUE },
+
{ 0x0, 0, 0 }
};
@@ -8593,7 +8679,9 @@ ndpi_protocol_match host_match[] = {
{ "hotspotshield.com", NULL, "hotspotshield" TLD, "HotspotShield", NDPI_PROTOCOL_HOTSPOT_SHIELD, NDPI_PROTOCOL_CATEGORY_VPN, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS },
{ ".northghost.com", NULL, "\\.northghost" TLD, "HotspotShield", NDPI_PROTOCOL_HOTSPOT_SHIELD, NDPI_PROTOCOL_CATEGORY_VPN, NDPI_PROTOCOL_POTENTIALLY_DANGEROUS },
- { ".webex.com", NULL, "\\.webex" TLD, "Webex", NDPI_PROTOCOL_WEBEX, NDPI_PROTOCOL_CATEGORY_VOIP, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".webex.com", NULL, "\\.webex" TLD, "Webex", NDPI_PROTOCOL_WEBEX, NDPI_PROTOCOL_CATEGORY_VOIP, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".zoom.us", NULL, "\\.zoom" TLD, "Zoom", NDPI_PROTOCOL_ZOOM, NDPI_PROTOCOL_CATEGORY_VIDEO, NDPI_PROTOCOL_ACCEPTABLE },
+ { ".cloudfront.net", NULL, "\\.cloudfront" TLD, "Zoom", NDPI_PROTOCOL_ZOOM, NDPI_PROTOCOL_CATEGORY_VIDEO, NDPI_PROTOCOL_ACCEPTABLE },
{ ".ocsdomain.com", NULL, "\\.ocsdomain" TLD, "OCS", NDPI_PROTOCOL_OCS, NDPI_PROTOCOL_CATEGORY_MEDIA, NDPI_PROTOCOL_FUN },
{ "ocs.fr", NULL, "ocs" TLD, "OCS", NDPI_PROTOCOL_OCS, NDPI_PROTOCOL_CATEGORY_MEDIA, NDPI_PROTOCOL_FUN },
@@ -8639,8 +8727,6 @@ ndpi_protocol_match host_match[] = {
/* Detected "slack-assets2.s3-us-west-2.amazonaws.com.". Omitted "*amazonaws.com" CDN, but no generic pattern to use on first part */
{ "slack-assets2.s3-", NULL, "slack-assets2\\.s3-", "Slack", NDPI_PROTOCOL_SLACK, NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, NDPI_PROTOCOL_ACCEPTABLE },
- { "wechat.com", NULL, "wechat\\.com" TLD, "WeChat", NDPI_PROTOCOL_WECHAT, NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, NDPI_PROTOCOL_FUN },
-
{ "github.com", NULL, "github" TLD, "Github", NDPI_PROTOCOL_GITHUB, NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, NDPI_PROTOCOL_ACCEPTABLE },
{ ".github.com", NULL, "\\.github" TLD, "Github", NDPI_PROTOCOL_GITHUB, NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, NDPI_PROTOCOL_ACCEPTABLE },
{ "github.io", NULL, NULL, "Github", NDPI_PROTOCOL_GITHUB, NDPI_PROTOCOL_CATEGORY_COLLABORATIVE, NDPI_PROTOCOL_ACCEPTABLE },
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index df40c5769..44963d183 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -455,7 +455,7 @@ static int ndpi_string_to_automa(struct ndpi_detection_module_struct *ndpi_struc
/*
TODO
This function should free the memory during program termination
-
+
*/
static void ndpi_free_memory_at_termination(struct ndpi_detection_module_struct *ndpi_struct, char *buf) {
@@ -471,7 +471,7 @@ static int ndpi_add_host_url_subprotocol(struct ndpi_detection_module_struct *nd
char *value = ndpi_strdup(_value);
if(!value) return(-1); else ndpi_free_memory_at_termination(ndpi_struct, value);
-
+
#ifdef DEBUG
NDPI_LOG_DEBUG2(ndpi_struct, "[NDPI] Adding [%s][%d]\n", value, protocol_id);
#endif
@@ -978,7 +978,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
ndpi_build_default_ports(ports_b, 3544, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WECHAT,
0 /* can_have_a_subprotocol */, no_master, /* wechat.com */
- no_master, "WeChat", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK,
+ no_master, "WeChat", NDPI_PROTOCOL_CATEGORY_CHAT,
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MEMCACHED,
@@ -1122,9 +1122,9 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
- ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_FREE_64,
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_PS_VUE,
0 /* can_have_a_subprotocol */, no_master,
- no_master, "Free64", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT,
+ no_master, "PS_VUE", NDPI_PROTOCOL_CATEGORY_VIDEO,
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_IRC,
@@ -1249,9 +1249,9 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
no_master, "PcAnywhere", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS,
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
- ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_FREE_189,
+ ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ZOOM,
0 /* can_have_a_subprotocol */, no_master,
- no_master, "Free189", NDPI_PROTOCOL_CATEGORY_VOIP,
+ no_master, "Zoom", NDPI_PROTOCOL_CATEGORY_VIDEO,
ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_FILES,
@@ -1555,7 +1555,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CISCOVPN,
0 /* can_have_a_subprotocol */, no_master,
no_master, "CiscoVPN", NDPI_PROTOCOL_CATEGORY_VPN,
- ndpi_build_default_ports(ports_a, 10000, 0, 0, 0, 0) /* TCP */,
+ ndpi_build_default_ports(ports_a, 10000, 8008, 8009, 0, 0) /* TCP */,
ndpi_build_default_ports(ports_b, 10000, 0, 0, 0, 0) /* UDP */);
ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TEAMSPEAK,
0 /* can_have_a_subprotocol */, no_master,
@@ -1794,10 +1794,14 @@ static int ac_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) {
if(whatfound
&& (whatfound != buf)
&& (m->patterns->astring[0] != '.') /* The searched pattern does not start with . */
- && strchr(m->patterns->astring, '.') /* The matched pattern has a . (e.g. numeric or sym IPs) */
- && (whatfound[-1] != '.')
- )
- return(0);
+ && strchr(m->patterns->astring, '.') /* The matched pattern has a . (e.g. numeric or sym IPs) */) {
+ if(whatfound[-1] != '.') {
+ return(0);
+ } else {
+ memcpy(match, &m->patterns[0].rep, sizeof(AC_REP_t)); /* Partial match? */
+ return(0); /* Keep searching as probably there is a better match */
+ }
+ }
}
/*
@@ -2215,6 +2219,13 @@ int ndpi_match_string(void *_automa, char *string_to_match) {
rc = ac_automata_search(automa, &ac_input_text, &match);
ac_automata_reset(automa);
+ /*
+ As ac_automata_search can detect partial matches and continue the search process
+ in case rc == 0 (i.e. no match), we need to check if there is a partial match
+ and in this case return it
+ */
+ if((rc == 0) && (match.number != 0)) rc = 1;
+
return(rc ? match.number : 0);
}
@@ -2236,6 +2247,13 @@ int ndpi_match_string_id(void *_automa, char *string_to_match, unsigned long *id
rc = ac_automata_search(automa, &ac_input_text, &match);
ac_automata_reset(automa);
+ /*
+ As ac_automata_search can detect partial matches and continue the search process
+ in case rc == 0 (i.e. no match), we need to check if there is a partial match
+ and in this case return it
+ */
+ if((rc == 0) && (match.number != 0)) rc = 1;
+
*id = rc ? match.number : NDPI_PROTOCOL_UNKNOWN;
return(*id != NDPI_PROTOCOL_UNKNOWN ? 0 : -1);
@@ -3543,7 +3561,7 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str
u_int8_t l4_result;
if (!flow)
- return 1;
+ return 1;
/* reset payload_packet_len, will be set if ipv4 tcp or udp */
flow->packet.payload_packet_len = 0;
@@ -3606,7 +3624,7 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str
flow->packet.l4_protocol = l4protocol;
flow->packet.l4_packet_len = l4len;
flow->l4_proto = l4protocol;
-
+
/* tcp / udp detection */
if(l4protocol == IPPROTO_TCP && flow->packet.l4_packet_len >= 20 /* min size of tcp */ ) {
/* tcp */
@@ -3860,7 +3878,7 @@ void check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_struct,
&& NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer_udp[a].detection_bitmask,
detection_bitmask) != 0) {
ndpi_struct->callback_buffer_udp[a].func(ndpi_struct, flow);
-
+
// NDPI_LOG_DBG(ndpi_struct, "[UDP,CALL] dissector of protocol as callback_buffer idx = %d\n",a);
if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN)
break; /* Stop after detecting the first protocol */
@@ -4044,8 +4062,14 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
if(flow == NULL)
return(ret);
- else
- ret.category = flow->category;
+
+ /* Init defaults */
+ ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
+ ret.category = flow->category;
+
+ /* Ensure that we don't change our mind if detection is already complete */
+ if((ret.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN))
+ return(ret);
/* TODO: add the remaining stage_XXXX protocols */
if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
@@ -4460,6 +4484,44 @@ void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_struc
/* ********************************************************************************* */
+static void ndpi_reset_packet_line_info(struct ndpi_packet_struct *packet) {
+ packet->parsed_lines = 0,
+ packet->empty_line_position_set = 0,
+ packet->host_line.ptr = NULL,
+ packet->host_line.len = 0,
+ packet->referer_line.ptr = NULL,
+ packet->referer_line.len = 0,
+ packet->content_line.ptr = NULL,
+ packet->content_line.len = 0,
+ packet->accept_line.ptr = NULL,
+ packet->accept_line.len = 0,
+ packet->user_agent_line.ptr = NULL,
+ packet->user_agent_line.len = 0,
+ packet->http_url_name.ptr = NULL,
+ packet->http_url_name.len = 0,
+ packet->http_encoding.ptr = NULL,
+ packet->http_encoding.len = 0,
+ packet->http_transfer_encoding.ptr = NULL,
+ packet->http_transfer_encoding.len = 0,
+ packet->http_contentlen.ptr = NULL,
+ packet->http_contentlen.len = 0,
+ packet->http_cookie.ptr = NULL,
+ packet->http_cookie.len = 0,
+ packet->http_origin.len = 0,
+ packet->http_origin.ptr = NULL,
+ packet->http_x_session_type.ptr = NULL,
+ packet->http_x_session_type.len = 0,
+ packet->server_line.ptr = NULL,
+ packet->server_line.len = 0,
+ packet->http_method.ptr = NULL,
+ packet->http_method.len = 0,
+ packet->http_response.ptr = NULL,
+ packet->http_response.len = 0,
+ packet->http_num_headers = 0;
+}
+
+/* ********************************************************************************* */
+
ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct,
struct ndpi_flow_struct *flow,
const unsigned char *packet,
@@ -4484,7 +4546,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
/* Init default */
ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0];
-
+
if(flow->server_id == NULL) flow->server_id = dst; /* Default */
if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) {
/*
@@ -4497,7 +4559,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
*/
) {
ndpi_process_extra_packet(ndpi_struct, flow, packet, packetlen, current_tick_l, src, dst);
-
+
return(ret);
} else
goto ret_protocols;
@@ -4676,8 +4738,12 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
} else
ret.app_protocol = flow->detected_protocol_stack[0];
- ndpi_fill_protocol_category(ndpi_struct, flow, &ret);
-
+ /* Don;t overwrite the category if already set */
+ if(flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)
+ ndpi_fill_protocol_category(ndpi_struct, flow, &ret);
+ else
+ ret.category = flow->category;
+
if((flow->num_processed_pkts == 1)
&& (ret.master_protocol == NDPI_PROTOCOL_UNKNOWN)
&& (ret.app_protocol == NDPI_PROTOCOL_UNKNOWN)
@@ -4701,7 +4767,8 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
Invalidate packet memory to avoid accessing the pointers below
when the packet is no longer accessible
*/
- flow->packet.iph = NULL, flow->packet.tcp = NULL, flow->packet.udp = NULL;
+ flow->packet.iph = NULL, flow->packet.tcp = NULL, flow->packet.udp = NULL, flow->packet.payload = NULL;
+ ndpi_reset_packet_line_info(&flow->packet);
return(ret);
}
@@ -4864,39 +4931,7 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_struc
return;
packet->packet_lines_parsed_complete = 1;
- packet->parsed_lines = 0;
- packet->empty_line_position_set = 0;
- packet->host_line.ptr = NULL;
- packet->host_line.len = 0;
- packet->referer_line.ptr = NULL;
- packet->referer_line.len = 0;
- packet->content_line.ptr = NULL;
- packet->content_line.len = 0;
- packet->accept_line.ptr = NULL;
- packet->accept_line.len = 0;
- packet->user_agent_line.ptr = NULL;
- packet->user_agent_line.len = 0;
- packet->http_url_name.ptr = NULL;
- packet->http_url_name.len = 0;
- packet->http_encoding.ptr = NULL;
- packet->http_encoding.len = 0;
- packet->http_transfer_encoding.ptr = NULL;
- packet->http_transfer_encoding.len = 0;
- packet->http_contentlen.ptr = NULL;
- packet->http_contentlen.len = 0;
- packet->http_cookie.ptr = NULL;
- packet->http_cookie.len = 0;
- packet->http_origin.len = 0;
- packet->http_origin.ptr = NULL;
- packet->http_x_session_type.ptr = NULL;
- packet->http_x_session_type.len = 0;
- packet->server_line.ptr = NULL;
- packet->server_line.len = 0;
- packet->http_method.ptr = NULL;
- packet->http_method.len = 0;
- packet->http_response.ptr = NULL;
- packet->http_response.len = 0;
- packet->http_num_headers=0;
+ ndpi_reset_packet_line_info(packet);
if((packet->payload_packet_len < 3)
|| (packet->payload == NULL))
@@ -5862,7 +5897,7 @@ int ndpi_get_category_id(struct ndpi_detection_module_struct *ndpi_mod, char *ca
void ndpi_dump_protocols(struct ndpi_detection_module_struct *ndpi_mod) {
int i;
-
+
for(i=0; i<(int)ndpi_mod->ndpi_num_supported_protocols; i++)
printf("%3d %-22s %-12s %s\n", i,
ndpi_mod->proto_defaults[i].protoName,
@@ -6102,6 +6137,13 @@ int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct,
rc = ac_automata_search(((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, &match);
ac_automata_reset(((AC_AUTOMATA_t*)automa->ac_automa));
+ /*
+ As ac_automata_search can detect partial matches and continue the search process
+ in case rc == 0 (i.e. no match), we need to check if there is a partial match
+ and in this case return it
+ */
+ if((rc == 0) && (match.number != 0)) rc = 1;
+
return(rc ? match.number : 0);
}
@@ -6116,7 +6158,7 @@ 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);
}
-
+
ndpi_free(flow);
}
}
@@ -6275,4 +6317,43 @@ int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struc
return(0); /* OK */
}
-/* **************************************** */
+/* ******************************************************************** */
+
+/*
+ This function tells if it's possible to further dissect a given flow
+ 0 - All possible dissection has been completed
+ 1 - Additional dissection is possible
+*/
+u_int8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow) {
+
+#if 0
+ printf("[DEBUG] %s(%u.%u)\n", __FUNCTION__,
+ flow->detected_protocol_stack[0],
+ flow->detected_protocol_stack[1]);
+#endif
+
+ if(flow->check_extra_packets) return(1);
+
+ switch(flow->detected_protocol_stack[0]) {
+ case NDPI_PROTOCOL_TLS:
+ if(!flow->l4.tcp.tls_srv_cert_fingerprint_processed)
+ return(1);
+ break;
+
+ case NDPI_PROTOCOL_HTTP:
+ if(flow->host_server_name[0] == '\0')
+ return(1);
+ break;
+
+ case NDPI_PROTOCOL_DNS:
+ if((ndpi_struct->dns_dont_dissect_response == 0)
+ && (flow->host_server_name[0] == '\0'))
+ return(1);
+ break;
+ }
+
+ return(0);
+}
+
+/* ******************************************************************** */
diff --git a/src/lib/ndpi_serializer.c b/src/lib/ndpi_serializer.c
index 87ce5e364..49f29a4e8 100644
--- a/src/lib/ndpi_serializer.c
+++ b/src/lib/ndpi_serializer.c
@@ -454,7 +454,10 @@ static inline void ndpi_serialize_json_pre(ndpi_serializer *_serializer) {
if(serializer->status.flags & NDPI_SERIALIZER_STATUS_ARRAY)
serializer->status.size_used--; /* Remove ']'*/
serializer->status.size_used--; /* Remove '}'*/
- if(serializer->status.flags & NDPI_SERIALIZER_STATUS_COMMA)
+
+ 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++] = ',';
}
}
@@ -1206,6 +1209,64 @@ int ndpi_serialize_string_string(ndpi_serializer *_serializer,
/* ********************************** */
+/* 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 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, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->status.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;
+ ndpi_serialize_json_post(_serializer);
+
+ serializer->status.flags |= NDPI_SERIALIZER_STATUS_SOB;
+
+ return(0);
+}
+
+/* ********************************** */
+
+/* Serialize start 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 needed;
+
+ if (serializer->fmt != ndpi_serialization_format_json)
+ return -1;
+
+ needed = 4;
+
+ if (buff_diff < needed) {
+ if (ndpi_extend_serializer_buffer(_serializer, needed - buff_diff) < 0)
+ return(-1);
+ buff_diff = serializer->buffer_size - serializer->status.size_used;
+ }
+
+ buff_diff = serializer->buffer_size - serializer->status.size_used;
+ ndpi_serialize_json_post(_serializer);
+
+ return(0);
+}
+
+/* ********************************** */
+
void ndpi_serializer_create_snapshot(ndpi_serializer *_serializer) {
ndpi_private_serializer *serializer = (ndpi_private_serializer*)_serializer;
diff --git a/src/lib/protocols/ciscovpn.c b/src/lib/protocols/ciscovpn.c
index d98f91e02..4a73e5728 100644
--- a/src/lib/protocols/ciscovpn.c
+++ b/src/lib/protocols/ciscovpn.c
@@ -48,7 +48,33 @@ void ndpi_search_ciscovpn(struct ndpi_detection_module_struct *ndpi_struct, stru
NDPI_LOG_INFO(ndpi_struct, "found CISCOVPN\n");
ndpi_int_ciscovpn_add_connection(ndpi_struct, flow);
return;
- }
+ }
+ else if(((tsport == 443 || tdport == 443) ||
+ (tsport == 80 || tdport == 80)) &&
+ ((packet->payload[0] == 0x17 &&
+ packet->payload[1] == 0x03 &&
+ packet->payload[2] == 0x03 &&
+ packet->payload[3] == 0x00 &&
+ packet->payload[4] == 0x3A)))
+ {
+ /* TLS signature of Cisco AnyConnect 0X170303003A */
+ NDPI_LOG_INFO(ndpi_struct, "found CISCO Anyconnect VPN\n");
+ ndpi_int_ciscovpn_add_connection(ndpi_struct, flow);
+ return;
+ }
+ else if(((tsport == 8009 || tdport == 8009) ||
+ (tsport == 8008 || tdport == 8008)) &&
+ ((packet->payload[0] == 0x17 &&
+ packet->payload[1] == 0x03 &&
+ packet->payload[2] == 0x03 &&
+ packet->payload[3] == 0x00 &&
+ packet->payload[4] == 0x69)))
+ {
+ /* TCP signature of Cisco AnyConnect 0X1703030069 */
+ NDPI_LOG_INFO(ndpi_struct, "found CISCO Anyconnect VPN\n");
+ ndpi_int_ciscovpn_add_connection(ndpi_struct, flow);
+ return;
+ }
else if(
(
(usport == 10000 && udport == 10000)
diff --git a/src/lib/protocols/dns.c b/src/lib/protocols/dns.c
index b9cd1a9cb..86575f23e 100644
--- a/src/lib/protocols/dns.c
+++ b/src/lib/protocols/dns.c
@@ -30,7 +30,7 @@
#define FLAGS_MASK 0x8000
-/* #define DNS_DEBUG 1 */
+// #define DNS_DEBUG 1
/* *********************************************** */
@@ -59,23 +59,144 @@ static u_int getNameLength(u_int i, const u_int8_t *payload, u_int payloadLen) {
return(off + getNameLength(i+off, payload, payloadLen));
}
}
-/*
- allowed chars for dns names A-Z 0-9 _ -
- Perl script for generation map:
+/*
+ allowed chars for dns names A-Z 0-9 _ -
+ Perl script for generation map:
my @M;
for(my $ch=0; $ch < 256; $ch++) {
- $M[$ch >> 5] |= 1 << ($ch & 0x1f) if chr($ch) =~ /[a-z0-9_-]/i;
+ $M[$ch >> 5] |= 1 << ($ch & 0x1f) if chr($ch) =~ /[a-z0-9_-]/i;
}
print join(',', map { sprintf "0x%08x",$_ } @M),"\n";
- */
+*/
static uint32_t dns_validchar[8] = {
- 0x00000000,0x03ff2000,0x87fffffe,0x07fffffe,0,0,0,0
+ 0x00000000,0x03ff2000,0x87fffffe,0x07fffffe,0,0,0,0
};
+
+/* *********************************************** */
+
+static int search_valid_dns(struct ndpi_detection_module_struct *ndpi_struct,
+ struct ndpi_flow_struct *flow,
+ struct ndpi_dns_packet_header *dns_header,
+ int payload_offset, u_int8_t *is_query) {
+ int x = payload_offset;
+
+ memcpy(dns_header, (struct ndpi_dns_packet_header*)&flow->packet.payload[x],
+ sizeof(struct ndpi_dns_packet_header));
+ dns_header->tr_id = ntohs(dns_header->tr_id);
+ dns_header->flags = ntohs(dns_header->flags);
+ dns_header->num_queries = ntohs(dns_header->num_queries);
+ dns_header->num_answers = ntohs(dns_header->num_answers);
+ dns_header->authority_rrs = ntohs(dns_header->authority_rrs);
+ dns_header->additional_rrs = ntohs(dns_header->additional_rrs);
+
+ x += sizeof(struct ndpi_dns_packet_header);
+
+ /* 0x0000 QUERY */
+ if((dns_header->flags & FLAGS_MASK) == 0x0000)
+ *is_query = 1;
+ /* 0x8000 RESPONSE */
+ else if((dns_header->flags & FLAGS_MASK) == 0x8000)
+ *is_query = 0;
+ else
+ return(1 /* invalid */);
+
+ if(*is_query) {
+ /* DNS Request */
+ if((dns_header->num_queries > 0) && (dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS)
+ && (((dns_header->flags & 0x2800) == 0x2800 /* Dynamic DNS Update */)
+ || ((dns_header->num_answers == 0) && (dns_header->authority_rrs == 0)))) {
+ /* This is a good query */
+ while(x < flow->packet.payload_packet_len) {
+ if(flow->packet.payload[x] == '\0') {
+ x++;
+ flow->protos.dns.query_type = get16(&x, flow->packet.payload);
+#ifdef DNS_DEBUG
+ NDPI_LOG_DBG2(ndpi_struct, "query_type=%2d\n", flow->protos.dns.query_type);
+ printf("[DNS] query_type=%d\n", flow->protos.dns.query_type);
+#endif
+ break;
+ } else
+ x++;
+ }
+ } else
+ return(1 /* invalid */);
+ } else {
+ /* DNS Reply */
+ flow->protos.dns.reply_code = dns_header->flags & 0x0F;
+
+ if((dns_header->num_queries > 0) && (dns_header->num_queries <= NDPI_MAX_DNS_REQUESTS) /* Don't assume that num_queries must be zero */
+ && (((dns_header->num_answers > 0) && (dns_header->num_answers <= NDPI_MAX_DNS_REQUESTS))
+ || ((dns_header->authority_rrs > 0) && (dns_header->authority_rrs <= NDPI_MAX_DNS_REQUESTS))
+ || ((dns_header->additional_rrs > 0) && (dns_header->additional_rrs <= NDPI_MAX_DNS_REQUESTS)))
+ ) {
+ /* This is a good reply: we dissect it both for request and response */
+
+ /* Leave the statement below commented necessary in case of call to ndpi_get_partial_detection() */
+ /* if(ndpi_struct->dns_dont_dissect_response == 0) */ {
+ x++;
+
+ if(flow->packet.payload[x] != '\0') {
+ while((x < flow->packet.payload_packet_len)
+ && (flow->packet.payload[x] != '\0')) {
+ x++;
+ }
+
+ x++;
+ }
+
+ x += 4;
+
+ if(dns_header->num_answers > 0) {
+ u_int16_t rsp_type;
+ u_int16_t num;
+
+ for(num = 0; num < dns_header->num_answers; num++) {
+ u_int16_t data_len;
+
+ if((x+6) >= flow->packet.payload_packet_len) {
+ break;
+ }
+
+ if((data_len = getNameLength(x, flow->packet.payload, flow->packet.payload_packet_len)) == 0) {
+ break;
+ } else
+ x += data_len;
+
+ rsp_type = get16(&x, flow->packet.payload);
+ flow->protos.dns.rsp_type = rsp_type;
+
+ /* here x points to the response "class" field */
+ if((x+12) <= flow->packet.payload_packet_len) {
+ x += 6;
+ data_len = get16(&x, flow->packet.payload);
+
+ if(((x + data_len) <= flow->packet.payload_packet_len)
+ && (((rsp_type == 0x1) && (data_len == 4)) /* A */
+#ifdef NDPI_DETECTION_SUPPORT_IPV6
+ || ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */
+#endif
+ )) {
+ memcpy(&flow->protos.dns.rsp_addr, flow->packet.payload + x, data_len);
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ } else
+ return(1 /* invalid */);
+ }
+
+ /* Valid */
+ return(0);
+}
+
/* *********************************************** */
void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
- int x, payload_offset;
+ int payload_offset;
u_int8_t is_query;
u_int16_t s_port = 0, d_port = 0;
@@ -94,191 +215,97 @@ void ndpi_search_dns(struct ndpi_detection_module_struct *ndpi_struct, struct nd
return;
}
- x = payload_offset;
-
if((s_port == 53 || d_port == 53 || d_port == 5355)
- && (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header)+x)) {
+ && (flow->packet.payload_packet_len > sizeof(struct ndpi_dns_packet_header)+payload_offset)) {
struct ndpi_dns_packet_header dns_header;
- int invalid = 0;
-
- memcpy(&dns_header, (struct ndpi_dns_packet_header*) &flow->packet.payload[x], sizeof(struct ndpi_dns_packet_header));
- dns_header.tr_id = ntohs(dns_header.tr_id);
- dns_header.flags = ntohs(dns_header.flags);
- dns_header.num_queries = ntohs(dns_header.num_queries);
- dns_header.num_answers = ntohs(dns_header.num_answers);
- dns_header.authority_rrs = ntohs(dns_header.authority_rrs);
- dns_header.additional_rrs = ntohs(dns_header.additional_rrs);
- x += sizeof(struct ndpi_dns_packet_header);
-
- /* 0x0000 QUERY */
- if((dns_header.flags & FLAGS_MASK) == 0x0000)
- is_query = 1;
- /* 0x8000 RESPONSE */
- else if((dns_header.flags & FLAGS_MASK) == 0x8000)
- is_query = 0;
- else
- invalid = 1;
-
- if(!invalid) {
- int j = 0, max_len, off;
- if(is_query) {
- /* DNS Request */
- if((dns_header.num_queries > 0) && (dns_header.num_queries <= NDPI_MAX_DNS_REQUESTS)
- && (((dns_header.flags & 0x2800) == 0x2800 /* Dynamic DNS Update */)
- || ((dns_header.num_answers == 0) && (dns_header.authority_rrs == 0)))) {
- /* This is a good query */
-
- while(x < flow->packet.payload_packet_len) {
- if(flow->packet.payload[x] == '\0') {
- x++;
- flow->protos.dns.query_type = get16(&x, flow->packet.payload);
-#ifdef DNS_DEBUG
- NDPI_LOG_DBG2(ndpi_struct, "query_type=%2d\n", flow->protos.dns.query_type);
-#endif
- break;
- } else
- x++;
- }
- } else
- invalid = 1;
- } else {
- /* DNS Reply */
-
- flow->protos.dns.reply_code = dns_header.flags & 0x0F;
-
- if((dns_header.num_queries > 0) && (dns_header.num_queries <= NDPI_MAX_DNS_REQUESTS) /* Don't assume that num_queries must be zero */
- && (((dns_header.num_answers > 0) && (dns_header.num_answers <= NDPI_MAX_DNS_REQUESTS))
- || ((dns_header.authority_rrs > 0) && (dns_header.authority_rrs <= NDPI_MAX_DNS_REQUESTS))
- || ((dns_header.additional_rrs > 0) && (dns_header.additional_rrs <= NDPI_MAX_DNS_REQUESTS)))
- ) {
- /* This is a good reply: we dissect it both for request and response */
-
- /* Leave the statement below commented necessary in case of call to ndpi_get_partial_detection() */
- /* if(ndpi_struct->dns_dont_dissect_response == 0) */ {
- x++;
-
- if(flow->packet.payload[x] != '\0') {
- while((x < flow->packet.payload_packet_len)
- && (flow->packet.payload[x] != '\0')) {
- x++;
- }
-
- x++;
- }
-
- x += 4;
-
- if(dns_header.num_answers > 0) {
- u_int16_t rsp_type;
- u_int16_t num;
-
- for(num = 0; num < dns_header.num_answers; num++) {
- u_int16_t data_len;
-
- if((x+6) >= flow->packet.payload_packet_len) {
- break;
- }
-
- if((data_len = getNameLength(x, flow->packet.payload, flow->packet.payload_packet_len)) == 0) {
- break;
- } else
- x += data_len;
+ int j = 0, max_len, off;
+ int invalid = search_valid_dns(ndpi_struct, flow, &dns_header, payload_offset, &is_query);
+ ndpi_protocol ret;
+
+ ret.master_protocol = NDPI_PROTOCOL_UNKNOWN;
+ ret.app_protocol = (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS;
+
+ if(invalid) {
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ return;
+ }
- rsp_type = get16(&x, flow->packet.payload);
- flow->protos.dns.rsp_type = rsp_type;
+ /* extract host name server */
+ max_len = sizeof(flow->host_server_name)-1;
+ off = sizeof(struct ndpi_dns_packet_header) + payload_offset;
- /* here x points to the response "class" field */
- if((x+12) <= flow->packet.payload_packet_len) {
- x += 6;
- data_len = get16(&x, flow->packet.payload);
+ while(j < max_len && off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') {
+ uint8_t c, cl = flow->packet.payload[off++];
- if(((x + data_len) <= flow->packet.payload_packet_len)
- && (((rsp_type == 0x1) && (data_len == 4)) /* A */
-#ifdef NDPI_DETECTION_SUPPORT_IPV6
- || ((rsp_type == 0x1c) && (data_len == 16)) /* AAAA */
-#endif
- )) {
- memcpy(&flow->protos.dns.rsp_addr, flow->packet.payload + x, data_len);
- }
- }
-
- break;
- }
- }
- }
- } else
- invalid = 1;
+ if( (cl & 0xc0) != 0 || // we not support compressed names in query
+ off + cl >= flow->packet.payload_packet_len) {
+ j = 0;
+ break;
}
- if(invalid) {
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- return;
- }
-
- /* extract host name server */
- max_len = sizeof(flow->host_server_name)-1;
- off = sizeof(struct ndpi_dns_packet_header) + payload_offset;
-
- while(j < max_len && off < flow->packet.payload_packet_len && flow->packet.payload[off] != '\0') {
- uint8_t c, cl = flow->packet.payload[off++];
-
- if( (cl & 0xc0) != 0 || // we not support compressed names in query
- off + cl >= flow->packet.payload_packet_len) {
- j = 0;
- break;
- }
-
- if(j && j < max_len) flow->host_server_name[j++] = '.';
-
- while(j < max_len && cl != 0) {
- c = flow->packet.payload[off++];
- flow->host_server_name[j++] = (dns_validchar[c >> 5] & (1 << (c & 0x1f))) ? c : '_';
- cl--;
- }
- }
- flow->host_server_name[j] = '\0';
+ if(j && j < max_len) flow->host_server_name[j++] = '.';
- if(is_query && (ndpi_struct->dns_dont_dissect_response == 0)) {
- // dpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
- return; /* The response will set the verdict */
+ while(j < max_len && cl != 0) {
+ c = flow->packet.payload[off++];
+ flow->host_server_name[j++] = (dns_validchar[c >> 5] & (1 << (c & 0x1f))) ? c : '_';
+ cl--;
}
+ }
+ flow->host_server_name[j] = '\0';
+
+ if(j > 0) {
+ ndpi_protocol_match_result ret_match;
+
+ ret.app_protocol = ndpi_match_host_subprotocol(ndpi_struct, flow,
+ (char *)flow->host_server_name,
+ strlen((const char*)flow->host_server_name),
+ &ret_match,
+ NDPI_PROTOCOL_DNS);
+
+ if(ret_match.protocol_category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)
+ flow->category = ret_match.protocol_category;
+
+ if(ret.app_protocol == NDPI_PROTOCOL_UNKNOWN)
+ ret.master_protocol = (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS;
+ else
+ ret.master_protocol = NDPI_PROTOCOL_DNS;
+ }
+
+ if(is_query && (ndpi_struct->dns_dont_dissect_response == 0)) {
+ /* In this case we say that the protocol has been detected just to let apps carry on with their activities */
+ ndpi_set_detected_protocol(ndpi_struct, flow, ret.app_protocol, ret.master_protocol);
+ return; /* The response will set the verdict */
+ }
- flow->protos.dns.num_queries = (u_int8_t)dns_header.num_queries,
+ flow->protos.dns.num_queries = (u_int8_t)dns_header.num_queries,
flow->protos.dns.num_answers = (u_int8_t) (dns_header.num_answers + dns_header.authority_rrs + dns_header.additional_rrs);
- if(j > 0) {
- ndpi_protocol_match_result ret_match;
-
- ndpi_match_host_subprotocol(ndpi_struct, flow,
- (char *)flow->host_server_name,
- strlen((const char*)flow->host_server_name),
- &ret_match,
- NDPI_PROTOCOL_DNS);
- }
-
#ifdef DNS_DEBUG
- NDPI_LOG_DBG2(ndpi_struct, "[num_queries=%d][num_answers=%d][reply_code=%u][rsp_type=%u][host_server_name=%s]\n",
- flow->protos.dns.num_queries, flow->protos.dns.num_answers,
- flow->protos.dns.reply_code, flow->protos.dns.rsp_type, flow->host_server_name
- );
+ NDPI_LOG_DBG2(ndpi_struct, "[num_queries=%d][num_answers=%d][reply_code=%u][rsp_type=%u][host_server_name=%s]\n",
+ flow->protos.dns.num_queries, flow->protos.dns.num_answers,
+ flow->protos.dns.reply_code, flow->protos.dns.rsp_type, flow->host_server_name
+ );
#endif
- if(flow->packet.detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
- /**
- Do not set the protocol with DNS if ndpi_match_host_subprotocol() has
- matched a subprotocol
- **/
- NDPI_LOG_INFO(ndpi_struct, "found DNS\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, (d_port == 5355) ? NDPI_PROTOCOL_LLMNR : NDPI_PROTOCOL_DNS, NDPI_PROTOCOL_UNKNOWN);
- } else {
+ if(flow->packet.detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) {
+ /**
+ Do not set the protocol with DNS if ndpi_match_host_subprotocol() has
+ matched a subprotocol
+ **/
+ NDPI_LOG_INFO(ndpi_struct, "found DNS\n");
+ ndpi_set_detected_protocol(ndpi_struct, flow, ret.app_protocol, ret.master_protocol);
+ } else {
+ if((flow->packet.detected_protocol_stack[0] == NDPI_PROTOCOL_DNS)
+ || (flow->packet.detected_protocol_stack[1] == NDPI_PROTOCOL_DNS))
+ ;
+ else
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- }
}
}
}
-void init_dns_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
-{
+void init_dns_dissector(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) {
ndpi_set_bitmask_protocol_detection("DNS", ndpi_struct, detection_bitmask, *id,
NDPI_PROTOCOL_DNS,
ndpi_search_dns,
diff --git a/src/lib/protocols/skype.c b/src/lib/protocols/skype.c
index 2f3aac2f6..8ada5d997 100644
--- a/src/lib/protocols/skype.c
+++ b/src/lib/protocols/skype.c
@@ -23,13 +23,6 @@
#include "ndpi_api.h"
-static void ndpi_skype_report_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
- /* printf("-> payload_len=%u\n", flow->packet.payload_packet_len); */
-
- NDPI_LOG_INFO(ndpi_struct, "found skype\n");
- ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
-}
-
static int is_port(u_int16_t a, u_int16_t b, u_int16_t c) {
return(((a == c) || (b == c)) ? 1 : 0);
}
@@ -60,7 +53,11 @@ static void ndpi_check_skype(struct ndpi_detection_module_struct *ndpi_struct, s
((payload_len >= 16)
&& (packet->payload[0] != 0x30) /* Avoid invalid SNMP detection */
&& (packet->payload[2] == 0x02))) {
- ndpi_skype_report_protocol(ndpi_struct, flow);
+
+ if(is_port(sport, dport, 8801))
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_ZOOM, NDPI_PROTOCOL_UNKNOWN);
+ else
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
}
}
@@ -90,7 +87,7 @@ static void ndpi_check_skype(struct ndpi_detection_module_struct *ndpi_struct, s
/* printf("[SKYPE] %u/%u\n", ntohs(packet->tcp->source), ntohs(packet->tcp->dest)); */
NDPI_LOG_INFO(ndpi_struct, "found skype\n");
- ndpi_skype_report_protocol(ndpi_struct, flow);
+ ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE);
} else {
// printf("NO [SKYPE] payload_len=%u\n", payload_len);
}
diff --git a/src/lib/protocols/steam.c b/src/lib/protocols/steam.c
index 0a737baf9..6e1034aee 100644
--- a/src/lib/protocols/steam.c
+++ b/src/lib/protocols/steam.c
@@ -1,6 +1,7 @@
/*
* steam.c
*
+ * Copyright (C) 2011-19 - ntop.org
* Copyright (C) 2014 Tomasz Bujlow <tomasz@skatnet.dk>
*
* The signature is mostly based on the Libprotoident library
@@ -242,52 +243,55 @@ static void ndpi_check_steam_udp3(struct ndpi_detection_module_struct *ndpi_stru
void ndpi_search_steam(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) {
struct ndpi_packet_struct *packet = &flow->packet;
- /* Break after 20 packets. */
- if (flow->packet_counter > 20) {
- NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
- return;
- }
-
- /* skip marked or retransmitted packets */
- if (packet->tcp_retransmission != 0) {
- return;
- }
-
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
- return;
- }
-
- NDPI_LOG_DBG(ndpi_struct, "search STEAM\n");
- ndpi_check_steam_http(ndpi_struct, flow);
+ if(flow->packet.udp != NULL) {
+ if(flow->packet_counter > 5) {
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ return;
+ }
+
+ ndpi_check_steam_udp1(ndpi_struct, flow);
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
- return;
- }
-
- ndpi_check_steam_tcp(ndpi_struct, flow);
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM)
+ return;
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
- return;
- }
+ ndpi_check_steam_udp2(ndpi_struct, flow);
- ndpi_check_steam_udp1(ndpi_struct, flow);
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM)
+ return;
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
- return;
- }
+ ndpi_check_steam_udp3(ndpi_struct, flow);
+ } else {
+ /* Break after 10 packets. */
+ if(flow->packet_counter > 10) {
+ NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
+ return;
+ }
+
+
+ /* skip marked or retransmitted packets */
+ if(packet->tcp_retransmission != 0) {
+ return;
+ }
+
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM)
+ return;
+
+ NDPI_LOG_DBG(ndpi_struct, "search STEAM\n");
+ ndpi_check_steam_http(ndpi_struct, flow);
- ndpi_check_steam_udp2(ndpi_struct, flow);
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM)
+ return;
+
+ ndpi_check_steam_tcp(ndpi_struct, flow);
- if (packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM) {
- return;
+ if(packet->detected_protocol_stack[0] == NDPI_PROTOCOL_STEAM)
+ return;
}
-
- ndpi_check_steam_udp3(ndpi_struct, flow);
}
-void init_steam_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
-{
+void init_steam_dissector(struct ndpi_detection_module_struct *ndpi_struct,
+ u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) {
ndpi_set_bitmask_protocol_detection("Steam", ndpi_struct, detection_bitmask, *id,
NDPI_PROTOCOL_STEAM,
ndpi_search_steam,
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c
index bf2eb0b86..448062f47 100644
--- a/src/lib/protocols/stun.c
+++ b/src/lib/protocols/stun.c
@@ -38,22 +38,6 @@ struct stun_packet_header {
u_int8_t transaction_id[8];
};
-/* ************************************************************ */
-
-static u_int8_t is_stun_based_proto(u_int16_t proto) {
-
- switch(proto) {
- case NDPI_PROTOCOL_WHATSAPP_CALL:
- case NDPI_PROTOCOL_MESSENGER:
- case NDPI_PROTOCOL_HANGOUT_DUO:
- case NDPI_PROTOCOL_SKYPE_CALL:
- case NDPI_PROTOCOL_SIGNAL:
- case NDPI_PROTOCOL_STUN:
- return(1);
- }
-
- return(0);
-}
/* ************************************************************ */
@@ -160,10 +144,11 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
const u_int16_t payload_length) {
u_int16_t msg_type, msg_len;
struct stun_packet_header *h = (struct stun_packet_header*)payload;
- u_int8_t can_this_be_whatsapp_voice = 1;
-
+ int rc;
+
/* STUN over TCP does not look good */
- if(flow->packet.tcp) return(NDPI_IS_NOT_STUN);
+ if (flow->packet.tcp)
+ return(NDPI_IS_NOT_STUN);
if(payload_length >= 512) {
return(NDPI_IS_NOT_STUN);
@@ -172,7 +157,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
if(flow->protos.stun_ssl.stun.num_udp_pkts > 0) {
flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
- return(NDPI_IS_STUN); /* This is WhatsApp Voice */
+ return(NDPI_IS_STUN);
} else
return(NDPI_IS_NOT_STUN);
}
@@ -183,52 +168,40 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
goto udp_stun_found;
}
- msg_type = ntohs(h->msg_type) /* & 0x3EEF */, msg_len = ntohs(h->msg_len);
+ msg_type = ntohs(h->msg_type), msg_len = ntohs(h->msg_len);
+ if(msg_type == 0)
+ return(NDPI_IS_NOT_STUN);
+
/* https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml */
- if(msg_type > 0x000C) {
+ if ((msg_type & 0x3EEF) > 0x000B && msg_type != 0x0800) {
#ifdef DEBUG_STUN
printf("[STUN] msg_type = %04X\n", msg_type);
#endif
- if(is_stun_based_proto(flow->guessed_host_protocol_id)) {
- /*
- In this case we have the detected the typical STUN pattern
- of modern protocols where the flow starts as STUN and becomes
- something else that has nothing to do with STUN anymore
- */
- ndpi_int_stun_add_connection(ndpi_struct, flow,
- flow->guessed_protocol_id,
- flow->guessed_host_protocol_id);
- return(NDPI_IS_STUN);
- }
-
/*
- If we're here it's because this does not look like STUN anymore
- as this was a flow that started as STUN and turned into something
- else. Let's investigate what is that about
- */
- if(payload[0] == 0x16) {
+ If we're here it's because this does not look like STUN anymore
+ as this was a flow that started as STUN and turned into something
+ else. Let's investigate what is that about
+ */
+ if (payload[0] == 0x16) {
/* Let's check if this is DTLS used by some socials */
struct ndpi_packet_struct *packet = &flow->packet;
- u_int16_t total_len, version = htons(*((u_int16_t*)&packet->payload[1]));
-
- switch(version) {
- case 0xFEFF: /* DTLS 1.0 */
- case 0xFEFD: /* DTLS 1.2 */
- total_len = ntohs(*((u_int16_t*)&packet->payload[11]))+13;
-
- if(payload_length == total_len) {
- /* This is DTLS and the only protocol we know behaves like this is signal */
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_SIGNAL;
- ndpi_int_stun_add_connection(ndpi_struct, flow,
- flow->guessed_protocol_id,
- flow->guessed_host_protocol_id);
- return(NDPI_IS_STUN);
- }
+ u_int16_t total_len, version = htons(*((u_int16_t*) &packet->payload[1]));
+
+ switch (version) {
+ case 0xFEFF: /* DTLS 1.0 */
+ case 0xFEFD: /* DTLS 1.2 */
+ total_len = ntohs(*((u_int16_t*) &packet->payload[11])) + 13;
+
+ if (payload_length == total_len) {
+ /* This is DTLS and the only protocol we know behaves like this is signal */
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_SIGNAL;
+ return(NDPI_IS_STUN);
+ }
}
}
-
+
return(NDPI_IS_NOT_STUN);
}
@@ -239,31 +212,32 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
printf("[STUN] Here we go\n");;
#endif
- if(ndpi_struct->stun_cache) {
+ if (ndpi_struct->stun_cache) {
u_int16_t proto;
u_int32_t key = get_stun_lru_key(flow, 0);
- int rc = ndpi_lru_find_cache(ndpi_struct->stun_cache, key, &proto, 0 /* Don't remove it as it can be used for other connections */);
+ int rc = ndpi_lru_find_cache(ndpi_struct->stun_cache, key, &proto,
+ 0 /* Don't remove it as it can be used for other connections */);
#ifdef DEBUG_LRU
printf("[LRU] Searching %u\n", key);
#endif
- if(!rc) {
+ if (!rc) {
key = get_stun_lru_key(flow, 1);
- rc = ndpi_lru_find_cache(ndpi_struct->stun_cache, key, &proto, 0 /* Don't remove it as it can be used for other connections */);
+ rc = ndpi_lru_find_cache(ndpi_struct->stun_cache, key, &proto,
+ 0 /* Don't remove it as it can be used for other connections */);
#ifdef DEBUG_LRU
- printf("[LRU] Searching %u\n", key);
+ printf("[LRU] Searching %u\n", key);
#endif
}
- if(rc) {
+ if (rc) {
#ifdef DEBUG_LRU
printf("[LRU] Cache FOUND %u / %u\n", key, proto);
#endif
- flow->guessed_host_protocol_id = proto, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
-
+ flow->guessed_host_protocol_id = proto;
return(NDPI_IS_STUN);
} else {
#ifdef DEBUG_LRU
@@ -279,42 +253,34 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
if(msg_type == 0x01 /* Binding Request */) {
flow->protos.stun_ssl.stun.num_binding_requests++;
- if((msg_len == 0) && (flow->guessed_host_protocol_id == NDPI_PROTOCOL_GOOGLE))
+ if (!msg_len && flow->guessed_host_protocol_id == NDPI_PROTOCOL_GOOGLE)
flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
else
flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
- if(msg_len == 0) {
+ if (!msg_len) {
/* flow->protos.stun_ssl.stun.num_udp_pkts++; */
return(NDPI_IS_NOT_STUN); /* This to keep analyzing STUN instead of giving up */
}
}
- if((msg_len == 0) && (flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN)) {
+ if (!msg_len && flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) {
NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
return(NDPI_IS_NOT_STUN);
}
flow->protos.stun_ssl.stun.num_udp_pkts++;
- /*
- printf("[msg_type: %04X][payload_length: %u][num_binding_request: %u]\n",
- msg_type, payload_length, flow->protos.stun_ssl.stun.num_binding_requests);
- */
-
- if(((payload[0] == 0x80)
- && (payload_length < 512)
- && ((msg_len+20) <= payload_length)) /* WhatsApp Voice */) {
+ if((payload[0] == 0x80 && payload_length < 512 && ((msg_len+20) <= payload_length))) {
flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
- return(NDPI_IS_STUN); /* This is WhatsApp Voice */
- } else if((payload[0] == 0x90)
- && (((msg_len+11) == payload_length) /* WhatsApp Video */
- || (flow->protos.stun_ssl.stun.num_binding_requests >= 4))) {
+ return(NDPI_IS_STUN); /* This is WhatsApp Call */
+ } else if((payload[0] == 0x90) && (((msg_len+11) == payload_length) ||
+ (flow->protos.stun_ssl.stun.num_binding_requests >= 4))) {
flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
- return(NDPI_IS_STUN); /* This is WhatsApp Video */
+ return(NDPI_IS_STUN); /* This is WhatsApp Call */
}
- if((payload[0] != 0x80) && ((msg_len+20) > payload_length))
+ if (payload[0] != 0x80 && (msg_len + 20) > payload_length)
return(NDPI_IS_NOT_STUN);
else {
switch(flow->guessed_protocol_id) {
@@ -330,202 +296,186 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *
}
}
- if(payload_length == (msg_len+20)) {
- if(msg_type <= 0x000b) /* http://www.3cx.com/blog/voip-howto/stun-details/ */ {
+ if (payload_length == (msg_len+20)) {
+ if ((msg_type & 0x3EEF) <= 0x000B) /* http://www.3cx.com/blog/voip-howto/stun-details/ */ {
u_int offset = 20;
- // printf("[%02X][%02X][%02X][%02X][payload_length: %u]\n", payload[offset], payload[offset+1], payload[offset+2], payload[offset+3],payload_length);
-
/*
- This can either be the standard RTCP or Ms Lync RTCP that
- later will become Ms Lync RTP. In this case we need to
- be careful before deciding about the protocol before dissecting the packet
+ This can either be the standard RTCP or Ms Lync RTCP that
+ later will become Ms Lync RTP. In this case we need to
+ be careful before deciding about the protocol before dissecting the packet
- MS Lync = Skype
- https://en.wikipedia.org/wiki/Skype_for_Business
- */
+ MS Lync = Skype
+ https://en.wikipedia.org/wiki/Skype_for_Business
+ */
while((offset+2) < payload_length) {
- u_int16_t attribute = ntohs(*((u_int16_t*)&payload[offset]));
- u_int16_t len = ntohs(*((u_int16_t*)&payload[offset+2]));
- u_int16_t x = (len + 4) % 4;
+ u_int16_t attribute = ntohs(*((u_int16_t*)&payload[offset]));
+ u_int16_t len = ntohs(*((u_int16_t*)&payload[offset+2]));
+ u_int16_t x = (len + 4) % 4;
- if(x != 0)
- len += 4-x;
+ if (x)
+ len += 4-x;
#ifdef DEBUG_STUN
- printf("==> Attribute: %04X\n", attribute);
+ printf("==> Attribute: %04X\n", attribute);
#endif
- switch(attribute) {
- // case 0x0008: /* Message Integrity */
- // case 0x0020: /* XOR-MAPPED-ADDRESSES */
- case 0x4000:
- case 0x4001:
- case 0x4002:
- /* These are the only messages apparently whatsapp voice can use */
+ switch(attribute) {
+ case 0x0103:
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_ZOOM;
+ return(NDPI_IS_STUN);
break;
+
+ case 0x4000:
+ case 0x4001:
+ case 0x4002:
+ /* These are the only messages apparently whatsapp voice can use */
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
+ return(NDPI_IS_STUN);
+ break;
- case 0x0014: /* Realm */
- {
- u_int16_t realm_len = ntohs(*((u_int16_t*)&payload[offset+2]));
+ case 0x0014: /* Realm */
+ {
+ u_int16_t realm_len = ntohs(*((u_int16_t*)&payload[offset+2]));
- if(flow->host_server_name[0] == '\0') {
- u_int j, i = (realm_len > sizeof(flow->host_server_name)) ? sizeof(flow->host_server_name) : realm_len;
- u_int k = offset+4;
+ if(flow->host_server_name[0] == '\0') {
+ u_int j, i = (realm_len > sizeof(flow->host_server_name)) ? sizeof(flow->host_server_name) : realm_len;
+ u_int k = offset+4;
- memset(flow->host_server_name, 0, sizeof(flow->host_server_name));
+ memset(flow->host_server_name, 0, sizeof(flow->host_server_name));
- for(j=0; j<i; j++)
- flow->host_server_name[j] = payload[k++];
+ for(j=0; j<i; j++)
+ flow->host_server_name[j] = payload[k++];
#ifdef DEBUG_STUN
- printf("==> [%s]\n", flow->host_server_name);
+ printf("==> [%s]\n", flow->host_server_name);
#endif
- if(strstr((char*)flow->host_server_name, "google.com") != NULL) {
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
- return(NDPI_IS_STUN);
- } else if(strstr((char*)flow->host_server_name, "whispersystems.org") != NULL) {
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_SIGNAL, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
- return(NDPI_IS_STUN);
- }
- }
- }
- break;
-
- case 0xC057: /* Messeger */
- if(msg_type == 0x0001) {
- if((msg_len == 100) || (msg_len == 104)) {
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_MESSENGER, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
- return(NDPI_IS_STUN);
- } else if(msg_len == 76) {
+ if (strstr((char*) flow->host_server_name, "google.com") != NULL) {
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
+ return(NDPI_IS_STUN);
+ } else if (strstr((char*) flow->host_server_name, "whispersystems.org") != NULL) {
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_SIGNAL;
+ return(NDPI_IS_STUN);
+ }
+ }
+ }
+ break;
+
+ case 0xC057: /* Messeger */
+ if (msg_type == 0x0001) {
+ if ((msg_len == 100) || (msg_len == 104)) {
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_MESSENGER;
+ return(NDPI_IS_STUN);
+ } else if(msg_len == 76) {
#if 0
- if(1) {
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO, flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
- return(NDPI_IS_NOT_STUN); /* This case is found also with signal traffic */
- } else
- return(NDPI_IS_STUN);
+ if(1) {
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
+ return(NDPI_IS_NOT_STUN); /* This case is found also with signal traffic */
+ } else
+ return(NDPI_IS_STUN);
#endif
- }
- }
- break;
-
- case 0x8054: /* Candidate Identifier */
- if((len == 4)
- && ((offset+7) < payload_length)
- && (payload[offset+5] == 0x00)
- && (payload[offset+6] == 0x00)
- && (payload[offset+7] == 0x00)) {
- /* Either skype for business or "normal" skype with multiparty call */
+ }
+ }
+ break;
+
+ case 0x8054: /* Candidate Identifier */
+ if((len == 4)
+ && ((offset+7) < payload_length)
+ && (payload[offset+5] == 0x00)
+ && (payload[offset+6] == 0x00)
+ && (payload[offset+7] == 0x00)) {
+ /* Either skype for business or "normal" skype with multiparty call */
#ifdef DEBUG_STUN
- printf("==> Skype found\n");
+ printf("==> Skype found\n");
#endif
- flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
- return(NDPI_IS_STUN);
- }
- break;
-
- case 0x8055: /* MS Service Quality (skype?) */
- break;
-
- /* Proprietary fields found on skype calls */
- case 0x24DF:
- case 0x3802:
- case 0x8036:
- case 0x8095:
- case 0x0800:
- case 0x8006: /* This is found on skype calls) */
- /* printf("====>>>> %04X\n", attribute); */
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
+ return(NDPI_IS_STUN);
+ }
+
+ break;
+
+ case 0x8055: /* MS Service Quality (skype?) */
+ break;
+
+ /* Proprietary fields found on skype calls */
+ case 0x24DF:
+ case 0x3802:
+ case 0x8036:
+ case 0x8095:
+ case 0x0800:
+ case 0x8006: /* This is found on skype calls) */
+ /* printf("====>>>> %04X\n", attribute); */
#ifdef DEBUG_STUN
- printf("==> Skype (2) found\n");
+ printf("==> Skype (2) found\n");
#endif
- flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
- return(NDPI_IS_STUN);
- break;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
+ return(NDPI_IS_STUN);
+ break;
- case 0x8070: /* Implementation Version */
- if((len == 4)
- && ((offset+7) < payload_length)
- && (payload[offset+4] == 0x00)
- && (payload[offset+5] == 0x00)
- && (payload[offset+6] == 0x00)
- && ((payload[offset+7] == 0x02) || (payload[offset+7] == 0x03))
- ) {
- flow->guessed_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
+ case 0x8070: /* Implementation Version */
+ if (len == 4 && ((offset+7) < payload_length)
+ && (payload[offset+4] == 0x00) && (payload[offset+5] == 0x00) && (payload[offset+6] == 0x00) &&
+ ((payload[offset+7] == 0x02) || (payload[offset+7] == 0x03))) {
#ifdef DEBUG_STUN
- printf("==> Skype (3) found\n");
+ printf("==> Skype (3) found\n");
#endif
- return(NDPI_IS_STUN);
- }
- break;
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_SKYPE_CALL;
+ return(NDPI_IS_STUN);
+ }
+ break;
- case 0xFF03:
- can_this_be_whatsapp_voice = 0;
- flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
- break;
+ case 0xFF03:
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
+ return(NDPI_IS_STUN);
+ break;
- default:
- /* This means this STUN packet cannot be confused with whatsapp voice */
+ default:
#ifdef DEBUG_STUN
- printf("==> %04X\n", attribute);
+ printf("==> %04X\n", attribute);
#endif
- can_this_be_whatsapp_voice = 0;
- break;
- }
+ break;
+ }
- offset += len + 4;
+ offset += len + 4;
}
+
goto udp_stun_found;
} else if(msg_type == 0x0800) {
flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
- return(NDPI_IS_STUN); /* This is WhatsApp */
+ return(NDPI_IS_STUN);
}
}
- if((flow->protos.stun_ssl.stun.num_udp_pkts > 0) && (msg_type <= 0x00FF)) {
+ if ((flow->protos.stun_ssl.stun.num_udp_pkts > 0) && (msg_type <= 0x00FF)) {
flow->guessed_host_protocol_id = NDPI_PROTOCOL_WHATSAPP_CALL;
- return(NDPI_IS_STUN); /* This is WhatsApp Voice */
+ return(NDPI_IS_STUN);
} else
return(NDPI_IS_NOT_STUN);
- udp_stun_found:
- if(can_this_be_whatsapp_voice) {
- struct ndpi_packet_struct *packet = &flow->packet;
- int rc;
+udp_stun_found:
+ flow->protos.stun_ssl.stun.num_processed_pkts++;
+
+ struct ndpi_packet_struct *packet = &flow->packet;
- flow->protos.stun_ssl.stun.num_processed_pkts++;
#ifdef DEBUG_STUN
- printf("==>> NDPI_PROTOCOL_WHATSAPP_CALL\n");
+ printf("==>> NDPI_PROTOCOL_WHATSAPP_CALL\n");
#endif
- if((ntohs(packet->udp->source) == 3478) || (ntohs(packet->udp->dest) == 3478)) {
- flow->guessed_host_protocol_id = (is_messenger_ip_address(ntohl(packet->iph->saddr)) || is_messenger_ip_address(ntohl(packet->iph->daddr))) ?
- NDPI_PROTOCOL_MESSENGER : NDPI_PROTOCOL_WHATSAPP_CALL;
- } else
- flow->guessed_host_protocol_id = (is_google_ip_address(ntohl(packet->iph->saddr)) || is_google_ip_address(ntohl(packet->iph->daddr)))
- ? NDPI_PROTOCOL_HANGOUT_DUO : NDPI_PROTOCOL_WHATSAPP_CALL;
-
- rc = (flow->protos.stun_ssl.stun.num_udp_pkts < MAX_NUM_STUN_PKTS) ? NDPI_IS_NOT_STUN : NDPI_IS_STUN;
-
- if(rc == NDPI_IS_STUN)
- ndpi_int_stun_add_connection(ndpi_struct, flow,
- NDPI_IS_STUN,
- flow->guessed_host_protocol_id);
+ if(is_messenger_ip_address(ntohl(packet->iph->saddr)) || is_messenger_ip_address(ntohl(packet->iph->daddr)))
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_MESSENGER;
+ else if(is_google_ip_address(ntohl(packet->iph->saddr)) || is_google_ip_address(ntohl(packet->iph->daddr)))
+ flow->guessed_host_protocol_id = NDPI_PROTOCOL_HANGOUT_DUO;
+
+ rc = (flow->protos.stun_ssl.stun.num_udp_pkts < MAX_NUM_STUN_PKTS) ? NDPI_IS_NOT_STUN : NDPI_IS_STUN;
- return(rc);
- } else {
- /*
- We cannot immediately say that this is STUN as there are other protocols
- like GoogleHangout that might be candidates, thus we set the
- guessed protocol to STUN
- */
- return(NDPI_IS_NOT_STUN);
- }
+ return rc;
}
+
void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow)
{
struct ndpi_packet_struct *packet = &flow->packet;
@@ -557,7 +507,7 @@ void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct n
if(ndpi_int_check_stun(ndpi_struct, flow, packet->payload,
packet->payload_packet_len) == NDPI_IS_STUN) {
udp_stun_match:
- if(flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN)
+ if (flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN)
flow->guessed_protocol_id = NDPI_PROTOCOL_STUN;
if(flow->guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) {