diff options
-rw-r--r-- | example/ndpiReader.c | 141 | ||||
-rw-r--r-- | src/include/ndpi_api.h | 21 | ||||
-rw-r--r-- | src/include/ndpi_main.h | 2 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 7 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 199 | ||||
-rw-r--r-- | tests/result/whatsapp_login_call.pcap.out | 6 |
6 files changed, 208 insertions, 168 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c index 80c6a7ac1..adf8b2269 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -76,7 +76,7 @@ static char *_jsonFilePath = NULL; /**< JSON file path */ #ifdef HAVE_JSON_C static json_object *jArray_known_flows, *jArray_unknown_flows; #endif -static u_int8_t live_capture = 0, full_http_dissection = 1; +static u_int8_t live_capture = 0; static u_int8_t undetected_flows_deleted = 0; /** * User preferences @@ -176,7 +176,7 @@ typedef struct ndpi_flow { u_int32_t packets; // result only, not used for flow identification - u_int16_t detected_protocol, detected_masterprotocol; + ndpi_protocol detected_protocol; char host_server_name[256]; @@ -489,15 +489,17 @@ static void printFlow(u_int16_t thread_id, struct ndpi_flow *flow) { if(flow->vlan_id > 0) fprintf(out, "[VLAN: %u]", flow->vlan_id); - if(flow->detected_masterprotocol) - fprintf(out, "[proto: %u.%u/%s.%s]", - flow->detected_masterprotocol, flow->detected_protocol, - ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_masterprotocol), - ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol)); - else - fprintf(out, "[proto: %u/%s]", - flow->detected_protocol, - ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol)); + if(flow->detected_protocol.master_protocol) { + char buf[64]; + + fprintf(out, "[proto: %u.%u/%s]", + flow->detected_protocol.master_protocol, flow->detected_protocol.protocol, + ndpi_protocol2name(ndpi_thread_info[thread_id].ndpi_struct, + flow->detected_protocol, buf, sizeof(buf))); + } else + fprintf(out, "[proto: %u/%s]", + flow->detected_protocol.protocol, + ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol.protocol)); fprintf(out, "[%u pkts/%llu bytes]", flow->packets, (long long unsigned int)flow->bytes); @@ -518,21 +520,24 @@ static void printFlow(u_int16_t thread_id, struct ndpi_flow *flow) { json_object_object_add(jObj,"host_b.name",json_object_new_string(flow->upper_name)); json_object_object_add(jObj,"host_n.port",json_object_new_int(ntohs(flow->upper_port))); - if(flow->detected_masterprotocol) - json_object_object_add(jObj,"detected.masterprotocol",json_object_new_int(flow->detected_masterprotocol)); - - json_object_object_add(jObj,"detected.protocol",json_object_new_int(flow->detected_protocol)); + if(flow->detected_protocol.master_protocol) + json_object_object_add(jObj,"detected.masterprotocol",json_object_new_int(flow->detected_protocol.master_protocol)); + + json_object_object_add(jObj,"detected.protocol",json_object_new_int(flow->detected_protocol.protocol)); - if(flow->detected_masterprotocol) { + if(flow->detected_protocol.master_protocol) { char tmp[256]; - snprintf(tmp, sizeof(tmp), "%s.%s", - ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_masterprotocol), - ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol)); + snprintf(tmp, sizeof(tmp), "%s.%s", + ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol.master_protocol), + ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol.protocol)); - json_object_object_add(jObj,"detected.protocol.name",json_object_new_string(tmp)); + json_object_object_add(jObj,"detected.protocol.name", + json_object_new_string(tmp)); } else - json_object_object_add(jObj,"detected.protocol.name",json_object_new_string(ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, flow->detected_protocol))); + json_object_object_add(jObj,"detected.protocol.name", + json_object_new_string(ndpi_get_proto_name(ndpi_thread_info[thread_id].ndpi_struct, + flow->detected_protocol.protocol))); json_object_object_add(jObj,"packets",json_object_new_int(flow->packets)); json_object_object_add(jObj,"bytes",json_object_new_int(flow->bytes)); @@ -584,7 +589,7 @@ static void node_print_unknown_proto_walker(const void *node, ndpi_VISIT which, struct ndpi_flow *flow = *(struct ndpi_flow**)node; u_int16_t thread_id = *((u_int16_t*)user_data); - if(flow->detected_protocol != 0 /* UNKNOWN */) return; + if(flow->detected_protocol.protocol != NDPI_PROTOCOL_UNKNOWN) return; if((which == ndpi_preorder) || (which == ndpi_leaf)) /* Avoid walking the same node multiple times */ printFlow(thread_id, flow); @@ -596,7 +601,7 @@ static void node_print_known_proto_walker(const void *node, ndpi_VISIT which, in struct ndpi_flow *flow = *(struct ndpi_flow**)node; u_int16_t thread_id = *((u_int16_t*)user_data); - if(flow->detected_protocol == 0 /* UNKNOWN */) return; + if(flow->detected_protocol.protocol == NDPI_PROTOCOL_UNKNOWN) return; if((which == ndpi_preorder) || (which == ndpi_leaf)) /* Avoid walking the same node multiple times */ printFlow(thread_id, flow); @@ -612,10 +617,10 @@ static u_int16_t node_guess_undetected_protocol(u_int16_t thread_id, struct ndpi ntohl(flow->upper_ip), ntohs(flow->upper_port)); // printf("Guess state: %u\n", flow->detected_protocol); - if(flow->detected_protocol != 0) + if(flow->detected_protocol.protocol != NDPI_PROTOCOL_UNKNOWN) ndpi_thread_info[thread_id].stats.guessed_flow_protocols++; - return flow->detected_protocol; + return(flow->detected_protocol.protocol); } /* ***************************************************** */ @@ -636,15 +641,15 @@ static void node_proto_guess_walker(const void *node, ndpi_VISIT which, int dept if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */ if(enable_protocol_guess) { - if(flow->detected_protocol == 0 /* UNKNOWN */) { + if(flow->detected_protocol.protocol == NDPI_PROTOCOL_UNKNOWN) { node_guess_undetected_protocol(thread_id, flow); // printFlow(thread_id, flow); } } - ndpi_thread_info[thread_id].stats.protocol_counter[flow->detected_protocol] += flow->packets; - ndpi_thread_info[thread_id].stats.protocol_counter_bytes[flow->detected_protocol] += flow->bytes; - ndpi_thread_info[thread_id].stats.protocol_flows[flow->detected_protocol]++; + ndpi_thread_info[thread_id].stats.protocol_counter[flow->detected_protocol.protocol] += flow->packets; + ndpi_thread_info[thread_id].stats.protocol_counter_bytes[flow->detected_protocol.protocol] += flow->bytes; + ndpi_thread_info[thread_id].stats.protocol_flows[flow->detected_protocol.protocol]++; } } @@ -663,7 +668,7 @@ static void node_idle_scan_walker(const void *node, ndpi_VISIT which, int depth, /* update stats */ node_proto_guess_walker(node, which, depth, user_data); - if (flow->detected_protocol == 0 /* UNKNOWN */ && !undetected_flows_deleted) + if((flow->detected_protocol.protocol == NDPI_PROTOCOL_UNKNOWN) && !undetected_flows_deleted) undetected_flows_deleted = 1; free_ndpi_flow(flow); @@ -919,8 +924,7 @@ static void setupDetection(u_int16_t thread_id) { exit(-1); } - if(!full_http_dissection) - ndpi_thread_info[thread_id].ndpi_struct->http_dont_dissect_response = 1; + /* ndpi_thread_info[thread_id].ndpi_struct->http_dont_dissect_response = 1; */ // enable all protocols NDPI_BITMASK_SET_ALL(all); @@ -965,7 +969,6 @@ static unsigned int packet_processing(u_int16_t thread_id, struct ndpi_id_struct *src, *dst; struct ndpi_flow *flow; struct ndpi_flow_struct *ndpi_flow = NULL; - u_int32_t protocol = 0; u_int8_t proto; if(iph) @@ -987,52 +990,47 @@ static unsigned int packet_processing(u_int16_t thread_id, if(flow->detection_completed) return(0); - protocol = (const u_int32_t)ndpi_detection_process_packet(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow, - iph ? (uint8_t *)iph : (uint8_t *)iph6, - ipsize, time, src, dst); - - if(protocol != NDPI_PROTOCOL_UNKNOWN) - flow->detected_protocol = protocol, flow->detected_masterprotocol = ndpi_get_flow_masterprotocol(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow); - - if((flow->detected_protocol != NDPI_PROTOCOL_UNKNOWN) + flow->detected_protocol = ndpi_detection_process_packet(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow, + iph ? (uint8_t *)iph : (uint8_t *)iph6, + ipsize, time, src, dst); + + if((flow->detected_protocol.protocol != NDPI_PROTOCOL_UNKNOWN) || ((proto == IPPROTO_UDP) && (flow->packets > 8)) || ((proto == IPPROTO_TCP) && (flow->packets > 10))) { flow->detection_completed = 1; - if((flow->detected_protocol == NDPI_PROTOCOL_UNKNOWN) && (ndpi_flow->num_stun_udp_pkts > 0)) + if((flow->detected_protocol.protocol == NDPI_PROTOCOL_UNKNOWN) && (ndpi_flow->num_stun_udp_pkts > 0)) ndpi_set_detected_protocol(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow, NDPI_PROTOCOL_STUN, NDPI_PROTOCOL_UNKNOWN); snprintf(flow->host_server_name, sizeof(flow->host_server_name), "%s", flow->ndpi_flow->host_server_name); - if((proto == IPPROTO_TCP) && (flow->detected_protocol != NDPI_PROTOCOL_DNS)) { + if((proto == IPPROTO_TCP) && (flow->detected_protocol.protocol != NDPI_PROTOCOL_DNS)) { snprintf(flow->ssl.client_certificate, sizeof(flow->ssl.client_certificate), "%s", flow->ndpi_flow->protos.ssl.client_certificate); snprintf(flow->ssl.server_certificate, sizeof(flow->ssl.server_certificate), "%s", flow->ndpi_flow->protos.ssl.server_certificate); } #if 0 - if(( - (flow->detected_protocol == NDPI_PROTOCOL_HTTP) - || (flow->detected_protocol == NDPI_SERVICE_FACEBOOK) - ) - && full_http_dissection) { - char *method; - - printf("[URL] %s\n", ndpi_get_http_url(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow)); - printf("[Content-Type] %s\n", ndpi_get_http_content_type(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow)); - - switch(ndpi_get_http_method(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow)) { - case HTTP_METHOD_OPTIONS: method = "HTTP_METHOD_OPTIONS"; break; - case HTTP_METHOD_GET: method = "HTTP_METHOD_GET"; break; - case HTTP_METHOD_HEAD: method = "HTTP_METHOD_HEAD"; break; - case HTTP_METHOD_POST: method = "HTTP_METHOD_POST"; break; - case HTTP_METHOD_PUT: method = "HTTP_METHOD_PUT"; break; - case HTTP_METHOD_DELETE: method = "HTTP_METHOD_DELETE"; break; - case HTTP_METHOD_TRACE: method = "HTTP_METHOD_TRACE"; break; - case HTTP_METHOD_CONNECT: method = "HTTP_METHOD_CONNECT"; break; - default: method = "HTTP_METHOD_UNKNOWN"; break; - } + if(verbose > 1) { + if(ndpi_is_proto(flow->detected_protocol, NDPI_PROTOCOL_HTTP)) { + char *method; + + printf("[URL] %s\n", ndpi_get_http_url(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow)); + printf("[Content-Type] %s\n", ndpi_get_http_content_type(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow)); + + switch(ndpi_get_http_method(ndpi_thread_info[thread_id].ndpi_struct, ndpi_flow)) { + case HTTP_METHOD_OPTIONS: method = "HTTP_METHOD_OPTIONS"; break; + case HTTP_METHOD_GET: method = "HTTP_METHOD_GET"; break; + case HTTP_METHOD_HEAD: method = "HTTP_METHOD_HEAD"; break; + case HTTP_METHOD_POST: method = "HTTP_METHOD_POST"; break; + case HTTP_METHOD_PUT: method = "HTTP_METHOD_PUT"; break; + case HTTP_METHOD_DELETE: method = "HTTP_METHOD_DELETE"; break; + case HTTP_METHOD_TRACE: method = "HTTP_METHOD_TRACE"; break; + case HTTP_METHOD_CONNECT: method = "HTTP_METHOD_CONNECT"; break; + default: method = "HTTP_METHOD_UNKNOWN"; break; + } - printf("[Method] %s\n", method); + printf("[Method] %s\n", method); + } } #endif @@ -1040,8 +1038,9 @@ static unsigned int packet_processing(u_int16_t thread_id, if(verbose > 1) { if(enable_protocol_guess) { - if(flow->detected_protocol == 0 /* UNKNOWN */) { - protocol = node_guess_undetected_protocol(thread_id, flow); + if(flow->detected_protocol.protocol == NDPI_PROTOCOL_UNKNOWN) { + flow->detected_protocol.protocol = node_guess_undetected_protocol(thread_id, flow), + flow->detected_protocol.master_protocol = NDPI_PROTOCOL_UNKNOWN; } } @@ -1256,7 +1255,7 @@ static void printResults(u_int64_t tot_usec) { if(enable_protocol_guess) printf("\tGuessed flow protos: %-13u\n", cumulative_stats.guessed_flow_protocols); } - } + } if(json_flag) { #ifdef HAVE_JSON_C @@ -1320,13 +1319,13 @@ static void printResults(u_int64_t tot_usec) { #ifdef HAVE_JSON_C if(json_fp) { jObj = json_object_new_object(); - + json_object_object_add(jObj,"name",json_object_new_string(ndpi_get_proto_name(ndpi_thread_info[0].ndpi_struct, i))); json_object_object_add(jObj,"breed",json_object_new_string(ndpi_get_proto_breed_name(ndpi_thread_info[0].ndpi_struct, breed))); json_object_object_add(jObj,"packets",json_object_new_int64(cumulative_stats.protocol_counter[i])); json_object_object_add(jObj,"bytes",json_object_new_int64(cumulative_stats.protocol_counter_bytes[i])); json_object_object_add(jObj,"flows",json_object_new_int(cumulative_stats.protocol_flows[i])); - + json_object_array_add(jArray_detProto,jObj); } #endif @@ -1352,7 +1351,7 @@ static void printResults(u_int64_t tot_usec) { if(verbose) { FILE *out = results_file ? results_file : stdout; - + if(!json_flag) fprintf(out, "\n"); num_flows = 0; diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h index 5ec188be5..d3fff5cfd 100644 --- a/src/include/ndpi_api.h +++ b/src/include/ndpi_api.h @@ -123,13 +123,13 @@ extern "C" { * @param dst void pointer to the destination subscriber state machine * @return returns the detected ID of the protocol */ - u_int16_t ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow, - const unsigned char *packet, - const unsigned short packetlen, - const u_int64_t current_tick, - struct ndpi_id_struct *src, - struct ndpi_id_struct *dst); + ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow, + const unsigned char *packet, + const unsigned short packetlen, + const u_int64_t current_tick, + struct ndpi_id_struct *src, + struct ndpi_id_struct *dst); u_int16_t ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow); @@ -169,10 +169,10 @@ extern "C" { u_int8_t ndpi_detection_flow_protocol_history_contains_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, u_int16_t protocol_id); - unsigned int ndpi_find_port_based_protocol(struct ndpi_detection_module_struct *ndpi_struct, - u_int8_t proto, u_int32_t shost, u_int16_t sport, u_int32_t dhost, u_int16_t dport); - unsigned int ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct, + ndpi_protocol ndpi_find_port_based_protocol(struct ndpi_detection_module_struct *ndpi_struct, u_int8_t proto, u_int32_t shost, u_int16_t sport, u_int32_t dhost, u_int16_t dport); + ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct, + u_int8_t proto, u_int32_t shost, u_int16_t sport, u_int32_t dhost, u_int16_t dport); int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, char *string_to_match, u_int string_to_match_len); int ndpi_match_content_subprotocol(struct ndpi_detection_module_struct *ndpi_struct, @@ -180,6 +180,7 @@ extern "C" { char *string_to_match, u_int string_to_match_len); int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct, ndpi_automa *automa, char *bigram_to_match); + char* ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_mod, ndpi_protocol proto, char *buf, u_int buf_len); char* ndpi_get_proto_name(struct ndpi_detection_module_struct *mod, u_int16_t proto_id); ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t proto); char* ndpi_get_proto_breed_name(struct ndpi_detection_module_struct *ndpi_struct, ndpi_protocol_breed_t breed_id); diff --git a/src/include/ndpi_main.h b/src/include/ndpi_main.h index ab869b167..adec3edf1 100644 --- a/src/include/ndpi_main.h +++ b/src/include/ndpi_main.h @@ -136,6 +136,8 @@ extern char *ndpi_get_packet_src_ip_string(struct ndpi_detection_module_struct * extern char* ndpi_get_proto_by_id(struct ndpi_detection_module_struct *ndpi_mod, u_int id); extern u_int16_t ndpi_guess_protocol_id(struct ndpi_detection_module_struct *ndpi_struct, u_int8_t proto, u_int16_t sport, u_int16_t dport); +extern u_int8_t ndpi_is_proto(ndpi_protocol p, u_int16_t proto); +extern u_int16_t ndpi_get_lower_proto(ndpi_protocol p); extern int ndpi_get_protocol_id_master_proto(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t protocol_id, u_int16_t** tcp_master_proto, diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 7ca59fa58..8404daa2e 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -561,6 +561,12 @@ typedef struct _ndpi_automa { u_int8_t ac_automa_finalized; } ndpi_automa; +typedef struct ndpi_proto { + u_int16_t master_protocol /* e.g. HTTP */, protocol /* e.g. FaceBook */; +} ndpi_protocol; + +#define NDPI_PROTOCOL_NULL { NDPI_PROTOCOL_UNKNOWN , NDPI_PROTOCOL_UNKNOWN } + typedef struct ndpi_detection_module_struct { NDPI_PROTOCOL_BITMASK detection_bitmask; NDPI_PROTOCOL_BITMASK generic_http_packet_bitmask; @@ -671,7 +677,6 @@ typedef struct ndpi_flow_struct { u_int16_t guessed_protocol_id; u_int8_t protocol_id_already_guessed:1; - u_int8_t no_cache_protocol:1; u_int8_t init_finished:1; u_int8_t setup_packet_direction:1; u_int8_t packet_direction:1; /* if ndpi_struct->direction_detect_disable == 1 */ diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index e4efcfc2d..9496545cd 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -695,7 +695,7 @@ static int ndpi_add_host_url_subprotocol(struct ndpi_detection_module_struct *nd int ndpi_add_content_subprotocol(struct ndpi_detection_module_struct *ndpi_struct, char *value, int protocol_id, ndpi_protocol_breed_t breed) { - return(ndpi_string_to_automa(ndpi_struct, &ndpi_struct->content_automa, + return(ndpi_string_to_automa(ndpi_struct, &ndpi_struct->content_automa, value, protocol_id, breed)); } @@ -732,7 +732,7 @@ static void init_string_based_protocols(struct ndpi_detection_module_struct *ndp ndpi_mod->proto_defaults[host_match[i].protocol_id].protoBreed = host_match[i].protocol_breed; } - ndpi_set_proto_defaults(ndpi_mod, + ndpi_set_proto_defaults(ndpi_mod, ndpi_mod->proto_defaults[host_match[i].protocol_id].protoBreed, ndpi_mod->proto_defaults[host_match[i].protocol_id].protoId, no_master, no_master, @@ -1241,7 +1241,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_VOICE, no_master, - no_master, "WhatsApp Voice", + no_master, "WhatsAppVoice", ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); @@ -3847,8 +3847,7 @@ __forceinline static void ndpi_apply_flow_protocol_to_packet(struct ndpi_flow_struct *flow, struct ndpi_packet_struct *packet) { - memcpy(&packet->detected_protocol_stack[0], - &flow->detected_protocol_stack[0], sizeof(packet->detected_protocol_stack)); + 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)); } @@ -3949,10 +3948,8 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str && flow->packet.tcp->ack == 0 && flow->init_finished != 0 && flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { - memset(flow, 0, sizeof(*(flow))); - NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_DEBUG, "%s:%u: tcp syn packet for unknown protocol, reset detection state\n", __FUNCTION__, __LINE__); @@ -4056,15 +4053,12 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct, } } else if(packet->payload_packet_len > 0) { /* check tcp sequence counters */ - if(((u_int32_t) - (ntohl(tcph->seq) - - flow->next_tcp_seq_nr[packet->packet_direction])) > + if(((u_int32_t)(ntohl(tcph->seq) - flow->next_tcp_seq_nr[packet->packet_direction])) > ndpi_struct->tcp_max_retransmission_window_size) { packet->tcp_retransmission = 1; - - /*CHECK IF PARTIAL RETRY IS HAPPENENING */ + /* CHECK IF PARTIAL RETRY IS HAPPENING */ if((flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq) < packet->payload_packet_len)) { /* num_retried_bytes actual_payload_len hold info about the partial retry analyzer which require this info can make use of this info @@ -4074,17 +4068,14 @@ void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_struct, flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len; } } - /*normal path - actual_payload_len is initialized to payload_packet_len during tcp header parsing itself. - It will be changed only in case of retransmission */ - else { - + /* normal path + actual_payload_len is initialized to payload_packet_len during tcp header parsing itself. + It will be changed only in case of retransmission */ + else { packet->num_retried_bytes = 0; flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len; } - - } if(tcph->rst) { @@ -4285,30 +4276,30 @@ void check_ndpi_flow_func(struct ndpi_detection_module_struct *ndpi_struct, check_ndpi_other_flow_func(ndpi_struct, flow, ndpi_selection_packet); } -u_int16_t ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct, - struct ndpi_flow_struct *flow, - const unsigned char *packet, - const unsigned short packetlen, - const u_int64_t current_tick_l, - struct ndpi_id_struct *src, - struct ndpi_id_struct *dst) +ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow, + const unsigned char *packet, + const unsigned short packetlen, + const u_int64_t current_tick_l, + struct ndpi_id_struct *src, + struct ndpi_id_struct *dst) { NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_packet; u_int32_t a; + ndpi_protocol ret = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN }; if(flow == NULL) - return NDPI_PROTOCOL_UNKNOWN; + return(ret); if(flow->server_id == NULL) flow->server_id = dst; /* Default */ - if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN && !flow->no_cache_protocol) - return(flow->detected_protocol_stack[0]); /* Stop after detecting the first protocol */ + if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) + goto ret_protocols; /* need at least 20 bytes for ip header */ if(packetlen < 20) { /* reset protocol which is normally done in init_packet_header */ ndpi_int_reset_packet_protocol(&flow->packet); - - return NDPI_PROTOCOL_UNKNOWN; + return(ret); } flow->packet.tick_timestamp_l = current_tick_l; @@ -4323,11 +4314,11 @@ u_int16_t ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndp #endif /* parse packet */ - flow->packet.iph = (struct ndpi_iphdr *) packet; + flow->packet.iph = (struct ndpi_iphdr *)packet; /* we are interested in ipv4 packet */ if(ndpi_init_packet_header(ndpi_struct, flow, packetlen) != 0) - return NDPI_PROTOCOL_UNKNOWN; + return(ret); /* detect traffic for tcp or udp only */ @@ -4337,28 +4328,26 @@ u_int16_t ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndp /* build ndpi_selction packet bitmask */ ndpi_selection_packet = NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC; - if(flow->packet.iph != NULL) { + if(flow->packet.iph != NULL) ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6; - } - if(flow->packet.tcp != NULL) { + + if(flow->packet.tcp != NULL) ndpi_selection_packet |= (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP); - } - if(flow->packet.udp != NULL) { + + if(flow->packet.udp != NULL) ndpi_selection_packet |= (NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP); - } - if(flow->packet.payload_packet_len != 0) { + + if(flow->packet.payload_packet_len != 0) ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD; - } - if(flow->packet.tcp_retransmission == 0) { + if(flow->packet.tcp_retransmission == 0) ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION; - } + #ifdef NDPI_DETECTION_SUPPORT_IPV6 - if(flow->packet.iphv6 != NULL) { + if(flow->packet.iphv6 != NULL) ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6; - } #endif /* NDPI_DETECTION_SUPPORT_IPV6 */ if((!flow->protocol_id_already_guessed) @@ -4386,17 +4375,18 @@ u_int16_t ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndp else if(flow->packet.tcp) sport = ntohs(flow->packet.tcp->source), dport = ntohs(flow->packet.tcp->dest); else sport = dport = 0; - flow->guessed_protocol_id = (int16_t)ndpi_guess_protocol_id(ndpi_struct, protocol, - sport, dport); + flow->guessed_protocol_id = (int16_t)ndpi_guess_protocol_id(ndpi_struct, protocol, sport, dport); flow->protocol_id_already_guessed = 1; } +#if 0 a = flow->detected_protocol_stack[0]; - if(a != NDPI_PROTOCOL_UNKNOWN && flow->no_cache_protocol) { + if(a != NDPI_PROTOCOL_UNKNOWN) { NDPI_LOG(NDPI_PROTOCOL_UNKNOWN, ndpi_struct, NDPI_LOG_TRACE, "PROCESS KNOWN PROTOCOL\n"); ndpi_struct->proto_defaults[a].func(ndpi_struct, flow); return a; } +#endif check_ndpi_flow_func(ndpi_struct, flow, &ndpi_selection_packet); @@ -4413,9 +4403,14 @@ u_int16_t ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndp flow->host_server_name[i] ='\0'; } - return a; -} + ret_protocols: + if(flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN) + ret.master_protocol = flow->detected_protocol_stack[1], ret.protocol = flow->detected_protocol_stack[0]; + else + ret.protocol = flow->detected_protocol_stack[0]; + return(ret); +} u_int32_t ndpi_bytestream_to_number(const u_int8_t * str, u_int16_t max_chars_to_read, u_int16_t * bytes_read) { @@ -4907,9 +4902,9 @@ void ndpi_set_detected_protocol(struct ndpi_detection_module_struct *ndpi_struct { struct ndpi_id_struct *src = flow->src; struct ndpi_id_struct *dst = flow->dst; - + ndpi_int_change_protocol(ndpi_struct, flow, upper_detected_protocol, lower_detected_protocol); - + if(src != NULL) { NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, upper_detected_protocol); @@ -4932,16 +4927,16 @@ u_int16_t ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct *ndpi void ndpi_int_change_flow_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - u_int16_t upper_detected_protocol, + u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { if(!flow) return; - + flow->detected_protocol_stack[0] = upper_detected_protocol, flow->detected_protocol_stack[1] = lower_detected_protocol; } void ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - u_int16_t upper_detected_protocol, + u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { struct ndpi_packet_struct *packet = &flow->packet; /* NOTE: everything below is identically to change_flow_protocol @@ -4985,7 +4980,7 @@ u_int8_t ndpi_detection_flow_protocol_history_contains_protocol(struct ndpi_dete */ void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - u_int16_t upper_detected_protocol, + u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { ndpi_int_change_flow_protocol(ndpi_struct, flow, upper_detected_protocol, lower_detected_protocol); ndpi_int_change_packet_protocol(ndpi_struct, flow, upper_detected_protocol, lower_detected_protocol); @@ -4995,7 +4990,7 @@ void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_struct, /* turns a packet back to unknown */ void ndpi_int_reset_packet_protocol(struct ndpi_packet_struct *packet) { int a; - + for(a = 0; a < NDPI_PROTOCOL_HISTORY_SIZE; a++) packet->detected_protocol_stack[a] = NDPI_PROTOCOL_UNKNOWN; } @@ -5003,13 +4998,13 @@ void ndpi_int_reset_packet_protocol(struct ndpi_packet_struct *packet) { void ndpi_int_reset_protocol(struct ndpi_flow_struct *flow) { if(flow) { int a; - + for(a = 0; a < NDPI_PROTOCOL_HISTORY_SIZE; a++) { flow->detected_protocol_stack[a] = NDPI_PROTOCOL_UNKNOWN; } } } - + void NDPI_PROTOCOL_IP_clear(ndpi_ip_addr_t * ip) { memset(ip, 0, sizeof(ndpi_ip_addr_t)); } @@ -5151,56 +5146,94 @@ static u_int is_port(u_int16_t sport, u_int16_t dport, u_int16_t match_port) { /* ****************************************************** */ -unsigned int ndpi_find_port_based_protocol(struct ndpi_detection_module_struct *ndpi_struct /* NOTUSED */, - u_int8_t proto, - u_int32_t shost, u_int16_t sport, - u_int32_t dhost, u_int16_t dport) { +ndpi_protocol ndpi_find_port_based_protocol(struct ndpi_detection_module_struct *ndpi_struct /* NOTUSED */, + u_int8_t proto, + u_int32_t shost, u_int16_t sport, + u_int32_t dhost, u_int16_t dport) { + ndpi_protocol p = NDPI_PROTOCOL_NULL; + /* Skyfile (host 193.252.234.246 or host 10.10.102.80) */ if((shost == 0xC1FCEAF6) || (dhost == 0xC1FCEAF6) || (shost == 0x0A0A6650) || (dhost == 0x0A0A6650)) { - if((sport == 4708) || (dport == 4708)) return(NDPI_PROTOCOL_SKYFILE_PREPAID); - else if((sport == 4709) || (dport == 4709)) return(NDPI_PROTOCOL_SKYFILE_RUDICS); - else if((sport == 4710) || (dport == 4710)) return(NDPI_PROTOCOL_SKYFILE_POSTPAID); + if((sport == 4708) || (dport == 4708)) p.protocol = NDPI_PROTOCOL_SKYFILE_PREPAID; + else if((sport == 4709) || (dport == 4709)) p.protocol = NDPI_PROTOCOL_SKYFILE_RUDICS; + else if((sport == 4710) || (dport == 4710)) p.protocol = NDPI_PROTOCOL_SKYFILE_POSTPAID; } - return(NDPI_PROTOCOL_UNKNOWN); + return(p); } /* ****************************************************** */ -unsigned int ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct, - u_int8_t proto, - u_int32_t shost /* host byte order */, u_int16_t sport, - u_int32_t dhost /* host byte order */, u_int16_t dport) { +u_int8_t ndpi_is_proto(ndpi_protocol p, u_int16_t proto) { + return(((p.protocol == proto) || (p.master_protocol == proto)) ? 1 : 0); +} + +/* ****************************************************** */ + +u_int16_t ndpi_get_lower_proto(ndpi_protocol p) { + return((p.master_protocol != NDPI_PROTOCOL_UNKNOWN) ? p.master_protocol : p.protocol); +} + +/* ****************************************************** */ + +ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_struct, + u_int8_t proto, + u_int32_t shost /* host byte order */, u_int16_t sport, + u_int32_t dhost /* host byte order */, u_int16_t dport) { unsigned int rc; struct in_addr addr; + ndpi_protocol ret = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN }; if((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) { rc = ndpi_search_tcp_or_udp_raw(ndpi_struct, proto, shost, dhost, sport, dport); - if(rc != NDPI_PROTOCOL_UNKNOWN) return(rc); + if(rc != NDPI_PROTOCOL_UNKNOWN) { + ret.protocol = rc; + return(ret); + } rc = ndpi_guess_protocol_id(ndpi_struct, proto, sport, dport); if(rc != NDPI_PROTOCOL_UNKNOWN) { + ret.protocol = rc; + if(rc == NDPI_PROTOCOL_SSL) goto check_guessed_skype; else - return(rc); + return(ret); } - rc = ndpi_find_port_based_protocol(ndpi_struct, proto, shost, sport, dhost, dport); - if(rc != NDPI_PROTOCOL_UNKNOWN) return(rc); + ret = ndpi_find_port_based_protocol(ndpi_struct, proto, shost, sport, dhost, dport); + if(ret.protocol != NDPI_PROTOCOL_UNKNOWN) + return(ret); check_guessed_skype: addr.s_addr = shost; - if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE) return(NDPI_PROTOCOL_SKYPE); + if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE) { + ret.protocol = NDPI_PROTOCOL_SKYPE; + } else { + addr.s_addr = dhost; + if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE) + ret.protocol = NDPI_PROTOCOL_SKYPE; + } + } else + ret.protocol = ndpi_guess_protocol_id(ndpi_struct, proto, sport, dport); - addr.s_addr = dhost; - if(ndpi_network_ptree_match(ndpi_struct, &addr) == NDPI_PROTOCOL_SKYPE) return(NDPI_PROTOCOL_SKYPE); + return(ret); +} - return(rc); - } else { - return(ndpi_guess_protocol_id(ndpi_struct, proto, sport, dport)); - } +/* ****************************************************** */ + +char* ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_mod, + ndpi_protocol proto, char *buf, u_int buf_len) { + if(proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) { + snprintf(buf, buf_len, "%s.%s", + ndpi_get_proto_name(ndpi_mod, proto.master_protocol), + ndpi_get_proto_name(ndpi_mod, proto.protocol)); + } else + snprintf(buf, buf_len, "%s", + ndpi_get_proto_name(ndpi_mod, proto.protocol)); + + return(buf); } /* ****************************************************** */ @@ -5340,7 +5373,7 @@ static int ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_str /* Move the protocol on slot 0 down one position */ packet->detected_protocol_stack[1] = packet->detected_protocol_stack[0]; packet->detected_protocol_stack[0] = matching_protocol_id; - + flow->detected_protocol_stack[0] = packet->detected_protocol_stack[0], flow->detected_protocol_stack[1] = packet->detected_protocol_stack[1]; diff --git a/tests/result/whatsapp_login_call.pcap.out b/tests/result/whatsapp_login_call.pcap.out index 38d79e24b..88cedf98d 100644 --- a/tests/result/whatsapp_login_call.pcap.out +++ b/tests/result/whatsapp_login_call.pcap.out @@ -10,12 +10,12 @@ Apple 127 28102 20 WhatsApp 182 25154 2 AppleiTunes 85 28087 2 Spotify 3 258 1 -WhatsApp Voice 662 83338 2 +WhatsAppVoice 662 83338 2 1 UDP fe80::da30:62ff:fe56:1c:5353 <-> ff02::fb:5353 [proto: 8/MDNS][2 pkts/258 bytes] 2 UDP 192.168.2.1:17500 <-> 192.168.2.255:17500 [proto: 121/DropBox][4 pkts/2176 bytes] 3 ICMP 192.168.2.4:0 <-> 91.253.176.65:0 [proto: 81/ICMP][10 pkts/700 bytes] - 4 UDP 192.168.2.4:52794 <-> 91.253.176.65:9665 [proto: 189/WhatsApp Voice][198 pkts/30418 bytes] + 4 UDP 192.168.2.4:52794 <-> 91.253.176.65:9665 [proto: 189/WhatsAppVoice][198 pkts/30418 bytes] 5 UDP 173.252.114.1:3478 <-> 192.168.2.4:52794 [proto: 78/STUN][5 pkts/676 bytes] 6 UDP 192.168.2.1:53 <-> 192.168.2.4:51897 [proto: 140/Apple][2 pkts/330 bytes][Host: query.ess.apple.com] 7 UDP 192.168.2.4:52794 <-> 179.60.192.48:3478 [proto: 78/STUN][5 pkts/676 bytes] @@ -45,7 +45,7 @@ WhatsApp Voice 662 83338 2 31 TCP 192.168.2.4:49173 <-> 93.186.135.82:80 [proto: 7/HTTP][3 pkts/198 bytes] 32 TCP 192.168.2.4:49194 <-> 93.62.150.157:443 [proto: 91/SSL][3 pkts/198 bytes] 33 UDP 0.0.0.0:68 <-> 255.255.255.255:67 [proto: 18/DHCP][10 pkts/3420 bytes] - 34 UDP 192.168.2.4:51518 <-> 91.253.176.65:9344 [proto: 189/WhatsApp Voice][464 pkts/52920 bytes] + 34 UDP 192.168.2.4:51518 <-> 91.253.176.65:9344 [proto: 189/WhatsAppVoice][464 pkts/52920 bytes] 35 TCP 192.168.2.4:49202 <-> 184.173.179.37:5222 [proto: 142/WhatsApp][180 pkts/24874 bytes] 36 UDP 192.168.2.1:57621 <-> 192.168.2.255:57621 [proto: 156/Spotify][3 pkts/258 bytes] 37 UDP 192.168.2.1:53 <-> 192.168.2.4:52190 [proto: 142/WhatsApp][2 pkts/280 bytes][Host: e13.whatsapp.net] |