diff options
author | Luca <deri@ntop.org> | 2015-06-04 18:44:09 +0200 |
---|---|---|
committer | Luca <deri@ntop.org> | 2015-06-04 18:44:09 +0200 |
commit | 4ce9dec54ecb18b7eb5b9123bfbfc6c57aa35c6b (patch) | |
tree | ed6349cbe9da3a26e424a5ceb6e0a4d94d30fe40 /src/lib/protocols/stun.c | |
parent | a31b0a3354d4a6f62ea9c338ed6f890136f1d3e6 (diff) |
Reworked the STUN plugin
Added support for WhatsApp Voice vs WhatsApp (chat, no voice)
Diffstat (limited to 'src/lib/protocols/stun.c')
-rw-r--r-- | src/lib/protocols/stun.c | 110 |
1 files changed, 74 insertions, 36 deletions
diff --git a/src/lib/protocols/stun.c b/src/lib/protocols/stun.c index 09ec4a050..c613ae242 100644 --- a/src/lib/protocols/stun.c +++ b/src/lib/protocols/stun.c @@ -27,12 +27,20 @@ #ifdef NDPI_PROTOCOL_STUN -static void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) -{ - ndpi_int_add_connection(ndpi_struct, flow, NDPI_PROTOCOL_STUN, NDPI_REAL_PROTOCOL); -} +#define MAX_NUM_STUN_PKTS 6 +struct stun_packet_header { + u_int16_t msg_type, msg_len; + u_int32_t cookie; + u_int8_t transaction_id[8]; +}; + +static void ndpi_int_stun_add_connection(struct ndpi_detection_module_struct *ndpi_struct, + u_int proto, + struct ndpi_flow_struct *flow) { + ndpi_int_add_connection(ndpi_struct, flow, proto, NDPI_REAL_PROTOCOL); +} typedef enum { NDPI_IS_STUN, @@ -40,18 +48,30 @@ typedef enum { } ndpi_int_stun_t; static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct *ndpi_struct, - const u_int8_t * payload, const u_int16_t payload_length) + struct ndpi_flow_struct *flow, + const u_int8_t * payload, + const u_int16_t payload_length, + u_int8_t *is_whatsapp) { - u_int16_t a; + u_int16_t msg_type, msg_len; + struct stun_packet_header *h = (struct stun_packet_header*)payload; + if(payload_length < sizeof(struct stun_packet_header)) + return(NDPI_IS_NOT_STUN); - if((payload_length > 13) - && (strncmp((const char*)payload, (const char*)"RSP/", 4) == 0) + if((strncmp((const char*)payload, (const char*)"RSP/", 4) == 0) && (strncmp((const char*)&payload[7], (const char*)" STUN_", 6) == 0)) { NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "Found stun.\n"); - return NDPI_IS_STUN; + goto udp_stun_found; } + + msg_type = ntohs(h->msg_type) & 0x3EEF, msg_len = ntohs(h->msg_len); + if((payload_length == (msg_len+20)) + && ((msg_type <= 0x000b) /* http://www.3cx.com/blog/voip-howto/stun-details/ */)) + goto udp_stun_found; + +#ifdef ORIGINAL_CODE /* * token list of message types and attribute types from * http://wwwbs1.informatik.htw-dresden.de/svortrag/i02/Schoene/stun/stun.html @@ -68,7 +88,7 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * * 0x8003, 0x8004 used by facetime */ - if (payload_length >= 20 && ntohs(get_u_int16_t(payload, 2)) + 20 == payload_length && + if(payload_length >= 20 && ntohs(get_u_int16_t(payload, 2)) + 20 == payload_length && ((payload[0] == 0x00 && (payload[1] >= 0x01 && payload[1] <= 0x04)) || (payload[0] == 0x01 && ((payload[1] >= 0x01 && payload[1] <= 0x04) || (payload[1] >= 0x11 && payload[1] <= 0x15))))) { @@ -77,16 +97,16 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * u_int8_t padding = 0; NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "len and type match.\n"); - if (payload_length == 20) { + if(payload_length == 20) { NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found stun.\n"); - return NDPI_IS_STUN; + goto udp_stun_found; } a = 20; while (a < payload_length) { - if (old && payload_length >= a + 4 + if(old && payload_length >= a + 4 && ((payload[a] == 0x00 && ((payload[a + 1] >= 0x01 && payload[a + 1] <= 0x16) || payload[a + 1] == 0x19 @@ -103,16 +123,16 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * a += ((payload[a + 2] << 8) + payload[a + 3] + 4); mod = a % 4; - if (mod) { + if(mod) { padding = 4 - mod; } - if (a == payload_length || (padding && (a + padding) == payload_length)) { + if(a == payload_length || (padding && (a + padding) == payload_length)) { NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found stun.\n"); - return NDPI_IS_STUN; + goto udp_stun_found; } - } else if (payload_length >= a + padding + 4 - && + } else if(payload_length >= a + padding + 4 + && ((payload[a + padding] == 0x00 && ((payload[a + 1 + padding] >= 0x01 && payload[a + 1 + padding] <= 0x16) || payload[a + 1 + padding] == 0x19 || payload[a + 1 + padding] == 0x20 @@ -125,7 +145,11 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * || payload[a + 1 + padding] == 0x20 || payload[a + 1 + padding] == 0x22 || payload[a + 1 + padding] == 0x28 || payload[a + 1 + padding] == 0x2a || payload[a + 1 + padding] == 0x29 || payload[a + 1 + padding] == 0x50 - || payload[a + 1 + padding] == 0x54 || payload[a + 1 + padding] == 0x55)))) { + || payload[a + 1 + padding] == 0x54 || payload[a + 1 + padding] == 0x55)) + || ((payload[a + padding] == 0x40) && (payload[a + padding + 1] == 0x00)) + )) { + if((payload[a + padding] == 0x40) && (payload[a + padding + 1] == 0x00)) + goto udp_stun_found; NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "New STUN - attribute match.\n"); @@ -133,56 +157,70 @@ static ndpi_int_stun_t ndpi_int_check_stun(struct ndpi_detection_module_struct * a += ((payload[a + 2 + padding] << 8) + payload[a + 3 + padding] + 4); padding = 0; mod = a % 4; - if (mod) { + if(mod) { a += 4 - mod; } - if (a == payload_length) { + if(a == payload_length) { NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found stun.\n"); - return NDPI_IS_STUN; + goto udp_stun_found; } } else { break; } } } +#endif + - return NDPI_IS_NOT_STUN; + if((flow->num_stun_udp_pkts > 0) && ((payload[0] == 0x80) || (payload[0] == 0x81))) { + *is_whatsapp = 1; + return NDPI_IS_STUN; /* This is WhatsApp Voice */ + } else + return NDPI_IS_NOT_STUN; + + udp_stun_found: + flow->num_stun_udp_pkts++; + + return((flow->num_stun_udp_pkts < MAX_NUM_STUN_PKTS) ? NDPI_IS_NOT_STUN : NDPI_IS_STUN); } void ndpi_search_stun(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { struct ndpi_packet_struct *packet = &flow->packet; - + u_int8_t is_whatsapp = 0; NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "search stun.\n"); - - if (packet->tcp) { - + if(packet->tcp) { /* STUN may be encapsulated in TCP packets */ - if (packet->payload_packet_len >= 2 + 20 && + if(packet->payload_packet_len >= 2 + 20 && ntohs(get_u_int16_t(packet->payload, 0)) + 2 == packet->payload_packet_len) { - + /* TODO there could be several STUN packets in a single TCP packet so maybe the detection could be * improved by checking only the STUN packet of given length */ - if (ndpi_int_check_stun(ndpi_struct, packet->payload + 2, packet->payload_packet_len - 2) == - NDPI_IS_STUN) { + if(ndpi_int_check_stun(ndpi_struct, flow, packet->payload + 2, + packet->payload_packet_len - 2, &is_whatsapp) == NDPI_IS_STUN) { NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found TCP stun.\n"); - ndpi_int_stun_add_connection(ndpi_struct, flow); + ndpi_int_stun_add_connection(ndpi_struct, NDPI_PROTOCOL_STUN, flow); return; } } } - if (ndpi_int_check_stun(ndpi_struct, packet->payload, packet->payload_packet_len) == NDPI_IS_STUN) { + + if(ndpi_int_check_stun(ndpi_struct, flow, packet->payload, + packet->payload_packet_len, &is_whatsapp) == NDPI_IS_STUN) { NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "found UDP stun.\n"); - ndpi_int_stun_add_connection(ndpi_struct, flow); + ndpi_int_stun_add_connection(ndpi_struct, + is_whatsapp ? NDPI_PROTOCOL_WHATSAPP_VOICE : NDPI_PROTOCOL_STUN, flow); return; } - NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "exclude stun.\n"); - NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_STUN); + if(flow->num_stun_udp_pkts >= MAX_NUM_STUN_PKTS) { + NDPI_LOG(NDPI_PROTOCOL_STUN, ndpi_struct, NDPI_LOG_DEBUG, "exclude stun.\n"); + NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_STUN); + } } #endif |