diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ndpi_utils.h | 1 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 4945 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 415 |
3 files changed, 2707 insertions, 2654 deletions
diff --git a/src/include/ndpi_utils.h b/src/include/ndpi_utils.h index 296bd6254..185856f3d 100644 --- a/src/include/ndpi_utils.h +++ b/src/include/ndpi_utils.h @@ -8,7 +8,6 @@ #define MYDBG(m, ...) \ printf(" DBG[%s:%s:%u]: \t" m "\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); - // #define NDPI_ENABLE_DEBUG_POINTER_MESSAGES // #define NDPI_ENABLE_DEBUG_INFO_MESSAGES // #define NDPI_ENABLE_DEBUG_TRACE_MESSAGES diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index daf447d58..9f8514848 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -2018,7 +2018,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs if(!(prefs & ndpi_dont_init_libgcrypt)) { if(!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) { const char *gcrypt_ver = gcry_check_version(NULL); - if (!gcrypt_ver) { + if(!gcrypt_ver) { NDPI_LOG_ERR(ndpi_str, "Error initializing libgcrypt\n"); ndpi_free(ndpi_str); return NULL; @@ -3498,25 +3498,25 @@ int ndpi_handle_ipv6_extension_headers(struct ndpi_detection_module_struct *ndpi static u_int8_t ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr *iph, const u_int16_t ipsize) { - #ifdef FRAG_MAN +#ifdef FRAG_MAN /* the logic has been inverted!!! returned value: - 0: not fragmented (instead of fragmented) - 1: packet too small - 2: fragmented and last, reassemble - 3: fragmented but not the last, add to buffer + 0: not fragmented (instead of fragmented) + 1: packet too small + 2: fragmented and last, reassemble + 3: fragmented but not the last, add to buffer */ u_int16_t tot_len = ntohs(iph->tot_len); - if ( ipsize < iph->ihl * 4 || ipsize < tot_len || tot_len < iph->ihl * 4 ) + if( ipsize < iph->ihl * 4 || ipsize < tot_len || tot_len < iph->ihl * 4 ) // packet too small return(1); - else if ((iph->frag_off & htons(0x2000)) != 0) { + else if((iph->frag_off & htons(0x2000)) != 0) { // MF=1 : this is a fragment and not the last -> add to buffer //printf("DBG(ndpi_iph_is_valid_and_not_fragmented): ipv4 fragment and not the last! (off=%u) \n", (htons(iph->frag_off) & 0x1FFF)<<3); // MUST add to buffer return(3); - } else if ((iph->frag_off & htons(0x1FFF)) != 0) { + } else if((iph->frag_off & htons(0x1FFF)) != 0) { // MF=0, this is (a fragment, but) the last fragment! //printf("DBG(ndpi_iph_is_valid_and_not_fragmented): ipv4 fragment and the last! (0ff=%u) \n", (htons(iph->frag_off) & 0x1FFF)<<3); @@ -3526,10 +3526,10 @@ static u_int8_t ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr *ip return (0); #else // FRAG_MAN - /* + /* returned value: - 0: fragmented - 1: not fragmented + 0: fragmented + 1: not fragmented */ //#ifdef REQUIRE_FULL_PACKETS if(ipsize < iph->ihl * 4 || ipsize < ntohs(iph->tot_len) || ntohs(iph->tot_len) < iph->ihl * 4 || @@ -3544,13 +3544,13 @@ static u_int8_t ndpi_iph_is_valid_and_not_fragmented(const struct ndpi_iphdr *ip } /* -extract the l4 payload, if available -returned value: -FRAG_MAN + extract the l4 payload, if available + returned value: + FRAG_MAN 0: ok, extracted 1: packet too small 2,3: fragmented, .... -else + else 0: ok, extracted 1: error or not available */ @@ -3600,7 +3600,7 @@ static u_int8_t ndpi_detection_get_l4_internal(struct ndpi_detection_module_stru if(iph != NULL) { u_int8_t check4Frag = ndpi_iph_is_valid_and_not_fragmented(iph, l3_len); /* 0: not fragmented; 1: too small; 2,3: fragmented */ - if (!check4Frag) { + if(!check4Frag) { u_int16_t len = ntohs(iph->tot_len); u_int16_t hlen = (iph->ihl * 4); @@ -3759,10 +3759,10 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str * idea: reset detection state if a connection is unknown */ if(flow->packet.tcp->syn != 0 && flow->packet.tcp->ack == 0 && flow->init_finished != 0 && - flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { + flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { u_int8_t backup; - u_int16_t backup1, backup2; + u_int16_t backup1, backup2; backup = flow->num_processed_pkts; backup1 = flow->guessed_protocol_id; @@ -3812,271 +3812,212 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str #ifdef FRAG_MAN uint8_t ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow) { + struct ndpi_flow_struct *flow) { #else // FRAG_MAN -void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow) { + void ndpi_connection_tracking(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow) { #endif // FRAG_MAN - if(!flow) { + if(!flow) { #ifdef FRAG_MAN - return 0; + return 0; #else // FRAG_MAN - return; + return; #endif // FRAG_MAN - } else { - /* const for gcc code optimization and cleaner code */ - struct ndpi_packet_struct *packet = &flow->packet; - const struct ndpi_iphdr *iph = packet->iph; + } else { + /* const for gcc code optimization and cleaner code */ + struct ndpi_packet_struct *packet = &flow->packet; + const struct ndpi_iphdr *iph = packet->iph; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - const struct ndpi_ipv6hdr *iphv6 = packet->iphv6; + const struct ndpi_ipv6hdr *iphv6 = packet->iphv6; #endif - const struct ndpi_tcphdr *tcph = packet->tcp; - const struct ndpi_udphdr *udph = packet->udp; + const struct ndpi_tcphdr *tcph = packet->tcp; + const struct ndpi_udphdr *udph = packet->udp; - packet->tcp_retransmission = 0, packet->packet_direction = 0; + packet->tcp_retransmission = 0, packet->packet_direction = 0; - if(ndpi_str->direction_detect_disable) { - packet->packet_direction = flow->packet_direction; - } else { - if(iph != NULL && ntohl(iph->saddr) < ntohl(iph->daddr)) - packet->packet_direction = 1; + if(ndpi_str->direction_detect_disable) { + packet->packet_direction = flow->packet_direction; + } else { + if(iph != NULL && ntohl(iph->saddr) < ntohl(iph->daddr)) + packet->packet_direction = 1; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - if(iphv6 != NULL && NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(&iphv6->ip6_src, &iphv6->ip6_dst) != 0) - packet->packet_direction = 1; + if(iphv6 != NULL && NDPI_COMPARE_IPV6_ADDRESS_STRUCTS(&iphv6->ip6_src, &iphv6->ip6_dst) != 0) + packet->packet_direction = 1; #endif - } - - packet->packet_lines_parsed_complete = 0; - - if(flow->init_finished == 0) { - flow->init_finished = 1; - flow->setup_packet_direction = packet->packet_direction; - } - - if(tcph != NULL) { - /* reset retried bytes here before setting it */ - packet->num_retried_bytes = 0; + } - if(!ndpi_str->direction_detect_disable) - packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 0; + packet->packet_lines_parsed_complete = 0; - if(tcph->syn != 0 && tcph->ack == 0 && flow->l4.tcp.seen_syn == 0 && flow->l4.tcp.seen_syn_ack == 0 && - flow->l4.tcp.seen_ack == 0) { - flow->l4.tcp.seen_syn = 1; - } else - if(tcph->syn != 0 && tcph->ack != 0 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 0 && - flow->l4.tcp.seen_ack == 0) { - flow->l4.tcp.seen_syn_ack = 1; - } else - if(tcph->syn == 0 && tcph->ack == 1 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 1 && - flow->l4.tcp.seen_ack == 0) { - flow->l4.tcp.seen_ack = 1; + if(flow->init_finished == 0) { + flow->init_finished = 1; + flow->setup_packet_direction = packet->packet_direction; } + if(tcph != NULL) { + /* reset retried bytes here before setting it */ + packet->num_retried_bytes = 0; + + if(!ndpi_str->direction_detect_disable) + packet->packet_direction = (ntohs(tcph->source) < ntohs(tcph->dest)) ? 1 : 0; + + if(tcph->syn != 0 && tcph->ack == 0 && flow->l4.tcp.seen_syn == 0 && flow->l4.tcp.seen_syn_ack == 0 && + flow->l4.tcp.seen_ack == 0) { + flow->l4.tcp.seen_syn = 1; + } else + if(tcph->syn != 0 && tcph->ack != 0 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 0 && + flow->l4.tcp.seen_ack == 0) { + flow->l4.tcp.seen_syn_ack = 1; + } else + if(tcph->syn == 0 && tcph->ack == 1 && flow->l4.tcp.seen_syn == 1 && flow->l4.tcp.seen_syn_ack == 1 && + flow->l4.tcp.seen_ack == 0) { + flow->l4.tcp.seen_ack = 1; + } + #ifdef FRAG_MAN - // check sequence, if there is missing packet, add it to buffer - if ( check_for_sequence(flow, tcph) ) { - // if here added segment to list for next elaboration - // and skip extra processing for after... - return 0; - } + // check sequence, if there is missing packet, add it to buffer + if( check_for_sequence(flow, tcph) ) { + // if here added segment to list for next elaboration + // and skip extra processing for after... + return 0; + } #endif //FRAG_MAN - if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0) || - (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0)) { - /* initialize tcp sequence counters */ - /* the ack flag needs to be set to get valid sequence numbers from the other - * direction. Usually it will catch the second packet syn+ack but it works - * also for asymmetric traffic where it will use the first data packet - * - * if the syn flag is set add one to the sequence number, - * otherwise use the payload length. - */ - if(tcph->ack != 0) { - flow->next_tcp_seq_nr[flow->packet.packet_direction] = - ntohl(tcph->seq) + (tcph->syn ? 1 : packet->payload_packet_len); + if((flow->next_tcp_seq_nr[0] == 0 && flow->next_tcp_seq_nr[1] == 0) || + (flow->next_tcp_seq_nr[0] == 0 || flow->next_tcp_seq_nr[1] == 0)) { + /* initialize tcp sequence counters */ + /* the ack flag needs to be set to get valid sequence numbers from the other + * direction. Usually it will catch the second packet syn+ack but it works + * also for asymmetric traffic where it will use the first data packet + * + * if the syn flag is set add one to the sequence number, + * otherwise use the payload length. + */ + if(tcph->ack != 0) { + flow->next_tcp_seq_nr[flow->packet.packet_direction] = + ntohl(tcph->seq) + (tcph->syn ? 1 : packet->payload_packet_len); + + /* + Check to avoid discrepancies in case we analyze a flow that does not start with SYN... + but that is already started when nDPI being to process it. See also (***) below + */ + if(flow->num_processed_pkts > 1) + flow->next_tcp_seq_nr[1 - flow->packet.packet_direction] = ntohl(tcph->ack_seq); + } + } 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])) > + ndpi_str->tcp_max_retransmission_window_size) { + packet->tcp_retransmission = 1; + + /* 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 + Other analyzer can use packet->payload_packet_len */ + packet->num_retried_bytes = + (u_int16_t)(flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq)); + packet->actual_payload_len = packet->payload_packet_len - packet->num_retried_bytes; + + if(flow->num_processed_pkts > 1) /* See also (***) above */ + flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len; + } + } - /* - Check to avoid discrepancies in case we analyze a flow that does not start with SYN... - but that is already started when nDPI being to process it. See also (***) below - */ - if(flow->num_processed_pkts > 1) - flow->next_tcp_seq_nr[1 - flow->packet.packet_direction] = ntohl(tcph->ack_seq); - } - } 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])) > - ndpi_str->tcp_max_retransmission_window_size) { - packet->tcp_retransmission = 1; - - /* 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 - Other analyzer can use packet->payload_packet_len */ - packet->num_retried_bytes = - (u_int16_t)(flow->next_tcp_seq_nr[packet->packet_direction] - ntohl(tcph->seq)); - packet->actual_payload_len = packet->payload_packet_len - packet->num_retried_bytes; - - if(flow->num_processed_pkts > 1) /* See also (***) above */ - 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 { + packet->num_retried_bytes = 0; + 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 { - packet->num_retried_bytes = 0; - flow->next_tcp_seq_nr[packet->packet_direction] = ntohl(tcph->seq) + packet->payload_packet_len; + if(tcph->rst) { + flow->next_tcp_seq_nr[0] = 0; + flow->next_tcp_seq_nr[1] = 0; } + } else if(udph != NULL) { + if(!ndpi_str->direction_detect_disable) + packet->packet_direction = (htons(udph->source) < htons(udph->dest)) ? 1 : 0; } - if(tcph->rst) { - flow->next_tcp_seq_nr[0] = 0; - flow->next_tcp_seq_nr[1] = 0; + if(flow->packet_counter < MAX_PACKET_COUNTER && packet->payload_packet_len) { + flow->packet_counter++; } - } else if(udph != NULL) { - if(!ndpi_str->direction_detect_disable) - packet->packet_direction = (htons(udph->source) < htons(udph->dest)) ? 1 : 0; - } - - if(flow->packet_counter < MAX_PACKET_COUNTER && packet->payload_packet_len) { - flow->packet_counter++; - } - if(flow->packet_direction_counter[packet->packet_direction] < MAX_PACKET_COUNTER && - packet->payload_packet_len) { - flow->packet_direction_counter[packet->packet_direction]++; - } + if(flow->packet_direction_counter[packet->packet_direction] < MAX_PACKET_COUNTER && + packet->payload_packet_len) { + flow->packet_direction_counter[packet->packet_direction]++; + } - if(flow->byte_counter[packet->packet_direction] + packet->payload_packet_len > - flow->byte_counter[packet->packet_direction]) { - flow->byte_counter[packet->packet_direction] += packet->payload_packet_len; + if(flow->byte_counter[packet->packet_direction] + packet->payload_packet_len > + flow->byte_counter[packet->packet_direction]) { + flow->byte_counter[packet->packet_direction] += packet->payload_packet_len; + } } - } #ifdef FRAG_MAN - return 1; + return 1; #endif // FRAG_MAN -} - -/* ************************************************ */ - -u_int32_t check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { - void *func = NULL; - u_int32_t a, num_calls = 0; - u_int16_t proto_index = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoIdx; - int16_t proto_id = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoId; - NDPI_PROTOCOL_BITMASK detection_bitmask; - - NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]); - - if((proto_id != NDPI_PROTOCOL_UNKNOWN) && - NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, - ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 && - NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[proto_index].detection_bitmask, detection_bitmask) != 0 && - (ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask & *ndpi_selection_packet) == - ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask) { - if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) && - (ndpi_str->proto_defaults[flow->guessed_protocol_id].func != NULL)) - ndpi_str->proto_defaults[flow->guessed_protocol_id].func(ndpi_str, flow), - func = ndpi_str->proto_defaults[flow->guessed_protocol_id].func, num_calls++; - } - - for (a = 0; a < ndpi_str->callback_buffer_size_non_tcp_udp; a++) { - if((func != ndpi_str->callback_buffer_non_tcp_udp[a].func) && - (ndpi_str->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask & *ndpi_selection_packet) == - ndpi_str->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask && - NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, - ndpi_str->callback_buffer_non_tcp_udp[a].excluded_protocol_bitmask) == 0 && - NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_non_tcp_udp[a].detection_bitmask, detection_bitmask) != 0) { - if(ndpi_str->callback_buffer_non_tcp_udp[a].func != NULL) - ndpi_str->callback_buffer_non_tcp_udp[a].func(ndpi_str, flow), num_calls++; - - if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) - break; /* Stop after detecting the first protocol */ - } } - return(num_calls); -} + /* ************************************************ */ -/* ************************************************ */ + u_int32_t check_ndpi_other_flow_func(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { + void *func = NULL; + u_int32_t a, num_calls = 0; + u_int16_t proto_index = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoIdx; + int16_t proto_id = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoId; + NDPI_PROTOCOL_BITMASK detection_bitmask; -static u_int32_t check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { - void *func = NULL; - u_int32_t a, num_calls = 0; - u_int16_t proto_index = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoIdx; - int16_t proto_id = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoId; - NDPI_PROTOCOL_BITMASK detection_bitmask; - - NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]); - - if((proto_id != NDPI_PROTOCOL_UNKNOWN) && - NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, - ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 && - NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[proto_index].detection_bitmask, detection_bitmask) != 0 && - (ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask & *ndpi_selection_packet) == - ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask) { - if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) && - (ndpi_str->proto_defaults[flow->guessed_protocol_id].func != NULL)) - ndpi_str->proto_defaults[flow->guessed_protocol_id].func(ndpi_str, flow), - func = ndpi_str->proto_defaults[flow->guessed_protocol_id].func, num_calls++; - } - - if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { - for (a = 0; a < ndpi_str->callback_buffer_size_udp; a++) { - if((func != ndpi_str->callback_buffer_udp[a].func) && - (ndpi_str->callback_buffer_udp[a].ndpi_selection_bitmask & *ndpi_selection_packet) == - ndpi_str->callback_buffer_udp[a].ndpi_selection_bitmask && - NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, - ndpi_str->callback_buffer_udp[a].excluded_protocol_bitmask) == 0 && - NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_udp[a].detection_bitmask, detection_bitmask) != 0) { - ndpi_str->callback_buffer_udp[a].func(ndpi_str, flow), num_calls++; + NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]); - // NDPI_LOG_DBG(ndpi_str, "[UDP,CALL] dissector of protocol as callback_buffer idx = %d\n",a); + if((proto_id != NDPI_PROTOCOL_UNKNOWN) && + NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, + ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 && + NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[proto_index].detection_bitmask, detection_bitmask) != 0 && + (ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask & *ndpi_selection_packet) == + ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask) { + if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) && + (ndpi_str->proto_defaults[flow->guessed_protocol_id].func != NULL)) + ndpi_str->proto_defaults[flow->guessed_protocol_id].func(ndpi_str, flow), + func = ndpi_str->proto_defaults[flow->guessed_protocol_id].func, num_calls++; + } -#ifdef DEBUG_UDP_CALLS - { - char buf[64]; - u_int16_t proto_id = ndpi_str->callback_buffer_udp[a].ndpi_protocol_id; - ndpi_protocol proto = { proto_id, proto_id, 0 }; - printf("-> [UDP,CALL] dissector of protocol as callback_buffer idx = %d / %s\n", - proto_id, ndpi_protocol2name(ndpi_str, proto, buf, sizeof(buf))); - } -#endif + for (a = 0; a < ndpi_str->callback_buffer_size_non_tcp_udp; a++) { + if((func != ndpi_str->callback_buffer_non_tcp_udp[a].func) && + (ndpi_str->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask & *ndpi_selection_packet) == + ndpi_str->callback_buffer_non_tcp_udp[a].ndpi_selection_bitmask && + NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, + ndpi_str->callback_buffer_non_tcp_udp[a].excluded_protocol_bitmask) == 0 && + NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_non_tcp_udp[a].detection_bitmask, detection_bitmask) != 0) { + if(ndpi_str->callback_buffer_non_tcp_udp[a].func != NULL) + ndpi_str->callback_buffer_non_tcp_udp[a].func(ndpi_str, flow), num_calls++; if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) break; /* Stop after detecting the first protocol */ - } else if(_ndpi_debug_callbacks) - NDPI_LOG_DBG2(ndpi_str, "[UDP,SKIP] dissector of protocol as callback_buffer idx = %d\n", a); + } } - } else - num_calls = 1; - return(num_calls); -} + return(num_calls); + } -/* ************************************************ */ + /* ************************************************ */ -static u_int32_t check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { - void *func = NULL; - u_int32_t a, num_calls = 0; - u_int16_t proto_index = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoIdx; - int16_t proto_id = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoId; - NDPI_PROTOCOL_BITMASK detection_bitmask; + static u_int32_t check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { + void *func = NULL; + u_int32_t a, num_calls = 0; + u_int16_t proto_index = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoIdx; + int16_t proto_id = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoId; + NDPI_PROTOCOL_BITMASK detection_bitmask; - NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]); + NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]); - if(flow->packet.payload_packet_len != 0) { if((proto_id != NDPI_PROTOCOL_UNKNOWN) && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 && @@ -4090,1449 +4031,1512 @@ static u_int32_t check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *n } if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { - for (a = 0; a < ndpi_str->callback_buffer_size_tcp_payload; a++) { - if((func != ndpi_str->callback_buffer_tcp_payload[a].func) && - (ndpi_str->callback_buffer_tcp_payload[a].ndpi_selection_bitmask & *ndpi_selection_packet) == - ndpi_str->callback_buffer_tcp_payload[a].ndpi_selection_bitmask && + for (a = 0; a < ndpi_str->callback_buffer_size_udp; a++) { + if((func != ndpi_str->callback_buffer_udp[a].func) && + (ndpi_str->callback_buffer_udp[a].ndpi_selection_bitmask & *ndpi_selection_packet) == + ndpi_str->callback_buffer_udp[a].ndpi_selection_bitmask && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, - ndpi_str->callback_buffer_tcp_payload[a].excluded_protocol_bitmask) == 0 && - NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_tcp_payload[a].detection_bitmask, - detection_bitmask) != 0) { - ndpi_str->callback_buffer_tcp_payload[a].func(ndpi_str, flow), num_calls++; + ndpi_str->callback_buffer_udp[a].excluded_protocol_bitmask) == 0 && + NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_udp[a].detection_bitmask, detection_bitmask) != 0) { + ndpi_str->callback_buffer_udp[a].func(ndpi_str, flow), num_calls++; + + // NDPI_LOG_DBG(ndpi_str, "[UDP,CALL] dissector of protocol as callback_buffer idx = %d\n",a); + +#ifdef DEBUG_UDP_CALLS + { + char buf[64]; + u_int16_t proto_id = ndpi_str->callback_buffer_udp[a].ndpi_protocol_id; + ndpi_protocol proto = { proto_id, proto_id, 0 }; + printf("-> [UDP,CALL] dissector of protocol as callback_buffer idx = %d / %s\n", + proto_id, ndpi_protocol2name(ndpi_str, proto, buf, sizeof(buf))); + } +#endif + if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) break; /* Stop after detecting the first protocol */ - } + } else if(_ndpi_debug_callbacks) + NDPI_LOG_DBG2(ndpi_str, "[UDP,SKIP] dissector of protocol as callback_buffer idx = %d\n", a); } - } - } else { - /* no payload */ + } else + num_calls = 1; - num_calls = 1; + return(num_calls); + } - if((proto_id != NDPI_PROTOCOL_UNKNOWN) && - NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, - ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 && - NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[proto_index].detection_bitmask, detection_bitmask) != 0 && - (ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask & *ndpi_selection_packet) == - ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask) { - if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) && - (ndpi_str->proto_defaults[flow->guessed_protocol_id].func != NULL) && - ((ndpi_str->callback_buffer[flow->guessed_protocol_id].ndpi_selection_bitmask & - NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) == 0)) - ndpi_str->proto_defaults[flow->guessed_protocol_id].func(ndpi_str, flow), - func = ndpi_str->proto_defaults[flow->guessed_protocol_id].func, num_calls++; - } + /* ************************************************ */ + + static u_int32_t check_ndpi_tcp_flow_func(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { + void *func = NULL; + u_int32_t a, num_calls = 0; + u_int16_t proto_index = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoIdx; + int16_t proto_id = ndpi_str->proto_defaults[flow->guessed_protocol_id].protoId; + NDPI_PROTOCOL_BITMASK detection_bitmask; + + NDPI_SAVE_AS_BITMASK(detection_bitmask, flow->packet.detected_protocol_stack[0]); - for (a = 0; a < ndpi_str->callback_buffer_size_tcp_no_payload; a++) { - if((func != ndpi_str->callback_buffer_tcp_payload[a].func) && - (ndpi_str->callback_buffer_tcp_no_payload[a].ndpi_selection_bitmask & *ndpi_selection_packet) == - ndpi_str->callback_buffer_tcp_no_payload[a].ndpi_selection_bitmask && + if(flow->packet.payload_packet_len != 0) { + if((proto_id != NDPI_PROTOCOL_UNKNOWN) && NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, - ndpi_str->callback_buffer_tcp_no_payload[a].excluded_protocol_bitmask) == 0 && - NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_tcp_no_payload[a].detection_bitmask, - detection_bitmask) != 0) { - ndpi_str->callback_buffer_tcp_no_payload[a].func(ndpi_str, flow), num_calls++; - if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) - break; /* Stop after detecting the first protocol */ + ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 && + NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[proto_index].detection_bitmask, detection_bitmask) != 0 && + (ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask & *ndpi_selection_packet) == + ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask) { + if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) && + (ndpi_str->proto_defaults[flow->guessed_protocol_id].func != NULL)) + ndpi_str->proto_defaults[flow->guessed_protocol_id].func(ndpi_str, flow), + func = ndpi_str->proto_defaults[flow->guessed_protocol_id].func, num_calls++; + } + + if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { + for (a = 0; a < ndpi_str->callback_buffer_size_tcp_payload; a++) { + if((func != ndpi_str->callback_buffer_tcp_payload[a].func) && + (ndpi_str->callback_buffer_tcp_payload[a].ndpi_selection_bitmask & *ndpi_selection_packet) == + ndpi_str->callback_buffer_tcp_payload[a].ndpi_selection_bitmask && + NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, + ndpi_str->callback_buffer_tcp_payload[a].excluded_protocol_bitmask) == 0 && + NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_tcp_payload[a].detection_bitmask, + detection_bitmask) != 0) { + ndpi_str->callback_buffer_tcp_payload[a].func(ndpi_str, flow), num_calls++; + if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) + break; /* Stop after detecting the first protocol */ + } + } + } + } else { + /* no payload */ + + num_calls = 1; + + if((proto_id != NDPI_PROTOCOL_UNKNOWN) && + NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, + ndpi_str->callback_buffer[proto_index].excluded_protocol_bitmask) == 0 && + NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer[proto_index].detection_bitmask, detection_bitmask) != 0 && + (ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask & *ndpi_selection_packet) == + ndpi_str->callback_buffer[proto_index].ndpi_selection_bitmask) { + if((flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) && + (ndpi_str->proto_defaults[flow->guessed_protocol_id].func != NULL) && + ((ndpi_str->callback_buffer[flow->guessed_protocol_id].ndpi_selection_bitmask & + NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD) == 0)) + ndpi_str->proto_defaults[flow->guessed_protocol_id].func(ndpi_str, flow), + func = ndpi_str->proto_defaults[flow->guessed_protocol_id].func, num_calls++; + } + + for (a = 0; a < ndpi_str->callback_buffer_size_tcp_no_payload; a++) { + if((func != ndpi_str->callback_buffer_tcp_payload[a].func) && + (ndpi_str->callback_buffer_tcp_no_payload[a].ndpi_selection_bitmask & *ndpi_selection_packet) == + ndpi_str->callback_buffer_tcp_no_payload[a].ndpi_selection_bitmask && + NDPI_BITMASK_COMPARE(flow->excluded_protocol_bitmask, + ndpi_str->callback_buffer_tcp_no_payload[a].excluded_protocol_bitmask) == 0 && + NDPI_BITMASK_COMPARE(ndpi_str->callback_buffer_tcp_no_payload[a].detection_bitmask, + detection_bitmask) != 0) { + ndpi_str->callback_buffer_tcp_no_payload[a].func(ndpi_str, flow), num_calls++; + if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) + break; /* Stop after detecting the first protocol */ + } } } - } - return(num_calls); -} + return(num_calls); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -u_int32_t ndpi_check_flow_func(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { - if(!flow) - return(0); - else if(flow->packet.tcp != NULL) - return(check_ndpi_tcp_flow_func(ndpi_str, flow, ndpi_selection_packet)); - else if(flow->packet.udp != NULL) - return(check_ndpi_udp_flow_func(ndpi_str, flow, ndpi_selection_packet)); - else - return(check_ndpi_other_flow_func(ndpi_str, flow, ndpi_selection_packet)); -} + u_int32_t ndpi_check_flow_func(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + NDPI_SELECTION_BITMASK_PROTOCOL_SIZE *ndpi_selection_packet) { + if(!flow) + return(0); + else if(flow->packet.tcp != NULL) + return(check_ndpi_tcp_flow_func(ndpi_str, flow, ndpi_selection_packet)); + else if(flow->packet.udp != NULL) + return(check_ndpi_udp_flow_func(ndpi_str, flow, ndpi_selection_packet)); + else + return(check_ndpi_other_flow_func(ndpi_str, flow, ndpi_selection_packet)); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow) { - u_int16_t ret = NDPI_PROTOCOL_UNKNOWN; + u_int16_t ndpi_guess_host_protocol_id(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow) { + u_int16_t ret = NDPI_PROTOCOL_UNKNOWN; - if(flow->packet.iph) { - struct in_addr addr; - u_int16_t sport, dport; + if(flow->packet.iph) { + struct in_addr addr; + u_int16_t sport, dport; - addr.s_addr = flow->packet.iph->saddr; + addr.s_addr = flow->packet.iph->saddr; - if((flow->l4_proto == IPPROTO_TCP) && flow->packet.tcp) - sport = flow->packet.tcp->source, dport = flow->packet.tcp->dest; - else if((flow->l4_proto == IPPROTO_UDP) && flow->packet.udp) - sport = flow->packet.udp->source, dport = flow->packet.udp->dest; - else - sport = dport = 0; + if((flow->l4_proto == IPPROTO_TCP) && flow->packet.tcp) + sport = flow->packet.tcp->source, dport = flow->packet.tcp->dest; + else if((flow->l4_proto == IPPROTO_UDP) && flow->packet.udp) + sport = flow->packet.udp->source, dport = flow->packet.udp->dest; + else + sport = dport = 0; - /* guess host protocol */ - ret = ndpi_network_port_ptree_match(ndpi_str, &addr, sport); + /* guess host protocol */ + ret = ndpi_network_port_ptree_match(ndpi_str, &addr, sport); - if(ret == NDPI_PROTOCOL_UNKNOWN) { - addr.s_addr = flow->packet.iph->daddr; - ret = ndpi_network_port_ptree_match(ndpi_str, &addr, dport); + if(ret == NDPI_PROTOCOL_UNKNOWN) { + addr.s_addr = flow->packet.iph->daddr; + ret = ndpi_network_port_ptree_match(ndpi_str, &addr, dport); + } } + + return(ret); } - return(ret); -} + /* ********************************************************************************* */ -/* ********************************************************************************* */ + ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + u_int8_t enable_guess, u_int8_t *protocol_was_guessed) { + ndpi_protocol ret = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED}; -ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - u_int8_t enable_guess, u_int8_t *protocol_was_guessed) { - ndpi_protocol ret = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED}; + *protocol_was_guessed = 0; - *protocol_was_guessed = 0; + if(flow == NULL) + return(ret); - if(flow == NULL) - return(ret); + /* Init defaults */ + ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; + 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); - /* 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) { + u_int16_t guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN, guessed_host_protocol_id = NDPI_PROTOCOL_UNKNOWN; - /* TODO: add the remaining stage_XXXX protocols */ - if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { - u_int16_t guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN, guessed_host_protocol_id = NDPI_PROTOCOL_UNKNOWN; + if(flow->guessed_protocol_id == NDPI_PROTOCOL_STUN) + goto check_stun_export; + else if((flow->guessed_protocol_id == NDPI_PROTOCOL_HANGOUT_DUO) || + (flow->guessed_protocol_id == NDPI_PROTOCOL_MESSENGER) || + (flow->guessed_protocol_id == NDPI_PROTOCOL_WHATSAPP_CALL)) { + *protocol_was_guessed = 1; + ndpi_set_detected_protocol(ndpi_str, flow, flow->guessed_protocol_id, NDPI_PROTOCOL_UNKNOWN); + } + else if((flow->l4.tcp.tls.hello_processed == 1) && + (flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] != '\0')) { + *protocol_was_guessed = 1; + ndpi_set_detected_protocol(ndpi_str, flow, NDPI_PROTOCOL_TLS, NDPI_PROTOCOL_UNKNOWN); + } else if(enable_guess) { + if((flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) && (flow->packet.l4_protocol == IPPROTO_TCP) && + flow->l4.tcp.tls.hello_processed) + flow->guessed_protocol_id = NDPI_PROTOCOL_TLS; + + guessed_protocol_id = flow->guessed_protocol_id, guessed_host_protocol_id = flow->guessed_host_protocol_id; + + if((guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) && + ((flow->packet.l4_protocol == IPPROTO_UDP) && + NDPI_ISSET(&flow->excluded_protocol_bitmask, guessed_host_protocol_id) && + is_udp_guessable_protocol(guessed_host_protocol_id))) + flow->guessed_host_protocol_id = guessed_host_protocol_id = NDPI_PROTOCOL_UNKNOWN; + + /* Ignore guessed protocol if they have been discarded */ + if((guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) + // && (guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) + && (flow->packet.l4_protocol == IPPROTO_UDP) && + NDPI_ISSET(&flow->excluded_protocol_bitmask, guessed_protocol_id) && + is_udp_guessable_protocol(guessed_protocol_id)) + flow->guessed_protocol_id = guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN; + + if((guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) || (guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN)) { + if((guessed_protocol_id == 0) && (flow->protos.tls_quic_stun.stun.num_binding_requests > 0) && + (flow->protos.tls_quic_stun.stun.num_processed_pkts > 0)) + guessed_protocol_id = NDPI_PROTOCOL_STUN; + + if(flow->host_server_name[0] != '\0') { + ndpi_protocol_match_result ret_match; + + memset(&ret_match, 0, sizeof(ret_match)); + + ndpi_match_host_subprotocol(ndpi_str, flow, (char *) flow->host_server_name, + strlen((const char *) flow->host_server_name), &ret_match, + NDPI_PROTOCOL_DNS); + + if(ret_match.protocol_id != NDPI_PROTOCOL_UNKNOWN) + guessed_host_protocol_id = ret_match.protocol_id; + } - if(flow->guessed_protocol_id == NDPI_PROTOCOL_STUN) - goto check_stun_export; - else if((flow->guessed_protocol_id == NDPI_PROTOCOL_HANGOUT_DUO) || - (flow->guessed_protocol_id == NDPI_PROTOCOL_MESSENGER) || - (flow->guessed_protocol_id == NDPI_PROTOCOL_WHATSAPP_CALL)) { - *protocol_was_guessed = 1; - ndpi_set_detected_protocol(ndpi_str, flow, flow->guessed_protocol_id, NDPI_PROTOCOL_UNKNOWN); - } - else if((flow->l4.tcp.tls.hello_processed == 1) && - (flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] != '\0')) { - *protocol_was_guessed = 1; - ndpi_set_detected_protocol(ndpi_str, flow, NDPI_PROTOCOL_TLS, NDPI_PROTOCOL_UNKNOWN); - } else if(enable_guess) { - if((flow->guessed_protocol_id == NDPI_PROTOCOL_UNKNOWN) && (flow->packet.l4_protocol == IPPROTO_TCP) && - flow->l4.tcp.tls.hello_processed) - flow->guessed_protocol_id = NDPI_PROTOCOL_TLS; - - guessed_protocol_id = flow->guessed_protocol_id, guessed_host_protocol_id = flow->guessed_host_protocol_id; - - if((guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) && - ((flow->packet.l4_protocol == IPPROTO_UDP) && - NDPI_ISSET(&flow->excluded_protocol_bitmask, guessed_host_protocol_id) && - is_udp_guessable_protocol(guessed_host_protocol_id))) - flow->guessed_host_protocol_id = guessed_host_protocol_id = NDPI_PROTOCOL_UNKNOWN; - - /* Ignore guessed protocol if they have been discarded */ - if((guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) - // && (guessed_host_protocol_id == NDPI_PROTOCOL_UNKNOWN) - && (flow->packet.l4_protocol == IPPROTO_UDP) && - NDPI_ISSET(&flow->excluded_protocol_bitmask, guessed_protocol_id) && - is_udp_guessable_protocol(guessed_protocol_id)) - flow->guessed_protocol_id = guessed_protocol_id = NDPI_PROTOCOL_UNKNOWN; - - if((guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) || (guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN)) { - if((guessed_protocol_id == 0) && (flow->protos.tls_quic_stun.stun.num_binding_requests > 0) && - (flow->protos.tls_quic_stun.stun.num_processed_pkts > 0)) - guessed_protocol_id = NDPI_PROTOCOL_STUN; - - if(flow->host_server_name[0] != '\0') { - ndpi_protocol_match_result ret_match; - - memset(&ret_match, 0, sizeof(ret_match)); - - ndpi_match_host_subprotocol(ndpi_str, flow, (char *) flow->host_server_name, - strlen((const char *) flow->host_server_name), &ret_match, - NDPI_PROTOCOL_DNS); - - if(ret_match.protocol_id != NDPI_PROTOCOL_UNKNOWN) - guessed_host_protocol_id = ret_match.protocol_id; + *protocol_was_guessed = 1; + ndpi_int_change_protocol(ndpi_str, flow, guessed_host_protocol_id, guessed_protocol_id); } + } + } else if(enable_guess) { + if(flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) { + *protocol_was_guessed = 1; + flow->detected_protocol_stack[1] = flow->guessed_protocol_id; + } + if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) { *protocol_was_guessed = 1; - ndpi_int_change_protocol(ndpi_str, flow, guessed_host_protocol_id, guessed_protocol_id); + flow->detected_protocol_stack[0] = flow->guessed_host_protocol_id; } - } - } else if(enable_guess) { - if(flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) { - *protocol_was_guessed = 1; - flow->detected_protocol_stack[1] = flow->guessed_protocol_id; - } - if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) { - *protocol_was_guessed = 1; - flow->detected_protocol_stack[0] = flow->guessed_host_protocol_id; + if(flow->detected_protocol_stack[1] == flow->detected_protocol_stack[0]) { + *protocol_was_guessed = 1; + flow->detected_protocol_stack[1] = flow->guessed_host_protocol_id; + } } - if(flow->detected_protocol_stack[1] == flow->detected_protocol_stack[0]) { - *protocol_was_guessed = 1; - flow->detected_protocol_stack[1] = flow->guessed_host_protocol_id; + if((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) && + (flow->guessed_protocol_id == NDPI_PROTOCOL_STUN)) { + check_stun_export: + if(flow->protos.tls_quic_stun.stun.num_processed_pkts || flow->protos.tls_quic_stun.stun.num_udp_pkts) { + // if(/* (flow->protos.tls_quic_stun.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) */ + *protocol_was_guessed = 1; + ndpi_set_detected_protocol(ndpi_str, flow, flow->guessed_host_protocol_id, NDPI_PROTOCOL_STUN); + } } - } - if((flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) && - (flow->guessed_protocol_id == NDPI_PROTOCOL_STUN)) { - check_stun_export: - if(flow->protos.tls_quic_stun.stun.num_processed_pkts || flow->protos.tls_quic_stun.stun.num_udp_pkts) { - // if(/* (flow->protos.tls_quic_stun.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) */ - *protocol_was_guessed = 1; - ndpi_set_detected_protocol(ndpi_str, flow, flow->guessed_host_protocol_id, NDPI_PROTOCOL_STUN); - } - } + ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; - ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; + if(ret.master_protocol == NDPI_PROTOCOL_STUN) { + if(ret.app_protocol == NDPI_PROTOCOL_FACEBOOK) + ret.app_protocol = NDPI_PROTOCOL_MESSENGER; + else if(ret.app_protocol == NDPI_PROTOCOL_GOOGLE) { + /* + As Google has recently introduced Duo, + we need to distinguish between it and hangout + thing that should be handled by the STUN dissector + */ + ret.app_protocol = NDPI_PROTOCOL_HANGOUT_DUO; + } + } - if(ret.master_protocol == NDPI_PROTOCOL_STUN) { - if(ret.app_protocol == NDPI_PROTOCOL_FACEBOOK) - ret.app_protocol = NDPI_PROTOCOL_MESSENGER; - else if(ret.app_protocol == NDPI_PROTOCOL_GOOGLE) { - /* - As Google has recently introduced Duo, - we need to distinguish between it and hangout - thing that should be handled by the STUN dissector - */ - ret.app_protocol = NDPI_PROTOCOL_HANGOUT_DUO; + if(ret.app_protocol != NDPI_PROTOCOL_UNKNOWN) { + *protocol_was_guessed = 1; + ndpi_fill_protocol_category(ndpi_str, flow, &ret); } - } - if(ret.app_protocol != NDPI_PROTOCOL_UNKNOWN) { - *protocol_was_guessed = 1; - ndpi_fill_protocol_category(ndpi_str, flow, &ret); + return(ret); } - return(ret); -} - -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_process_extra_packet(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - const unsigned char *packet, const unsigned short packetlen, - const u_int64_t current_time_ms, struct ndpi_id_struct *src, struct ndpi_id_struct *dst) { - if(flow == NULL) - return; + void ndpi_process_extra_packet(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + const unsigned char *packet, const unsigned short packetlen, + const u_int64_t current_time_ms, struct ndpi_id_struct *src, struct ndpi_id_struct *dst) { + if(flow == NULL) + return; - if(flow->server_id == NULL) - flow->server_id = dst; /* Default */ + if(flow->server_id == NULL) + flow->server_id = dst; /* Default */ - /* need at least 20 bytes for ip header */ - if(packetlen < 20) { - return; - } + /* need at least 20 bytes for ip header */ + if(packetlen < 20) { + return; + } - flow->packet.current_time_ms = current_time_ms; + flow->packet.current_time_ms = current_time_ms; - /* parse packet */ - flow->packet.iph = (struct ndpi_iphdr *) packet; - /* we are interested in ipv4 packet */ + /* parse packet */ + flow->packet.iph = (struct ndpi_iphdr *) packet; + /* we are interested in ipv4 packet */ - /* set up the packet headers for the extra packet function to use if it wants */ - if(ndpi_init_packet_header(ndpi_str, flow, packetlen) != 0) - return; + /* set up the packet headers for the extra packet function to use if it wants */ + if(ndpi_init_packet_header(ndpi_str, flow, packetlen) != 0) + return; - /* detect traffic for tcp or udp only */ - flow->src = src, flow->dst = dst; + /* detect traffic for tcp or udp only */ + flow->src = src, flow->dst = dst; #ifdef FRAG_MAN - if ( ndpi_connection_tracking(ndpi_str, flow) ) { + if( ndpi_connection_tracking(ndpi_str, flow) ) { #else // FRAG_MAN - ndpi_connection_tracking(ndpi_str, flow); + ndpi_connection_tracking(ndpi_str, flow); #endif // FRAG_MAN - /* call the extra packet function (which may add more data/info to flow) */ - if(flow->extra_packets_func) { - if((flow->extra_packets_func(ndpi_str, flow)) == 0) - flow->check_extra_packets = 0; + /* call the extra packet function (which may add more data/info to flow) */ + if(flow->extra_packets_func) { + if((flow->extra_packets_func(ndpi_str, flow)) == 0) + flow->check_extra_packets = 0; - if(++flow->num_extra_packets_checked == flow->max_extra_packets_to_check) - flow->extra_packets_func = NULL; /* Enough packets detected */ - } + if(++flow->num_extra_packets_checked == flow->max_extra_packets_to_check) + flow->extra_packets_func = NULL; /* Enough packets detected */ + } #ifdef FRAG_MAN - } + } #endif // FRAG_MAN -} + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -int ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_str, const char *ip_address_and_mask, - ndpi_protocol_category_t category) { - patricia_node_t *node; - struct in_addr pin; - int bits = 32; - char *ptr; - char ipbuf[64]; + int ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_str, const char *ip_address_and_mask, + ndpi_protocol_category_t category) { + patricia_node_t *node; + struct in_addr pin; + int bits = 32; + char *ptr; + char ipbuf[64]; - strncpy(ipbuf, ip_address_and_mask, sizeof(ipbuf)); - ipbuf[sizeof(ipbuf) - 1] = '\0'; + strncpy(ipbuf, ip_address_and_mask, sizeof(ipbuf)); + ipbuf[sizeof(ipbuf) - 1] = '\0'; - ptr = strrchr(ipbuf, '/'); + ptr = strrchr(ipbuf, '/'); - if(ptr) { - *(ptr++) = '\0'; - if(atoi(ptr) >= 0 && atoi(ptr) <= 32) - bits = atoi(ptr); - } + if(ptr) { + *(ptr++) = '\0'; + if(atoi(ptr) >= 0 && atoi(ptr) <= 32) + bits = atoi(ptr); + } - if(inet_pton(AF_INET, ipbuf, &pin) != 1) { - NDPI_LOG_DBG2(ndpi_str, "Invalid ip/ip+netmask: %s\n", ip_address_and_mask); - return(-1); - } + if(inet_pton(AF_INET, ipbuf, &pin) != 1) { + NDPI_LOG_DBG2(ndpi_str, "Invalid ip/ip+netmask: %s\n", ip_address_and_mask); + return(-1); + } - if((node = add_to_ptree(ndpi_str->custom_categories.ipAddresses_shadow, AF_INET, &pin, bits)) != NULL) { - node->value.u.uv32.user_value = (u_int16_t)category, node->value.u.uv32.additional_user_value = 0; - } + if((node = add_to_ptree(ndpi_str->custom_categories.ipAddresses_shadow, AF_INET, &pin, bits)) != NULL) { + node->value.u.uv32.user_value = (u_int16_t)category, node->value.u.uv32.additional_user_value = 0; + } - return(0); -} + return(0); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_str, const char *name_to_add, - ndpi_protocol_category_t category) { - char *name; + int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_str, const char *name_to_add, + ndpi_protocol_category_t category) { + char *name; - if(name_to_add == NULL) - return(-1); + if(name_to_add == NULL) + return(-1); - name = ndpi_strdup(name_to_add); + name = ndpi_strdup(name_to_add); - if(name == NULL) - return(-1); + if(name == NULL) + return(-1); #if 0 - printf("===> %s() Loading %s as %u\n", __FUNCTION__, name, category); + printf("===> %s() Loading %s as %u\n", __FUNCTION__, name, category); #endif - AC_PATTERN_t ac_pattern; - AC_ERROR_t rc; + AC_PATTERN_t ac_pattern; + AC_ERROR_t rc; - memset(&ac_pattern, 0, sizeof(ac_pattern)); + memset(&ac_pattern, 0, sizeof(ac_pattern)); - if(ndpi_str->custom_categories.hostnames_shadow.ac_automa == NULL) { - ndpi_free(name); - return(-1); - } - - ac_pattern.astring = name, ac_pattern.length = strlen(ac_pattern.astring); - ac_pattern.rep.number = (u_int32_t) category, ac_pattern.rep.category = category;; + if(ndpi_str->custom_categories.hostnames_shadow.ac_automa == NULL) { + ndpi_free(name); + return(-1); + } - rc = ac_automata_add(ndpi_str->custom_categories.hostnames_shadow.ac_automa, &ac_pattern); - if(rc != ACERR_DUPLICATE_PATTERN && rc != ACERR_SUCCESS) { - ndpi_free(name); - return(-1); - } + ac_pattern.astring = name, ac_pattern.length = strlen(ac_pattern.astring); + ac_pattern.rep.number = (u_int32_t) category, ac_pattern.rep.category = category;; - if(rc == ACERR_DUPLICATE_PATTERN) - ndpi_free(name); + rc = ac_automata_add(ndpi_str->custom_categories.hostnames_shadow.ac_automa, &ac_pattern); + if(rc != ACERR_DUPLICATE_PATTERN && rc != ACERR_SUCCESS) { + ndpi_free(name); + return(-1); + } - return(0); -} + if(rc == ACERR_DUPLICATE_PATTERN) + ndpi_free(name); -/* ********************************************************************************* */ + return(0); + } -/* Loads an IP or name category */ -int ndpi_load_category(struct ndpi_detection_module_struct *ndpi_struct, const char *ip_or_name, - ndpi_protocol_category_t category) { - int rv; + /* ********************************************************************************* */ - /* Try to load as IP address first */ - rv = ndpi_load_ip_category(ndpi_struct, ip_or_name, category); + /* Loads an IP or name category */ + int ndpi_load_category(struct ndpi_detection_module_struct *ndpi_struct, const char *ip_or_name, + ndpi_protocol_category_t category) { + int rv; - if(rv < 0) { - /* IP load failed, load as hostname */ - rv = ndpi_load_hostname_category(ndpi_struct, ip_or_name, category); - } + /* Try to load as IP address first */ + rv = ndpi_load_ip_category(ndpi_struct, ip_or_name, category); - return(rv); -} + if(rv < 0) { + /* IP load failed, load as hostname */ + rv = ndpi_load_hostname_category(ndpi_struct, ip_or_name, category); + } -/* ********************************************************************************* */ + return(rv); + } -int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_str) { - int i; + /* ********************************************************************************* */ - /* First add the nDPI known categories matches */ - for (i = 0; category_match[i].string_to_match != NULL; i++) - ndpi_load_category(ndpi_str, category_match[i].string_to_match, category_match[i].protocol_category); + int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_str) { + int i; - /* Free */ - ac_automata_release((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames.ac_automa, - 1 /* free patterns strings memory */); + /* First add the nDPI known categories matches */ + for (i = 0; category_match[i].string_to_match != NULL; i++) + ndpi_load_category(ndpi_str, category_match[i].string_to_match, category_match[i].protocol_category); - /* Finalize */ - ac_automata_finalize((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames_shadow.ac_automa); + /* Free */ + ac_automata_release((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames.ac_automa, + 1 /* free patterns strings memory */); - /* Swap */ - ndpi_str->custom_categories.hostnames.ac_automa = ndpi_str->custom_categories.hostnames_shadow.ac_automa; + /* Finalize */ + ac_automata_finalize((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames_shadow.ac_automa); - /* Realloc */ - ndpi_str->custom_categories.hostnames_shadow.ac_automa = ac_automata_init(ac_match_handler); + /* Swap */ + ndpi_str->custom_categories.hostnames.ac_automa = ndpi_str->custom_categories.hostnames_shadow.ac_automa; - if(ndpi_str->custom_categories.ipAddresses != NULL) - ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data); + /* Realloc */ + ndpi_str->custom_categories.hostnames_shadow.ac_automa = ac_automata_init(ac_match_handler); - ndpi_str->custom_categories.ipAddresses = ndpi_str->custom_categories.ipAddresses_shadow; - ndpi_str->custom_categories.ipAddresses_shadow = ndpi_New_Patricia(32 /* IPv4 */); + if(ndpi_str->custom_categories.ipAddresses != NULL) + ndpi_Destroy_Patricia((patricia_tree_t *) ndpi_str->custom_categories.ipAddresses, free_ptree_data); - ndpi_str->custom_categories.categories_loaded = 1; + ndpi_str->custom_categories.ipAddresses = ndpi_str->custom_categories.ipAddresses_shadow; + ndpi_str->custom_categories.ipAddresses_shadow = ndpi_New_Patricia(32 /* IPv4 */); - return(0); -} + ndpi_str->custom_categories.categories_loaded = 1; -/* ********************************************************************************* */ + return(0); + } -int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str, u_int32_t saddr, u_int32_t daddr, - ndpi_protocol *ret) { - if(ndpi_str->custom_categories.categories_loaded) { - prefix_t prefix; - patricia_node_t *node; + /* ********************************************************************************* */ - if(saddr == 0) - node = NULL; - else { - /* Make sure all in network byte order otherwise compares wont work */ - fill_prefix_v4(&prefix, (struct in_addr *) &saddr, 32, - ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); - node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix); - } + int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str, u_int32_t saddr, u_int32_t daddr, + ndpi_protocol *ret) { + if(ndpi_str->custom_categories.categories_loaded) { + prefix_t prefix; + patricia_node_t *node; - if(!node) { - if(daddr != 0) { - fill_prefix_v4(&prefix, (struct in_addr *) &daddr, 32, + if(saddr == 0) + node = NULL; + else { + /* Make sure all in network byte order otherwise compares wont work */ + fill_prefix_v4(&prefix, (struct in_addr *) &saddr, 32, ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix); } - } - if(node) { - ret->category = (ndpi_protocol_category_t) node->value.u.uv32.user_value; + if(!node) { + if(daddr != 0) { + fill_prefix_v4(&prefix, (struct in_addr *) &daddr, 32, + ((patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits); + node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix); + } + } - return(1); + if(node) { + ret->category = (ndpi_protocol_category_t) node->value.u.uv32.user_value; + + return(1); + } } - } - ret->category = ndpi_get_proto_category(ndpi_str, *ret); + ret->category = ndpi_get_proto_category(ndpi_str, *ret); - return(0); -} + return(0); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - ndpi_protocol *ret) { - if(ndpi_str->custom_categories.categories_loaded) { - if(flow->guessed_header_category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) { - flow->category = ret->category = flow->guessed_header_category; - return; - } + void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + ndpi_protocol *ret) { + if(ndpi_str->custom_categories.categories_loaded) { + if(flow->guessed_header_category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) { + flow->category = ret->category = flow->guessed_header_category; + return; + } - if(flow->host_server_name[0] != '\0') { - u_int32_t id; - int rc = ndpi_match_custom_category(ndpi_str, (char *) flow->host_server_name, - strlen((char *) flow->host_server_name), &id); + if(flow->host_server_name[0] != '\0') { + u_int32_t id; + int rc = ndpi_match_custom_category(ndpi_str, (char *) flow->host_server_name, + strlen((char *) flow->host_server_name), &id); - if(rc == 0) { - flow->category = ret->category = (ndpi_protocol_category_t) id; - return; + if(rc == 0) { + flow->category = ret->category = (ndpi_protocol_category_t) id; + return; + } } - } - if(flow->l4.tcp.tls.hello_processed == 1 && - flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] != '\0') { - u_int32_t id; - int rc = ndpi_match_custom_category(ndpi_str, (char *) flow->protos.tls_quic_stun.tls_quic.client_requested_server_name, - strlen(flow->protos.tls_quic_stun.tls_quic.client_requested_server_name), &id); + if(flow->l4.tcp.tls.hello_processed == 1 && + flow->protos.tls_quic_stun.tls_quic.client_requested_server_name[0] != '\0') { + u_int32_t id; + int rc = ndpi_match_custom_category(ndpi_str, (char *) flow->protos.tls_quic_stun.tls_quic.client_requested_server_name, + strlen(flow->protos.tls_quic_stun.tls_quic.client_requested_server_name), &id); - if(rc == 0) { - flow->category = ret->category = (ndpi_protocol_category_t) id; - return; + if(rc == 0) { + flow->category = ret->category = (ndpi_protocol_category_t) id; + return; + } } } + + flow->category = ret->category = ndpi_get_proto_category(ndpi_str, *ret); } - flow->category = ret->category = ndpi_get_proto_category(ndpi_str, *ret); -} + /* ********************************************************************************* */ -/* ********************************************************************************* */ - -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->content_disposition_line.ptr = NULL, - packet->content_disposition_line.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, - packet->forwarded_line.ptr = NULL, packet->forwarded_line.len = 0; -} + 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->content_disposition_line.ptr = NULL, + packet->content_disposition_line.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, + packet->forwarded_line.ptr = NULL, packet->forwarded_line.len = 0; + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -static int ndpi_is_ntop_protocol(ndpi_protocol *ret) { - if((ret->master_protocol == NDPI_PROTOCOL_HTTP) && (ret->app_protocol == NDPI_PROTOCOL_NTOP)) - return(1); - else - return(0); -} + static int ndpi_is_ntop_protocol(ndpi_protocol *ret) { + if((ret->master_protocol == NDPI_PROTOCOL_HTTP) && (ret->app_protocol == NDPI_PROTOCOL_NTOP)) + return(1); + else + return(0); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -static int ndpi_check_protocol_port_mismatch_exceptions(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - ndpi_default_ports_tree_node_t *expected_proto, - ndpi_protocol *returned_proto) { - /* - For TLS (and other protocols) it is not simple to guess the exact protocol so before - triggering an alert we need to make sure what we have exhausted all the possible - options available - */ + static int ndpi_check_protocol_port_mismatch_exceptions(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + ndpi_default_ports_tree_node_t *expected_proto, + ndpi_protocol *returned_proto) { + /* + For TLS (and other protocols) it is not simple to guess the exact protocol so before + triggering an alert we need to make sure what we have exhausted all the possible + options available + */ - if(ndpi_is_ntop_protocol(returned_proto)) return(1); + if(ndpi_is_ntop_protocol(returned_proto)) return(1); - if(returned_proto->master_protocol == NDPI_PROTOCOL_TLS) { - switch(expected_proto->proto->protoId) { - case NDPI_PROTOCOL_MAIL_IMAPS: - case NDPI_PROTOCOL_MAIL_POPS: - case NDPI_PROTOCOL_MAIL_SMTPS: - return(1); /* This is a reasonable exception */ - break; + if(returned_proto->master_protocol == NDPI_PROTOCOL_TLS) { + switch(expected_proto->proto->protoId) { + case NDPI_PROTOCOL_MAIL_IMAPS: + case NDPI_PROTOCOL_MAIL_POPS: + case NDPI_PROTOCOL_MAIL_SMTPS: + return(1); /* This is a reasonable exception */ + break; + } } - } - - return(0); -} - -/* ********************************************************************************* */ -static void ndpi_reconcile_protocols(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - ndpi_protocol *ret) { - /* - Skype for a host doing MS Teams means MS Teams - (MS Teams uses Skype as transport protocol for voice/video) - */ - if(flow) { - /* Do not go for DNS when there is an application protocol. Example DNS.Apple */ - if((flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN) - && (flow->detected_protocol_stack[0] /* app */ != flow->detected_protocol_stack[1] /* major */)) - NDPI_CLR_BIT(flow->risk, NDPI_SUSPICIOUS_DGA_DOMAIN); + return(0); } - switch(ret->app_protocol) { - case NDPI_PROTOCOL_MSTEAMS: - if(flow->packet.iph && flow->packet.tcp) { - // printf("====>> NDPI_PROTOCOL_MSTEAMS\n"); - - if(ndpi_str->msteams_cache == NULL) - ndpi_str->msteams_cache = ndpi_lru_cache_init(1024); + /* ********************************************************************************* */ - if(ndpi_str->msteams_cache) - ndpi_lru_add_to_cache(ndpi_str->msteams_cache, - flow->packet.iph->saddr, - (flow->packet.current_time_ms / 1000) & 0xFFFF /* 16 bit */); + static void ndpi_reconcile_protocols(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + ndpi_protocol *ret) { + /* + Skype for a host doing MS Teams means MS Teams + (MS Teams uses Skype as transport protocol for voice/video) + */ + if(flow) { + /* Do not go for DNS when there is an application protocol. Example DNS.Apple */ + if((flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN) + && (flow->detected_protocol_stack[0] /* app */ != flow->detected_protocol_stack[1] /* major */)) + NDPI_CLR_BIT(flow->risk, NDPI_SUSPICIOUS_DGA_DOMAIN); } - break; - - case NDPI_PROTOCOL_SKYPE: - case NDPI_PROTOCOL_SKYPE_CALL: - if(flow->packet.iph - && flow->packet.udp - && ndpi_str->msteams_cache) { - u_int16_t when; - if(ndpi_lru_find_cache(ndpi_str->msteams_cache, flow->packet.iph->saddr, - &when, 0 /* Don't remove it as it can be used for other connections */)) { - u_int16_t tdiff = ((flow->packet.current_time_ms /1000) & 0xFFFF) - when; + switch(ret->app_protocol) { + case NDPI_PROTOCOL_MSTEAMS: + if(flow->packet.iph && flow->packet.tcp) { + // printf("====>> NDPI_PROTOCOL_MSTEAMS\n"); - if(tdiff < 60 /* sec */) { - // printf("====>> NDPI_PROTOCOL_SKYPE(_CALL) -> NDPI_PROTOCOL_MSTEAMS [%u]\n", tdiff); - ret->app_protocol = NDPI_PROTOCOL_MSTEAMS; + if(ndpi_str->msteams_cache == NULL) + ndpi_str->msteams_cache = ndpi_lru_cache_init(1024); - /* Refresh cache */ + if(ndpi_str->msteams_cache) ndpi_lru_add_to_cache(ndpi_str->msteams_cache, flow->packet.iph->saddr, (flow->packet.current_time_ms / 1000) & 0xFFFF /* 16 bit */); - } } - } - break; - } /* switch */ - - if(flow) { - switch(ndpi_get_proto_breed(ndpi_str, ret->app_protocol)) { - case NDPI_PROTOCOL_UNSAFE: - case NDPI_PROTOCOL_POTENTIALLY_DANGEROUS: - case NDPI_PROTOCOL_DANGEROUS: - NDPI_SET_BIT(flow->risk, NDPI_UNSAFE_PROTOCOL); break; - default: - /* Nothing to do */ + + case NDPI_PROTOCOL_SKYPE: + case NDPI_PROTOCOL_SKYPE_CALL: + if(flow->packet.iph + && flow->packet.udp + && ndpi_str->msteams_cache) { + u_int16_t when; + + if(ndpi_lru_find_cache(ndpi_str->msteams_cache, flow->packet.iph->saddr, + &when, 0 /* Don't remove it as it can be used for other connections */)) { + u_int16_t tdiff = ((flow->packet.current_time_ms /1000) & 0xFFFF) - when; + + if(tdiff < 60 /* sec */) { + // printf("====>> NDPI_PROTOCOL_SKYPE(_CALL) -> NDPI_PROTOCOL_MSTEAMS [%u]\n", tdiff); + ret->app_protocol = NDPI_PROTOCOL_MSTEAMS; + + /* Refresh cache */ + ndpi_lru_add_to_cache(ndpi_str->msteams_cache, + flow->packet.iph->saddr, + (flow->packet.current_time_ms / 1000) & 0xFFFF /* 16 bit */); + } + } + } break; + } /* switch */ + + if(flow) { + switch(ndpi_get_proto_breed(ndpi_str, ret->app_protocol)) { + case NDPI_PROTOCOL_UNSAFE: + case NDPI_PROTOCOL_POTENTIALLY_DANGEROUS: + case NDPI_PROTOCOL_DANGEROUS: + NDPI_SET_BIT(flow->risk, NDPI_UNSAFE_PROTOCOL); + break; + default: + /* Nothing to do */ + break; + } } - } -} + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, const unsigned char *packet, - const unsigned short packetlen, const u_int64_t current_time_ms, - struct ndpi_id_struct *src, struct ndpi_id_struct *dst) { - NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_packet; - u_int32_t a, num_calls = 0; - ndpi_protocol ret = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED }; + ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, const unsigned char *packet, + const unsigned short packetlen, const u_int64_t current_time_ms, + struct ndpi_id_struct *src, struct ndpi_id_struct *dst) { + NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_packet; + u_int32_t a, num_calls = 0; + ndpi_protocol ret = { NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED }; - if(ndpi_str->ndpi_log_level >= NDPI_LOG_TRACE) - NDPI_LOG(flow ? flow->detected_protocol_stack[0] : NDPI_PROTOCOL_UNKNOWN, ndpi_str, NDPI_LOG_TRACE, - "START packet processing\n"); + if(ndpi_str->ndpi_log_level >= NDPI_LOG_TRACE) + NDPI_LOG(flow ? flow->detected_protocol_stack[0] : NDPI_PROTOCOL_UNKNOWN, ndpi_str, NDPI_LOG_TRACE, + "START packet processing\n"); - if(flow == NULL) - return(ret); - else - ret.category = flow->category; + if(flow == NULL) + return(ret); + else + ret.category = flow->category; - if(flow->fail_with_unknown) { - // printf("%s(): FAIL_WITH_UNKNOWN\n", __FUNCTION__); - return(ret); - } + if(flow->fail_with_unknown) { + // printf("%s(): FAIL_WITH_UNKNOWN\n", __FUNCTION__); + return(ret); + } - flow->num_processed_pkts++; + flow->num_processed_pkts++; #ifdef FRAG_MAN - flow->tcp_segments_management=1; + flow->tcp_segments_management=1; #endif // FRAG_MAN - /* Init default */ - ret.master_protocol = flow->detected_protocol_stack[1], - ret.app_protocol = flow->detected_protocol_stack[0]; + /* 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->server_id == NULL) + flow->server_id = dst; /* Default */ - if(flow->check_extra_packets) { - ndpi_process_extra_packet(ndpi_str, flow, packet, packetlen, current_time_ms, src, dst); - /* Update in case of new match */ - ret.master_protocol = flow->detected_protocol_stack[1], - ret.app_protocol = flow->detected_protocol_stack[0], - ret.category = flow->category; - goto invalidate_ptr; - } else if (flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) - goto ret_protocols; + if(flow->check_extra_packets) { + ndpi_process_extra_packet(ndpi_str, flow, packet, packetlen, current_time_ms, src, dst); + /* Update in case of new match */ + ret.master_protocol = flow->detected_protocol_stack[1], + ret.app_protocol = flow->detected_protocol_stack[0], + ret.category = flow->category; + goto invalidate_ptr; + } else 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); - goto invalidate_ptr; - } + /* 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); + goto invalidate_ptr; + } - flow->packet.current_time_ms = current_time_ms; + flow->packet.current_time_ms = current_time_ms; - /* parse packet */ - flow->packet.iph = (struct ndpi_iphdr *) packet; - /* we are interested in ipv4 packet */ + /* parse packet */ + flow->packet.iph = (struct ndpi_iphdr *) packet; + /* we are interested in ipv4 packet */ - if(ndpi_init_packet_header(ndpi_str, flow, packetlen) != 0) - goto invalidate_ptr; + if(ndpi_init_packet_header(ndpi_str, flow, packetlen) != 0) + goto invalidate_ptr; - /* detect traffic for tcp or udp only */ - flow->src = src, flow->dst = dst; + /* detect traffic for tcp or udp only */ + flow->src = src, flow->dst = dst; - ndpi_connection_tracking(ndpi_str, flow); + ndpi_connection_tracking(ndpi_str, flow); - /* build ndpi_selection packet bitmask */ - ndpi_selection_packet = NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC; - if(flow->packet.iph != NULL) - ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IP | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6; + /* build ndpi_selection packet bitmask */ + ndpi_selection_packet = NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC; + 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) - ndpi_selection_packet |= - (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP); + 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) - ndpi_selection_packet |= - (NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP); + 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) - ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD; + if(flow->packet.payload_packet_len != 0) + ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_HAS_PAYLOAD; - if(flow->packet.tcp_retransmission == 0) - ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_NO_TCP_RETRANSMISSION; + 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) - ndpi_selection_packet |= NDPI_SELECTION_BITMASK_PROTOCOL_IPV6 | NDPI_SELECTION_BITMASK_PROTOCOL_IPV4_OR_IPV6; + 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) && ( + if((!flow->protocol_id_already_guessed) && ( #ifdef NDPI_DETECTION_SUPPORT_IPV6 - flow->packet.iphv6 || + flow->packet.iphv6 || #endif - flow->packet.iph)) { - u_int16_t sport, dport; - u_int8_t protocol; - u_int8_t user_defined_proto; + flow->packet.iph)) { + u_int16_t sport, dport; + u_int8_t protocol; + u_int8_t user_defined_proto; - flow->protocol_id_already_guessed = 1; + flow->protocol_id_already_guessed = 1; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - if(flow->packet.iphv6 != NULL) { - protocol = flow->packet.iphv6->ip6_hdr.ip6_un1_nxt; - } else + if(flow->packet.iphv6 != NULL) { + protocol = flow->packet.iphv6->ip6_hdr.ip6_un1_nxt; + } else #endif - { - protocol = flow->packet.iph->protocol; - } - - if(flow->packet.udp) - sport = ntohs(flow->packet.udp->source), dport = ntohs(flow->packet.udp->dest); - else if(flow->packet.tcp) - sport = ntohs(flow->packet.tcp->source), dport = ntohs(flow->packet.tcp->dest); - else - sport = dport = 0; - - /* guess protocol */ - flow->guessed_protocol_id = - (int16_t) ndpi_guess_protocol_id(ndpi_str, flow, protocol, sport, dport, &user_defined_proto); - flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_str, flow); - - if(ndpi_str->custom_categories.categories_loaded && flow->packet.iph) { - ndpi_fill_ip_protocol_category(ndpi_str, flow->packet.iph->saddr, flow->packet.iph->daddr, &ret); - flow->guessed_header_category = ret.category; - } else - flow->guessed_header_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED; + { + protocol = flow->packet.iph->protocol; + } - if(flow->guessed_protocol_id >= NDPI_MAX_SUPPORTED_PROTOCOLS) { - /* This is a custom protocol and it has priority over everything else */ - ret.master_protocol = NDPI_PROTOCOL_UNKNOWN, - ret.app_protocol = flow->guessed_protocol_id ? flow->guessed_protocol_id : flow->guessed_host_protocol_id; - ndpi_fill_protocol_category(ndpi_str, flow, &ret); - goto invalidate_ptr; - } + if(flow->packet.udp) + sport = ntohs(flow->packet.udp->source), dport = ntohs(flow->packet.udp->dest); + else if(flow->packet.tcp) + sport = ntohs(flow->packet.tcp->source), dport = ntohs(flow->packet.tcp->dest); + else + sport = dport = 0; - if(user_defined_proto && flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) { - if(flow->packet.iph) { - if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) { - u_int8_t protocol_was_guessed; + /* guess protocol */ + flow->guessed_protocol_id = + (int16_t) ndpi_guess_protocol_id(ndpi_str, flow, protocol, sport, dport, &user_defined_proto); + flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_str, flow); - /* ret.master_protocol = flow->guessed_protocol_id , ret.app_protocol = flow->guessed_host_protocol_id; /\* ****** *\/ */ - ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed); - } + if(ndpi_str->custom_categories.categories_loaded && flow->packet.iph) { + ndpi_fill_ip_protocol_category(ndpi_str, flow->packet.iph->saddr, flow->packet.iph->daddr, &ret); + flow->guessed_header_category = ret.category; + } else + flow->guessed_header_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED; + if(flow->guessed_protocol_id >= NDPI_MAX_SUPPORTED_PROTOCOLS) { + /* This is a custom protocol and it has priority over everything else */ + ret.master_protocol = NDPI_PROTOCOL_UNKNOWN, + ret.app_protocol = flow->guessed_protocol_id ? flow->guessed_protocol_id : flow->guessed_host_protocol_id; ndpi_fill_protocol_category(ndpi_str, flow, &ret); goto invalidate_ptr; } - } else { - /* guess host protocol */ - if(flow->packet.iph) { - flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_str, flow); + if(user_defined_proto && flow->guessed_protocol_id != NDPI_PROTOCOL_UNKNOWN) { + if(flow->packet.iph) { + if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) { + u_int8_t protocol_was_guessed; - /* - We could implement a shortcut here skipping dissectors for - protocols we have identified by other means such as with the IP + /* ret.master_protocol = flow->guessed_protocol_id , ret.app_protocol = flow->guessed_host_protocol_id; /\* ****** *\/ */ + ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed); + } + + ndpi_fill_protocol_category(ndpi_str, flow, &ret); + goto invalidate_ptr; + } + } else { + /* guess host protocol */ + if(flow->packet.iph) { + + flow->guessed_host_protocol_id = ndpi_guess_host_protocol_id(ndpi_str, flow); - However we do NOT stop here and skip invoking the dissectors - because we want to dissect the flow (e.g. dissect the TLS) - and extract metadata. - */ -#if SKIP_INVOKING_THE_DISSECTORS - if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) { /* - We have identified a protocol using the IP address so - it is not worth to dissect the traffic as we already have - the solution + We could implement a shortcut here skipping dissectors for + protocols we have identified by other means such as with the IP + + However we do NOT stop here and skip invoking the dissectors + because we want to dissect the flow (e.g. dissect the TLS) + and extract metadata. */ - ret.master_protocol = flow->guessed_protocol_id, ret.app_protocol = flow->guessed_host_protocol_id; - } +#if SKIP_INVOKING_THE_DISSECTORS + if(flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) { + /* + We have identified a protocol using the IP address so + it is not worth to dissect the traffic as we already have + the solution + */ + ret.master_protocol = flow->guessed_protocol_id, ret.app_protocol = flow->guessed_host_protocol_id; + } #endif + } } } - } - if(flow->guessed_host_protocol_id >= NDPI_MAX_SUPPORTED_PROTOCOLS) { - /* This is a custom protocol and it has priority over everything else */ - ret.master_protocol = flow->guessed_protocol_id, ret.app_protocol = flow->guessed_host_protocol_id; + if(flow->guessed_host_protocol_id >= NDPI_MAX_SUPPORTED_PROTOCOLS) { + /* This is a custom protocol and it has priority over everything else */ + ret.master_protocol = flow->guessed_protocol_id, ret.app_protocol = flow->guessed_host_protocol_id; - num_calls = ndpi_check_flow_func(ndpi_str, flow, &ndpi_selection_packet); - ndpi_fill_protocol_category(ndpi_str, flow, &ret); - goto invalidate_ptr; - } + num_calls = ndpi_check_flow_func(ndpi_str, flow, &ndpi_selection_packet); + ndpi_fill_protocol_category(ndpi_str, flow, &ret); + goto invalidate_ptr; + } - num_calls = ndpi_check_flow_func(ndpi_str, flow, &ndpi_selection_packet); + num_calls = ndpi_check_flow_func(ndpi_str, flow, &ndpi_selection_packet); - a = flow->packet.detected_protocol_stack[0]; - if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_str->detection_bitmask, a) == 0) - a = NDPI_PROTOCOL_UNKNOWN; + a = flow->packet.detected_protocol_stack[0]; + if(NDPI_COMPARE_PROTOCOL_TO_BITMASK(ndpi_str->detection_bitmask, a) == 0) + a = NDPI_PROTOCOL_UNKNOWN; - if(a != NDPI_PROTOCOL_UNKNOWN) { - int i; + if(a != NDPI_PROTOCOL_UNKNOWN) { + int i; - for (i = 0; i < sizeof(flow->host_server_name); i++) { - if(flow->host_server_name[i] != '\0') - flow->host_server_name[i] = tolower(flow->host_server_name[i]); - else { - flow->host_server_name[i] = '\0'; - break; + for (i = 0; i < sizeof(flow->host_server_name); i++) { + if(flow->host_server_name[i] != '\0') + flow->host_server_name[i] = tolower(flow->host_server_name[i]); + else { + flow->host_server_name[i] = '\0'; + break; + } } } - } - ret_protocols: - if(flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN) { - ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; + ret_protocols: + if(flow->detected_protocol_stack[1] != NDPI_PROTOCOL_UNKNOWN) { + ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; - if(ret.app_protocol == ret.master_protocol) - ret.master_protocol = NDPI_PROTOCOL_UNKNOWN; - } else - ret.app_protocol = flow->detected_protocol_stack[0]; + if(ret.app_protocol == ret.master_protocol) + ret.master_protocol = NDPI_PROTOCOL_UNKNOWN; + } else + ret.app_protocol = flow->detected_protocol_stack[0]; - /* Don't overwrite the category if already set */ - if((flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN)) - ndpi_fill_protocol_category(ndpi_str, flow, &ret); - else - ret.category = flow->category; + /* Don't overwrite the category if already set */ + if((flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN)) + ndpi_fill_protocol_category(ndpi_str, 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) && flow->packet.tcp && (flow->packet.tcp->syn == 0) && - (flow->guessed_protocol_id == 0)) { - u_int8_t protocol_was_guessed; + if((flow->num_processed_pkts == 1) && (ret.master_protocol == NDPI_PROTOCOL_UNKNOWN) && + (ret.app_protocol == NDPI_PROTOCOL_UNKNOWN) && flow->packet.tcp && (flow->packet.tcp->syn == 0) && + (flow->guessed_protocol_id == 0)) { + u_int8_t protocol_was_guessed; - /* - This is a TCP flow - - whose first packet is NOT a SYN - - no protocol has been detected + /* + This is a TCP flow + - whose first packet is NOT a SYN + - no protocol has been detected - We don't see how future packets can match anything - hence we giveup here - */ - ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed); - } + We don't see how future packets can match anything + hence we giveup here + */ + ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed); + } - if((ret.master_protocol == NDPI_PROTOCOL_UNKNOWN) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN) && - (flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN)) { - ret.master_protocol = ret.app_protocol; - ret.app_protocol = flow->guessed_host_protocol_id; - } + if((ret.master_protocol == NDPI_PROTOCOL_UNKNOWN) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN) && + (flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN)) { + ret.master_protocol = ret.app_protocol; + ret.app_protocol = flow->guessed_host_protocol_id; + } - if((!flow->risk_checked) && (ret.master_protocol != NDPI_PROTOCOL_UNKNOWN)) { - ndpi_default_ports_tree_node_t *found; - u_int16_t *default_ports, sport, dport; + if((!flow->risk_checked) && (ret.master_protocol != NDPI_PROTOCOL_UNKNOWN)) { + ndpi_default_ports_tree_node_t *found; + u_int16_t *default_ports, sport, dport; + + if(flow->packet.udp) + found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_UDP, + sport = ntohs(flow->packet.udp->source), + dport = ntohs(flow->packet.udp->dest)), + default_ports = ndpi_str->proto_defaults[ret.master_protocol].udp_default_ports; + else if(flow->packet.tcp) + found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_TCP, + sport = ntohs(flow->packet.tcp->source), + dport = ntohs(flow->packet.tcp->dest)), + default_ports = ndpi_str->proto_defaults[ret.master_protocol].tcp_default_ports; + else + found = NULL, default_ports = NULL; + + if(found + && (found->proto->protoId != NDPI_PROTOCOL_UNKNOWN) + && (found->proto->protoId != ret.master_protocol) + && (found->proto->protoId != ret.app_protocol) + ) { + // printf("******** %u / %u\n", found->proto->protoId, ret.master_protocol); + + if(!ndpi_check_protocol_port_mismatch_exceptions(ndpi_str, flow, found, &ret)) + NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); + } else if((!ndpi_is_ntop_protocol(&ret)) && default_ports && (default_ports[0] != 0)) { + u_int8_t found = 0, i, num_loops = 0; + + check_default_ports: + for(i=0; (i<MAX_DEFAULT_PORTS) && (default_ports[i] != 0); i++) { + if((default_ports[i] == sport) || (default_ports[i] == dport)) { + found = 1; + break; + } + } /* for */ - if(flow->packet.udp) - found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_UDP, - sport = ntohs(flow->packet.udp->source), - dport = ntohs(flow->packet.udp->dest)), - default_ports = ndpi_str->proto_defaults[ret.master_protocol].udp_default_ports; - else if(flow->packet.tcp) - found = ndpi_get_guessed_protocol_id(ndpi_str, IPPROTO_TCP, - sport = ntohs(flow->packet.tcp->source), - dport = ntohs(flow->packet.tcp->dest)), - default_ports = ndpi_str->proto_defaults[ret.master_protocol].tcp_default_ports; - else - found = NULL, default_ports = NULL; - - if(found - && (found->proto->protoId != NDPI_PROTOCOL_UNKNOWN) - && (found->proto->protoId != ret.master_protocol) - && (found->proto->protoId != ret.app_protocol) - ) { - // printf("******** %u / %u\n", found->proto->protoId, ret.master_protocol); - - if(!ndpi_check_protocol_port_mismatch_exceptions(ndpi_str, flow, found, &ret)) - NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); - } else if((!ndpi_is_ntop_protocol(&ret)) && default_ports && (default_ports[0] != 0)) { - u_int8_t found = 0, i, num_loops = 0; - - check_default_ports: - for(i=0; (i<MAX_DEFAULT_PORTS) && (default_ports[i] != 0); i++) { - if((default_ports[i] == sport) || (default_ports[i] == dport)) { - found = 1; - break; - } - } /* for */ + if((num_loops == 0) && (!found)) { + if(flow->packet.udp) + default_ports = ndpi_str->proto_defaults[ret.app_protocol].udp_default_ports; + else + default_ports = ndpi_str->proto_defaults[ret.app_protocol].tcp_default_ports; - if((num_loops == 0) && (!found)) { - if(flow->packet.udp) - default_ports = ndpi_str->proto_defaults[ret.app_protocol].udp_default_ports; - else - default_ports = ndpi_str->proto_defaults[ret.app_protocol].tcp_default_ports; + num_loops = 1; + goto check_default_ports; + } - num_loops = 1; - goto check_default_ports; + if(!found) { + // printf("******** Invalid default port\n"); + NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); + } } - if(!found) { - // printf("******** Invalid default port\n"); - NDPI_SET_BIT(flow->risk, NDPI_KNOWN_PROTOCOL_ON_NON_STANDARD_PORT); - } + flow->risk_checked = 1; } - flow->risk_checked = 1; - } - - ndpi_reconcile_protocols(ndpi_str, flow, &ret); + ndpi_reconcile_protocols(ndpi_str, flow, &ret); - if(num_calls == 0) - flow->fail_with_unknown = 1; + if(num_calls == 0) + flow->fail_with_unknown = 1; - invalidate_ptr: + invalidate_ptr: #ifdef FRAG_MAN -if (flow->must_free[flow->packet.packet_direction] && - flow->packet.payload_packet_len>0 && flow->packet.payload) { - // if the payload is allocated for segments reassembling, it must be free - ndpi_free((void*)flow->packet.payload); - // flow->packet.payload=NULL; done after - flow->packet.payload_packet_len=0; - flow->must_free[flow->packet.packet_direction]=0; - } + if((flow->must_free[flow->packet.packet_direction] == 1) + && (flow->packet.payload_packet_len > 0) + && flow->packet.payload) { + // if the payload is allocated for segments reassembling, it must be freed + ndpi_free((void*)flow->packet.payload); + // flow->packet.payload=NULL; done after + flow->packet.payload_packet_len = 0; + flow->must_free[flow->packet.packet_direction] = 0; + } #endif // FRAG_MAN - /* - 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.payload = NULL; - ndpi_reset_packet_line_info(&flow->packet); - - 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) { - u_int32_t val; - val = 0; + /* + 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.payload = NULL; + ndpi_reset_packet_line_info(&flow->packet); - // cancel if eof, ' ' or line end chars are reached - while (*str >= '0' && *str <= '9' && max_chars_to_read > 0) { - val *= 10; - val += *str - '0'; - str++; - max_chars_to_read = max_chars_to_read - 1; - *bytes_read = *bytes_read + 1; + return(ret); } - return(val); -} + /* ********************************************************************************* */ -/* ********************************************************************************* */ + u_int32_t ndpi_bytestream_to_number(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) { + u_int32_t val; + val = 0; -#ifdef CODE_UNUSED -u_int32_t ndpi_bytestream_dec_or_hex_to_number(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) { - u_int32_t val; - val = 0; - if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') { - return(ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read)); - } else { - /*use base 16 system */ - str += 2; - max_chars_to_read -= 2; - *bytes_read = *bytes_read + 2; - - while (max_chars_to_read > 0) { - if(*str >= '0' && *str <= '9') { - val *= 16; - val += *str - '0'; - } else if(*str >= 'a' && *str <= 'f') { - val *= 16; - val += *str + 10 - 'a'; - } else if(*str >= 'A' && *str <= 'F') { - val *= 16; - val += *str + 10 - 'A'; - } else { - break; - } + // cancel if eof, ' ' or line end chars are reached + while (*str >= '0' && *str <= '9' && max_chars_to_read > 0) { + val *= 10; + val += *str - '0'; str++; max_chars_to_read = max_chars_to_read - 1; *bytes_read = *bytes_read + 1; } - } - return(val); -} + return(val); + } -#endif + /* ********************************************************************************* */ -/* ********************************************************************************* */ +#ifdef CODE_UNUSED + u_int32_t ndpi_bytestream_dec_or_hex_to_number(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) { + u_int32_t val; + val = 0; + if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') { + return(ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read)); + } else { + /*use base 16 system */ + str += 2; + max_chars_to_read -= 2; + *bytes_read = *bytes_read + 2; + + while (max_chars_to_read > 0) { + if(*str >= '0' && *str <= '9') { + val *= 16; + val += *str - '0'; + } else if(*str >= 'a' && *str <= 'f') { + val *= 16; + val += *str + 10 - 'a'; + } else if(*str >= 'A' && *str <= 'F') { + val *= 16; + val += *str + 10 - 'A'; + } else { + break; + } + str++; + max_chars_to_read = max_chars_to_read - 1; + *bytes_read = *bytes_read + 1; + } + } -u_int64_t ndpi_bytestream_to_number64(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) { - u_int64_t val; - val = 0; - // cancel if eof, ' ' or line end chars are reached - while (max_chars_to_read > 0 && *str >= '0' && *str <= '9') { - val *= 10; - val += *str - '0'; - str++; - max_chars_to_read = max_chars_to_read - 1; - *bytes_read = *bytes_read + 1; + return(val); } - return(val); -} -/* ********************************************************************************* */ +#endif -u_int64_t ndpi_bytestream_dec_or_hex_to_number64(const u_int8_t *str, u_int16_t max_chars_to_read, - u_int16_t *bytes_read) { - u_int64_t val; - val = 0; - if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') { - return(ndpi_bytestream_to_number64(str, max_chars_to_read, bytes_read)); - } else { - /*use base 16 system */ - str += 2; - max_chars_to_read -= 2; - *bytes_read = *bytes_read + 2; - while (max_chars_to_read > 0) { - if(*str >= '0' && *str <= '9') { - val *= 16; - val += *str - '0'; - } else if(*str >= 'a' && *str <= 'f') { - val *= 16; - val += *str + 10 - 'a'; - } else if(*str >= 'A' && *str <= 'F') { - val *= 16; - val += *str + 10 - 'A'; - } else { - break; - } + /* ********************************************************************************* */ + + u_int64_t ndpi_bytestream_to_number64(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) { + u_int64_t val; + val = 0; + // cancel if eof, ' ' or line end chars are reached + while (max_chars_to_read > 0 && *str >= '0' && *str <= '9') { + val *= 10; + val += *str - '0'; str++; max_chars_to_read = max_chars_to_read - 1; *bytes_read = *bytes_read + 1; } + return(val); } - return(val); -} -/* ********************************************************************************* */ + /* ********************************************************************************* */ -u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) { - u_int32_t val; - u_int16_t read = 0; - u_int16_t oldread; - u_int32_t c; + u_int64_t ndpi_bytestream_dec_or_hex_to_number64(const u_int8_t *str, u_int16_t max_chars_to_read, + u_int16_t *bytes_read) { + u_int64_t val; + val = 0; + if(max_chars_to_read <= 2 || str[0] != '0' || str[1] != 'x') { + return(ndpi_bytestream_to_number64(str, max_chars_to_read, bytes_read)); + } else { + /*use base 16 system */ + str += 2; + max_chars_to_read -= 2; + *bytes_read = *bytes_read + 2; + while (max_chars_to_read > 0) { + if(*str >= '0' && *str <= '9') { + val *= 16; + val += *str - '0'; + } else if(*str >= 'a' && *str <= 'f') { + val *= 16; + val += *str + 10 - 'a'; + } else if(*str >= 'A' && *str <= 'F') { + val *= 16; + val += *str + 10 - 'A'; + } else { + break; + } + str++; + max_chars_to_read = max_chars_to_read - 1; + *bytes_read = *bytes_read + 1; + } + } + return(val); + } - /* ip address must be X.X.X.X with each X between 0 and 255 */ - oldread = read; - c = ndpi_bytestream_to_number(str, max_chars_to_read, &read); - if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') - return(0); + /* ********************************************************************************* */ - read++; - val = c << 24; - oldread = read; - c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); - if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') - return(0); + u_int32_t ndpi_bytestream_to_ipv4(const u_int8_t *str, u_int16_t max_chars_to_read, u_int16_t *bytes_read) { + u_int32_t val; + u_int16_t read = 0; + u_int16_t oldread; + u_int32_t c; - read++; - val = val + (c << 16); - oldread = read; - c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); - if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') - return(0); + /* ip address must be X.X.X.X with each X between 0 and 255 */ + oldread = read; + c = ndpi_bytestream_to_number(str, max_chars_to_read, &read); + if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') + return(0); - read++; - val = val + (c << 8); - oldread = read; - c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); - if(c > 255 || oldread == read || max_chars_to_read == read) - return(0); + read++; + val = c << 24; + oldread = read; + c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); + if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') + return(0); - val = val + c; + read++; + val = val + (c << 16); + oldread = read; + c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); + if(c > 255 || oldread == read || max_chars_to_read == read || str[read] != '.') + return(0); - *bytes_read = *bytes_read + read; + read++; + val = val + (c << 8); + oldread = read; + c = ndpi_bytestream_to_number(&str[read], max_chars_to_read - read, &read); + if(c > 255 || oldread == read || max_chars_to_read == read) + return(0); - return(htonl(val)); -} + val = val + c; -/* ********************************************************************************* */ + *bytes_read = *bytes_read + read; -/* internal function for every detection to parse one packet and to increase the info buffer */ -void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { - u_int32_t a; - struct ndpi_packet_struct *packet = &flow->packet; + return(htonl(val)); + } - if((packet->payload_packet_len < 3) || (packet->payload == NULL)) - return; + /* ********************************************************************************* */ - if(packet->packet_lines_parsed_complete != 0) - return; + /* internal function for every detection to parse one packet and to increase the info buffer */ + void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { + u_int32_t a; + struct ndpi_packet_struct *packet = &flow->packet; - packet->packet_lines_parsed_complete = 1; - ndpi_reset_packet_line_info(packet); + if((packet->payload_packet_len < 3) || (packet->payload == NULL)) + return; - packet->line[packet->parsed_lines].ptr = packet->payload; - packet->line[packet->parsed_lines].len = 0; + if(packet->packet_lines_parsed_complete != 0) + return; - for (a = 0; ((a+1) < packet->payload_packet_len) && (packet->parsed_lines < NDPI_MAX_PARSE_LINES_PER_PACKET); a++) { - if((packet->payload[a] == 0x0d) && (packet->payload[a+1] == 0x0a)) { - /* If end of line char sequence CR+NL "\r\n", process line */ + packet->packet_lines_parsed_complete = 1; + ndpi_reset_packet_line_info(packet); - if(((a + 3) < packet->payload_packet_len) - && (packet->payload[a+2] == 0x0d) - && (packet->payload[a+3] == 0x0a)) { - /* \r\n\r\n */ - int diff; /* No unsigned ! */ - u_int32_t a1 = a + 4; + packet->line[packet->parsed_lines].ptr = packet->payload; + packet->line[packet->parsed_lines].len = 0; - diff = packet->payload_packet_len - a1; + for (a = 0; ((a+1) < packet->payload_packet_len) && (packet->parsed_lines < NDPI_MAX_PARSE_LINES_PER_PACKET); a++) { + if((packet->payload[a] == 0x0d) && (packet->payload[a+1] == 0x0a)) { + /* If end of line char sequence CR+NL "\r\n", process line */ - if(diff > 0) { - diff = ndpi_min(diff, sizeof(flow->initial_binary_bytes)); - memcpy(&flow->initial_binary_bytes, &packet->payload[a1], diff); - flow->initial_binary_bytes_len = diff; - } - } + if(((a + 3) < packet->payload_packet_len) + && (packet->payload[a+2] == 0x0d) + && (packet->payload[a+3] == 0x0a)) { + /* \r\n\r\n */ + int diff; /* No unsigned ! */ + u_int32_t a1 = a + 4; - packet->line[packet->parsed_lines].len = - (u_int16_t)(((size_t) &packet->payload[a]) - ((size_t) packet->line[packet->parsed_lines].ptr)); + diff = packet->payload_packet_len - a1; + + if(diff > 0) { + diff = ndpi_min(diff, sizeof(flow->initial_binary_bytes)); + memcpy(&flow->initial_binary_bytes, &packet->payload[a1], diff); + flow->initial_binary_bytes_len = diff; + } + } - /* First line of a HTTP response parsing. Expected a "HTTP/1.? ???" */ - if(packet->parsed_lines == 0 && packet->line[0].len >= NDPI_STATICSTRING_LEN("HTTP/1.X 200 ") && - strncasecmp((const char *) packet->line[0].ptr, "HTTP/1.", NDPI_STATICSTRING_LEN("HTTP/1.")) == 0 && - packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.X ")] > '0' && /* response code between 000 and 699 */ - packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.X ")] < '6') { - packet->http_response.ptr = &packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.1 ")]; - packet->http_response.len = packet->line[0].len - NDPI_STATICSTRING_LEN("HTTP/1.1 "); - packet->http_num_headers++; + packet->line[packet->parsed_lines].len = + (u_int16_t)(((size_t) &packet->payload[a]) - ((size_t) packet->line[packet->parsed_lines].ptr)); - /* Set server HTTP response code */ - if(packet->payload_packet_len >= 12) { - char buf[4]; + /* First line of a HTTP response parsing. Expected a "HTTP/1.? ???" */ + if(packet->parsed_lines == 0 && packet->line[0].len >= NDPI_STATICSTRING_LEN("HTTP/1.X 200 ") && + strncasecmp((const char *) packet->line[0].ptr, "HTTP/1.", NDPI_STATICSTRING_LEN("HTTP/1.")) == 0 && + packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.X ")] > '0' && /* response code between 000 and 699 */ + packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.X ")] < '6') { + packet->http_response.ptr = &packet->line[0].ptr[NDPI_STATICSTRING_LEN("HTTP/1.1 ")]; + packet->http_response.len = packet->line[0].len - NDPI_STATICSTRING_LEN("HTTP/1.1 "); + packet->http_num_headers++; /* Set server HTTP response code */ - strncpy(buf, (char *) &packet->payload[9], 3); - buf[3] = '\0'; + if(packet->payload_packet_len >= 12) { + char buf[4]; + + /* Set server HTTP response code */ + strncpy(buf, (char *) &packet->payload[9], 3); + buf[3] = '\0'; - flow->http.response_status_code = atoi(buf); - /* https://en.wikipedia.org/wiki/List_of_HTTP_status_codes */ - if((flow->http.response_status_code < 100) || (flow->http.response_status_code > 509)) - flow->http.response_status_code = 0; /* Out of range */ + flow->http.response_status_code = atoi(buf); + /* https://en.wikipedia.org/wiki/List_of_HTTP_status_codes */ + if((flow->http.response_status_code < 100) || (flow->http.response_status_code > 509)) + flow->http.response_status_code = 0; /* Out of range */ + } } - } - /* "Server:" header line in HTTP response */ - if(packet->line[packet->parsed_lines].len > NDPI_STATICSTRING_LEN("Server:") + 1 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, - "Server:", NDPI_STATICSTRING_LEN("Server:")) == 0) { - // some stupid clients omit a space and place the servername directly after the colon - if(packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")] == ' ') { - packet->server_line.ptr = - &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:") + 1]; - packet->server_line.len = - packet->line[packet->parsed_lines].len - (NDPI_STATICSTRING_LEN("Server:") + 1); - } else { - packet->server_line.ptr = &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")]; - packet->server_line.len = packet->line[packet->parsed_lines].len - NDPI_STATICSTRING_LEN("Server:"); + /* "Server:" header line in HTTP response */ + if(packet->line[packet->parsed_lines].len > NDPI_STATICSTRING_LEN("Server:") + 1 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, + "Server:", NDPI_STATICSTRING_LEN("Server:")) == 0) { + // some stupid clients omit a space and place the servername directly after the colon + if(packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")] == ' ') { + packet->server_line.ptr = + &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:") + 1]; + packet->server_line.len = + packet->line[packet->parsed_lines].len - (NDPI_STATICSTRING_LEN("Server:") + 1); + } else { + packet->server_line.ptr = &packet->line[packet->parsed_lines].ptr[NDPI_STATICSTRING_LEN("Server:")]; + packet->server_line.len = packet->line[packet->parsed_lines].len - NDPI_STATICSTRING_LEN("Server:"); + } + packet->http_num_headers++; } - packet->http_num_headers++; - } - /* "Host:" header line in HTTP request */ - if(packet->line[packet->parsed_lines].len > 6 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Host:", 5) == 0) { - // some stupid clients omit a space and place the hostname directly after the colon - if(packet->line[packet->parsed_lines].ptr[5] == ' ') { - packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[6]; - packet->host_line.len = packet->line[packet->parsed_lines].len - 6; - } else { - packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[5]; - packet->host_line.len = packet->line[packet->parsed_lines].len - 5; + /* "Host:" header line in HTTP request */ + if(packet->line[packet->parsed_lines].len > 6 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Host:", 5) == 0) { + // some stupid clients omit a space and place the hostname directly after the colon + if(packet->line[packet->parsed_lines].ptr[5] == ' ') { + packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[6]; + packet->host_line.len = packet->line[packet->parsed_lines].len - 6; + } else { + packet->host_line.ptr = &packet->line[packet->parsed_lines].ptr[5]; + packet->host_line.len = packet->line[packet->parsed_lines].len - 5; + } + packet->http_num_headers++; } - packet->http_num_headers++; - } - /* "X-Forwarded-For:" header line in HTTP request. Commonly used for HTTP proxies. */ - if(packet->line[packet->parsed_lines].len > 17 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Forwarded-For:", 16) == 0) { - // some stupid clients omit a space and place the hostname directly after the colon - if(packet->line[packet->parsed_lines].ptr[16] == ' ') { - packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[17]; - packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 17; - } else { - packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[16]; - packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 16; + /* "X-Forwarded-For:" header line in HTTP request. Commonly used for HTTP proxies. */ + if(packet->line[packet->parsed_lines].len > 17 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Forwarded-For:", 16) == 0) { + // some stupid clients omit a space and place the hostname directly after the colon + if(packet->line[packet->parsed_lines].ptr[16] == ' ') { + packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[17]; + packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 17; + } else { + packet->forwarded_line.ptr = &packet->line[packet->parsed_lines].ptr[16]; + packet->forwarded_line.len = packet->line[packet->parsed_lines].len - 16; + } + packet->http_num_headers++; } - packet->http_num_headers++; - } - /* "Content-Type:" header line in HTTP. */ - if(packet->line[packet->parsed_lines].len > 14 && - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Type: ", 14) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-type: ", 14) == 0)) { - packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[14]; - packet->content_line.len = packet->line[packet->parsed_lines].len - 14; + /* "Content-Type:" header line in HTTP. */ + if(packet->line[packet->parsed_lines].len > 14 && + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Type: ", 14) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-type: ", 14) == 0)) { + packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[14]; + packet->content_line.len = packet->line[packet->parsed_lines].len - 14; - while ((packet->content_line.len > 0) && (packet->content_line.ptr[0] == ' ')) - packet->content_line.len--, packet->content_line.ptr++; + while ((packet->content_line.len > 0) && (packet->content_line.ptr[0] == ' ')) + packet->content_line.len--, packet->content_line.ptr++; - packet->http_num_headers++; - } - /* "Content-Type:" header line in HTTP AGAIN. Probably a bogus response without space after ":" */ - if((packet->content_line.len == 0) && (packet->line[packet->parsed_lines].len > 13) && - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-type:", 13) == 0)) { - packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[13]; - packet->content_line.len = packet->line[packet->parsed_lines].len - 13; - packet->http_num_headers++; - } + packet->http_num_headers++; + } + /* "Content-Type:" header line in HTTP AGAIN. Probably a bogus response without space after ":" */ + if((packet->content_line.len == 0) && (packet->line[packet->parsed_lines].len > 13) && + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-type:", 13) == 0)) { + packet->content_line.ptr = &packet->line[packet->parsed_lines].ptr[13]; + packet->content_line.len = packet->line[packet->parsed_lines].len - 13; + packet->http_num_headers++; + } - if(packet->content_line.len > 0) { - /* application/json; charset=utf-8 */ - char separator[] = {';', '\r', '\0'}; - int i; + if(packet->content_line.len > 0) { + /* application/json; charset=utf-8 */ + char separator[] = {';', '\r', '\0'}; + int i; - for (i = 0; separator[i] != '\0'; i++) { - char *c = memchr((char *) packet->content_line.ptr, separator[i], packet->content_line.len); + for (i = 0; separator[i] != '\0'; i++) { + char *c = memchr((char *) packet->content_line.ptr, separator[i], packet->content_line.len); - if(c != NULL) - packet->content_line.len = c - (char *) packet->content_line.ptr; + if(c != NULL) + packet->content_line.len = c - (char *) packet->content_line.ptr; + } } - } - /* "Accept:" header line in HTTP request. */ - if(packet->line[packet->parsed_lines].len > 8 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept: ", 8) == 0) { - packet->accept_line.ptr = &packet->line[packet->parsed_lines].ptr[8]; - packet->accept_line.len = packet->line[packet->parsed_lines].len - 8; - packet->http_num_headers++; - } - /* "Referer:" header line in HTTP request. */ - if(packet->line[packet->parsed_lines].len > 9 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Referer: ", 9) == 0) { - packet->referer_line.ptr = &packet->line[packet->parsed_lines].ptr[9]; - packet->referer_line.len = packet->line[packet->parsed_lines].len - 9; - packet->http_num_headers++; - } - /* "User-Agent:" header line in HTTP request. */ - if(packet->line[packet->parsed_lines].len > 12 && - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "User-Agent: ", 12) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "User-agent: ", 12) == 0)) { - packet->user_agent_line.ptr = &packet->line[packet->parsed_lines].ptr[12]; - packet->user_agent_line.len = packet->line[packet->parsed_lines].len - 12; - packet->http_num_headers++; - } - /* "Content-Encoding:" header line in HTTP response (and request?). */ - if(packet->line[packet->parsed_lines].len > 18 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Encoding: ", 18) == 0) { - packet->http_encoding.ptr = &packet->line[packet->parsed_lines].ptr[18]; - packet->http_encoding.len = packet->line[packet->parsed_lines].len - 18; - packet->http_num_headers++; - } - /* "Transfer-Encoding:" header line in HTTP. */ - if(packet->line[packet->parsed_lines].len > 19 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Transfer-Encoding: ", 19) == 0) { - packet->http_transfer_encoding.ptr = &packet->line[packet->parsed_lines].ptr[19]; - packet->http_transfer_encoding.len = packet->line[packet->parsed_lines].len - 19; - packet->http_num_headers++; - } - /* "Content-Length:" header line in HTTP. */ - if(packet->line[packet->parsed_lines].len > 16 && - ((strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Length: ", 16) == 0) || - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "content-length: ", 16) == 0))) { - packet->http_contentlen.ptr = &packet->line[packet->parsed_lines].ptr[16]; - packet->http_contentlen.len = packet->line[packet->parsed_lines].len - 16; - packet->http_num_headers++; - } - /* "Content-Disposition"*/ - if(packet->line[packet->parsed_lines].len > 21 && - ((strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Disposition: ", 21) == 0))) { - packet->content_disposition_line.ptr = &packet->line[packet->parsed_lines].ptr[21]; - packet->content_disposition_line.len = packet->line[packet->parsed_lines].len - 21; - packet->http_num_headers++; - } - /* "Cookie:" header line in HTTP. */ - if(packet->line[packet->parsed_lines].len > 8 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Cookie: ", 8) == 0) { - packet->http_cookie.ptr = &packet->line[packet->parsed_lines].ptr[8]; - packet->http_cookie.len = packet->line[packet->parsed_lines].len - 8; - packet->http_num_headers++; - } - /* "Origin:" header line in HTTP. */ - if(packet->line[packet->parsed_lines].len > 8 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Origin: ", 8) == 0) { - packet->http_origin.ptr = &packet->line[packet->parsed_lines].ptr[8]; - packet->http_origin.len = packet->line[packet->parsed_lines].len - 8; - packet->http_num_headers++; - } - /* "X-Session-Type:" header line in HTTP. */ - if(packet->line[packet->parsed_lines].len > 16 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Session-Type: ", 16) == 0) { - packet->http_x_session_type.ptr = &packet->line[packet->parsed_lines].ptr[16]; - packet->http_x_session_type.len = packet->line[packet->parsed_lines].len - 16; - packet->http_num_headers++; - } - /* Identification and counting of other HTTP headers. - * We consider the most common headers, but there are many others, - * which can be seen at references below: - * - https://tools.ietf.org/html/rfc7230 - * - https://en.wikipedia.org/wiki/List_of_HTTP_header_fields - */ - if((packet->line[packet->parsed_lines].len > 6 && - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Date: ", 6) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Vary: ", 6) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "ETag: ", 6) == 0)) || - (packet->line[packet->parsed_lines].len > 8 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Pragma: ", 8) == 0) || - (packet->line[packet->parsed_lines].len > 9 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Expires: ", 9) == 0) || - (packet->line[packet->parsed_lines].len > 12 && - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Set-Cookie: ", 12) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Keep-Alive: ", 12) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Connection: ", 12) == 0)) || - (packet->line[packet->parsed_lines].len > 15 && - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Last-Modified: ", 15) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Ranges: ", 15) == 0)) || - (packet->line[packet->parsed_lines].len > 17 && - (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Language: ", 17) == 0 || - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Encoding: ", 17) == 0)) || - (packet->line[packet->parsed_lines].len > 27 && - strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, - "Upgrade-Insecure-Requests: ", 27) == 0)) { - /* Just count. In the future, if needed, this if can be splited to parse these headers */ - packet->http_num_headers++; - } + /* "Accept:" header line in HTTP request. */ + if(packet->line[packet->parsed_lines].len > 8 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept: ", 8) == 0) { + packet->accept_line.ptr = &packet->line[packet->parsed_lines].ptr[8]; + packet->accept_line.len = packet->line[packet->parsed_lines].len - 8; + packet->http_num_headers++; + } + /* "Referer:" header line in HTTP request. */ + if(packet->line[packet->parsed_lines].len > 9 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Referer: ", 9) == 0) { + packet->referer_line.ptr = &packet->line[packet->parsed_lines].ptr[9]; + packet->referer_line.len = packet->line[packet->parsed_lines].len - 9; + packet->http_num_headers++; + } + /* "User-Agent:" header line in HTTP request. */ + if(packet->line[packet->parsed_lines].len > 12 && + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "User-Agent: ", 12) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "User-agent: ", 12) == 0)) { + packet->user_agent_line.ptr = &packet->line[packet->parsed_lines].ptr[12]; + packet->user_agent_line.len = packet->line[packet->parsed_lines].len - 12; + packet->http_num_headers++; + } + /* "Content-Encoding:" header line in HTTP response (and request?). */ + if(packet->line[packet->parsed_lines].len > 18 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Encoding: ", 18) == 0) { + packet->http_encoding.ptr = &packet->line[packet->parsed_lines].ptr[18]; + packet->http_encoding.len = packet->line[packet->parsed_lines].len - 18; + packet->http_num_headers++; + } + /* "Transfer-Encoding:" header line in HTTP. */ + if(packet->line[packet->parsed_lines].len > 19 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Transfer-Encoding: ", 19) == 0) { + packet->http_transfer_encoding.ptr = &packet->line[packet->parsed_lines].ptr[19]; + packet->http_transfer_encoding.len = packet->line[packet->parsed_lines].len - 19; + packet->http_num_headers++; + } + /* "Content-Length:" header line in HTTP. */ + if(packet->line[packet->parsed_lines].len > 16 && + ((strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Length: ", 16) == 0) || + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "content-length: ", 16) == 0))) { + packet->http_contentlen.ptr = &packet->line[packet->parsed_lines].ptr[16]; + packet->http_contentlen.len = packet->line[packet->parsed_lines].len - 16; + packet->http_num_headers++; + } + /* "Content-Disposition"*/ + if(packet->line[packet->parsed_lines].len > 21 && + ((strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Content-Disposition: ", 21) == 0))) { + packet->content_disposition_line.ptr = &packet->line[packet->parsed_lines].ptr[21]; + packet->content_disposition_line.len = packet->line[packet->parsed_lines].len - 21; + packet->http_num_headers++; + } + /* "Cookie:" header line in HTTP. */ + if(packet->line[packet->parsed_lines].len > 8 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Cookie: ", 8) == 0) { + packet->http_cookie.ptr = &packet->line[packet->parsed_lines].ptr[8]; + packet->http_cookie.len = packet->line[packet->parsed_lines].len - 8; + packet->http_num_headers++; + } + /* "Origin:" header line in HTTP. */ + if(packet->line[packet->parsed_lines].len > 8 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Origin: ", 8) == 0) { + packet->http_origin.ptr = &packet->line[packet->parsed_lines].ptr[8]; + packet->http_origin.len = packet->line[packet->parsed_lines].len - 8; + packet->http_num_headers++; + } + /* "X-Session-Type:" header line in HTTP. */ + if(packet->line[packet->parsed_lines].len > 16 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "X-Session-Type: ", 16) == 0) { + packet->http_x_session_type.ptr = &packet->line[packet->parsed_lines].ptr[16]; + packet->http_x_session_type.len = packet->line[packet->parsed_lines].len - 16; + packet->http_num_headers++; + } + /* Identification and counting of other HTTP headers. + * We consider the most common headers, but there are many others, + * which can be seen at references below: + * - https://tools.ietf.org/html/rfc7230 + * - https://en.wikipedia.org/wiki/List_of_HTTP_header_fields + */ + if((packet->line[packet->parsed_lines].len > 6 && + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Date: ", 6) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Vary: ", 6) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "ETag: ", 6) == 0)) || + (packet->line[packet->parsed_lines].len > 8 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Pragma: ", 8) == 0) || + (packet->line[packet->parsed_lines].len > 9 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Expires: ", 9) == 0) || + (packet->line[packet->parsed_lines].len > 12 && + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Set-Cookie: ", 12) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Keep-Alive: ", 12) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Connection: ", 12) == 0)) || + (packet->line[packet->parsed_lines].len > 15 && + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Last-Modified: ", 15) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Ranges: ", 15) == 0)) || + (packet->line[packet->parsed_lines].len > 17 && + (strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Language: ", 17) == 0 || + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, "Accept-Encoding: ", 17) == 0)) || + (packet->line[packet->parsed_lines].len > 27 && + strncasecmp((const char *) packet->line[packet->parsed_lines].ptr, + "Upgrade-Insecure-Requests: ", 27) == 0)) { + /* Just count. In the future, if needed, this if can be splited to parse these headers */ + packet->http_num_headers++; + } - if(packet->line[packet->parsed_lines].len == 0) { - packet->empty_line_position = a; - packet->empty_line_position_set = 1; - } + if(packet->line[packet->parsed_lines].len == 0) { + packet->empty_line_position = a; + packet->empty_line_position_set = 1; + } - if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1)) - return; + if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1)) + return; - packet->parsed_lines++; - packet->line[packet->parsed_lines].ptr = &packet->payload[a + 2]; - packet->line[packet->parsed_lines].len = 0; + packet->parsed_lines++; + packet->line[packet->parsed_lines].ptr = &packet->payload[a + 2]; + packet->line[packet->parsed_lines].len = 0; - a++; /* next char in the payload */ + a++; /* next char in the payload */ + } } - } - if(packet->parsed_lines >= 1) { - packet->line[packet->parsed_lines].len = - (u_int16_t)(((size_t) &packet->payload[packet->payload_packet_len]) - - ((size_t) packet->line[packet->parsed_lines].ptr)); - packet->parsed_lines++; + if(packet->parsed_lines >= 1) { + packet->line[packet->parsed_lines].len = + (u_int16_t)(((size_t) &packet->payload[packet->payload_packet_len]) - + ((size_t) packet->line[packet->parsed_lines].ptr)); + packet->parsed_lines++; + } } -} -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { - struct ndpi_packet_struct *packet = &flow->packet; - u_int32_t a; - u_int16_t end = packet->payload_packet_len; + void ndpi_parse_packet_line_info_any(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { + struct ndpi_packet_struct *packet = &flow->packet; + u_int32_t a; + u_int16_t end = packet->payload_packet_len; - if(packet->packet_lines_parsed_complete != 0) - return; + if(packet->packet_lines_parsed_complete != 0) + return; - packet->packet_lines_parsed_complete = 1; - packet->parsed_lines = 0; + packet->packet_lines_parsed_complete = 1; + packet->parsed_lines = 0; - if(packet->payload_packet_len == 0) - return; + if(packet->payload_packet_len == 0) + return; - packet->line[packet->parsed_lines].ptr = packet->payload; - packet->line[packet->parsed_lines].len = 0; + packet->line[packet->parsed_lines].ptr = packet->payload; + packet->line[packet->parsed_lines].len = 0; - for (a = 0; a < end; a++) { - if(packet->payload[a] == 0x0a) { - packet->line[packet->parsed_lines].len = (u_int16_t)( - ((size_t) &packet->payload[a]) - ((size_t) packet->line[packet->parsed_lines].ptr)); + for (a = 0; a < end; a++) { + if(packet->payload[a] == 0x0a) { + packet->line[packet->parsed_lines].len = (u_int16_t)( + ((size_t) &packet->payload[a]) - ((size_t) packet->line[packet->parsed_lines].ptr)); - if(a > 0 && packet->payload[a - 1] == 0x0d) - packet->line[packet->parsed_lines].len--; + if(a > 0 && packet->payload[a - 1] == 0x0d) + packet->line[packet->parsed_lines].len--; - if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1)) - break; + if(packet->parsed_lines >= (NDPI_MAX_PARSE_LINES_PER_PACKET - 1)) + break; - packet->parsed_lines++; - packet->line[packet->parsed_lines].ptr = &packet->payload[a + 1]; - packet->line[packet->parsed_lines].len = 0; + packet->parsed_lines++; + packet->line[packet->parsed_lines].ptr = &packet->payload[a + 1]; + packet->line[packet->parsed_lines].len = 0; - if((a + 1) >= packet->payload_packet_len) - break; + if((a + 1) >= packet->payload_packet_len) + break; - //a++; + //a++; + } } } -} -/* ********************************************************************************* */ + /* ********************************************************************************* */ -u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - u_int16_t counter) { - struct ndpi_packet_struct *packet = &flow->packet; + u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + u_int16_t counter) { + struct ndpi_packet_struct *packet = &flow->packet; + + NDPI_LOG_DBG2(ndpi_str, "called ndpi_check_for_email_address\n"); - NDPI_LOG_DBG2(ndpi_str, "called ndpi_check_for_email_address\n"); - - if(packet->payload_packet_len > counter && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') || - (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') || - (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') || - packet->payload[counter] == '-' || packet->payload[counter] == '_')) { - NDPI_LOG_DBG2(ndpi_str, "first letter\n"); - counter++; - while (packet->payload_packet_len > counter && - ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') || - (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') || - (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') || - packet->payload[counter] == '-' || packet->payload[counter] == '_' || - packet->payload[counter] == '.')) { - NDPI_LOG_DBG2(ndpi_str, "further letter\n"); + if(packet->payload_packet_len > counter && ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') || + (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') || + (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') || + packet->payload[counter] == '-' || packet->payload[counter] == '_')) { + NDPI_LOG_DBG2(ndpi_str, "first letter\n"); counter++; - if(packet->payload_packet_len > counter && packet->payload[counter] == '@') { - NDPI_LOG_DBG2(ndpi_str, "@\n"); + while (packet->payload_packet_len > counter && + ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') || + (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') || + (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') || + packet->payload[counter] == '-' || packet->payload[counter] == '_' || + packet->payload[counter] == '.')) { + NDPI_LOG_DBG2(ndpi_str, "further letter\n"); counter++; - while (packet->payload_packet_len > counter && - ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') || - (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') || - (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') || - packet->payload[counter] == '-' || packet->payload[counter] == '_')) { - NDPI_LOG_DBG2(ndpi_str, "letter\n"); + if(packet->payload_packet_len > counter && packet->payload[counter] == '@') { + NDPI_LOG_DBG2(ndpi_str, "@\n"); counter++; - if(packet->payload_packet_len > counter && packet->payload[counter] == '.') { - NDPI_LOG_DBG2(ndpi_str, ".\n"); + while (packet->payload_packet_len > counter && + ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') || + (packet->payload[counter] >= 'A' && packet->payload[counter] <= 'Z') || + (packet->payload[counter] >= '0' && packet->payload[counter] <= '9') || + packet->payload[counter] == '-' || packet->payload[counter] == '_')) { + NDPI_LOG_DBG2(ndpi_str, "letter\n"); counter++; - if(packet->payload_packet_len > counter + 1 && - ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') && - (packet->payload[counter + 1] >= 'a' && packet->payload[counter + 1] <= 'z'))) { - NDPI_LOG_DBG2(ndpi_str, "two letters\n"); - counter += 2; - if(packet->payload_packet_len > counter && - (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) { - NDPI_LOG_DBG2(ndpi_str, "whitespace1\n"); - return(counter); - } else if(packet->payload_packet_len > counter && packet->payload[counter] >= 'a' && - packet->payload[counter] <= 'z') { - NDPI_LOG_DBG2(ndpi_str, "one letter\n"); - counter++; + if(packet->payload_packet_len > counter && packet->payload[counter] == '.') { + NDPI_LOG_DBG2(ndpi_str, ".\n"); + counter++; + if(packet->payload_packet_len > counter + 1 && + ((packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') && + (packet->payload[counter + 1] >= 'a' && packet->payload[counter + 1] <= 'z'))) { + NDPI_LOG_DBG2(ndpi_str, "two letters\n"); + counter += 2; if(packet->payload_packet_len > counter && (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) { - NDPI_LOG_DBG2(ndpi_str, "whitespace2\n"); + NDPI_LOG_DBG2(ndpi_str, "whitespace1\n"); return(counter); } else if(packet->payload_packet_len > counter && packet->payload[counter] >= 'a' && packet->payload[counter] <= 'z') { + NDPI_LOG_DBG2(ndpi_str, "one letter\n"); counter++; if(packet->payload_packet_len > counter && (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) { - NDPI_LOG_DBG2(ndpi_str, "whitespace3\n"); + NDPI_LOG_DBG2(ndpi_str, "whitespace2\n"); return(counter); + } else if(packet->payload_packet_len > counter && packet->payload[counter] >= 'a' && + packet->payload[counter] <= 'z') { + counter++; + if(packet->payload_packet_len > counter && + (packet->payload[counter] == ' ' || packet->payload[counter] == ';')) { + NDPI_LOG_DBG2(ndpi_str, "whitespace3\n"); + return(counter); + } else { + return(0); + } } else { return(0); } @@ -5542,1544 +5546,1541 @@ u_int16_t ndpi_check_for_email_address(struct ndpi_detection_module_struct *ndpi } else { return(0); } - } else { - return(0); } } + return(0); } - return(0); } } + return(0); } - return(0); -} #ifdef NDPI_ENABLE_DEBUG_MESSAGES -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct *ndpi_str, const char **file, - const char **func, u_int32_t *line) { - *file = ""; - *func = ""; + void ndpi_debug_get_last_log_function_line(struct ndpi_detection_module_struct *ndpi_str, const char **file, + const char **func, u_int32_t *line) { + *file = ""; + *func = ""; - if(ndpi_str->ndpi_debug_print_file != NULL) - *file = ndpi_str->ndpi_debug_print_file; + if(ndpi_str->ndpi_debug_print_file != NULL) + *file = ndpi_str->ndpi_debug_print_file; - if(ndpi_str->ndpi_debug_print_function != NULL) - *func = ndpi_str->ndpi_debug_print_function; + if(ndpi_str->ndpi_debug_print_function != NULL) + *func = ndpi_str->ndpi_debug_print_function; - *line = ndpi_str->ndpi_debug_print_line; -} + *line = ndpi_str->ndpi_debug_print_line; + } #endif -/* ********************************************************************************* */ + /* ********************************************************************************* */ -u_int8_t ndpi_detection_get_l4(const u_int8_t *l3, u_int16_t l3_len, const u_int8_t **l4_return, - u_int16_t *l4_len_return, u_int8_t *l4_protocol_return, u_int32_t flags) { - return(ndpi_detection_get_l4_internal(NULL, l3, l3_len, l4_return, l4_len_return, l4_protocol_return, flags)); -} + u_int8_t ndpi_detection_get_l4(const u_int8_t *l3, u_int16_t l3_len, const u_int8_t **l4_return, + u_int16_t *l4_len_return, u_int8_t *l4_protocol_return, u_int32_t flags) { + return(ndpi_detection_get_l4_internal(NULL, l3, l3_len, l4_return, l4_len_return, l4_protocol_return, flags)); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_set_detected_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { - struct ndpi_id_struct *src = flow->src, *dst = flow->dst; + void ndpi_set_detected_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { + struct ndpi_id_struct *src = flow->src, *dst = flow->dst; - ndpi_int_change_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol); + ndpi_int_change_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol); - if(src != NULL) { - NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, upper_detected_protocol); + if(src != NULL) { + NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, upper_detected_protocol); - if(lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN) - NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, lower_detected_protocol); - } + if(lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN) + NDPI_ADD_PROTOCOL_TO_BITMASK(src->detected_protocol_bitmask, lower_detected_protocol); + } - if(dst != NULL) { - NDPI_ADD_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, upper_detected_protocol); + if(dst != NULL) { + NDPI_ADD_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, upper_detected_protocol); - if(lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN) - NDPI_ADD_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, lower_detected_protocol); + if(lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN) + NDPI_ADD_PROTOCOL_TO_BITMASK(dst->detected_protocol_bitmask, lower_detected_protocol); + } } -} -/* ********************************************************************************* */ + /* ********************************************************************************* */ -u_int16_t ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { - return(flow->detected_protocol_stack[1]); -} + u_int16_t ndpi_get_flow_masterprotocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow) { + return(flow->detected_protocol_stack[1]); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_int_change_flow_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { - if(!flow) - return; + void ndpi_int_change_flow_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + 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; -} + 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_str, struct ndpi_flow_struct *flow, - 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 - * except flow->packet If you want to change something here, - * don't! Change it for the flow function and apply it here - * as well */ + void ndpi_int_change_packet_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + 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 + * except flow->packet If you want to change something here, + * don't! Change it for the flow function and apply it here + * as well */ - if(!packet) - return; + if(!packet) + return; - packet->detected_protocol_stack[0] = upper_detected_protocol, - packet->detected_protocol_stack[1] = lower_detected_protocol; -} + packet->detected_protocol_stack[0] = upper_detected_protocol, + packet->detected_protocol_stack[1] = lower_detected_protocol; + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -/* generic function for changing the protocol - * - * what it does is: - * 1.update the flow protocol stack with the new protocol - * 2.update the packet protocol stack with the new protocol - */ -void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { - if((upper_detected_protocol == NDPI_PROTOCOL_UNKNOWN) && (lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN)) - upper_detected_protocol = lower_detected_protocol; - - if(upper_detected_protocol == lower_detected_protocol) - lower_detected_protocol = NDPI_PROTOCOL_UNKNOWN; - - if((upper_detected_protocol != NDPI_PROTOCOL_UNKNOWN) && (lower_detected_protocol == NDPI_PROTOCOL_UNKNOWN)) { - if((flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) && - (upper_detected_protocol != flow->guessed_host_protocol_id)) { - if(ndpi_str->proto_defaults[upper_detected_protocol].can_have_a_subprotocol) { - lower_detected_protocol = upper_detected_protocol; - upper_detected_protocol = flow->guessed_host_protocol_id; + /* generic function for changing the protocol + * + * what it does is: + * 1.update the flow protocol stack with the new protocol + * 2.update the packet protocol stack with the new protocol + */ + void ndpi_int_change_protocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + u_int16_t upper_detected_protocol, u_int16_t lower_detected_protocol) { + if((upper_detected_protocol == NDPI_PROTOCOL_UNKNOWN) && (lower_detected_protocol != NDPI_PROTOCOL_UNKNOWN)) + upper_detected_protocol = lower_detected_protocol; + + if(upper_detected_protocol == lower_detected_protocol) + lower_detected_protocol = NDPI_PROTOCOL_UNKNOWN; + + if((upper_detected_protocol != NDPI_PROTOCOL_UNKNOWN) && (lower_detected_protocol == NDPI_PROTOCOL_UNKNOWN)) { + if((flow->guessed_host_protocol_id != NDPI_PROTOCOL_UNKNOWN) && + (upper_detected_protocol != flow->guessed_host_protocol_id)) { + if(ndpi_str->proto_defaults[upper_detected_protocol].can_have_a_subprotocol) { + lower_detected_protocol = upper_detected_protocol; + upper_detected_protocol = flow->guessed_host_protocol_id; + } } } - } - ndpi_int_change_flow_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol); - ndpi_int_change_packet_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol); -} + ndpi_int_change_flow_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol); + ndpi_int_change_packet_protocol(ndpi_str, flow, upper_detected_protocol, lower_detected_protocol); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_int_change_category(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - ndpi_protocol_category_t protocol_category) { - flow->category = protocol_category; -} + void ndpi_int_change_category(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + ndpi_protocol_category_t protocol_category) { + flow->category = protocol_category; + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -/* turns a packet back to unknown */ -void ndpi_int_reset_packet_protocol(struct ndpi_packet_struct *packet) { - int a; + /* 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_SIZE; a++) - packet->detected_protocol_stack[a] = NDPI_PROTOCOL_UNKNOWN; -} + for (a = 0; a < NDPI_PROTOCOL_SIZE; a++) + packet->detected_protocol_stack[a] = NDPI_PROTOCOL_UNKNOWN; + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -void ndpi_int_reset_protocol(struct ndpi_flow_struct *flow) { - if(flow) { - int a; + void ndpi_int_reset_protocol(struct ndpi_flow_struct *flow) { + if(flow) { + int a; - for (a = 0; a < NDPI_PROTOCOL_SIZE; a++) - flow->detected_protocol_stack[a] = NDPI_PROTOCOL_UNKNOWN; + for (a = 0; a < NDPI_PROTOCOL_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)); -} + void NDPI_PROTOCOL_IP_clear(ndpi_ip_addr_t *ip) { + memset(ip, 0, sizeof(ndpi_ip_addr_t)); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ #ifdef CODE_UNUSED -/* NTOP */ -int NDPI_PROTOCOL_IP_is_set(const ndpi_ip_addr_t *ip) { - return(memcmp(ip, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(ndpi_ip_addr_t)) != 0); -} + /* NTOP */ + int NDPI_PROTOCOL_IP_is_set(const ndpi_ip_addr_t *ip) { + return(memcmp(ip, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(ndpi_ip_addr_t)) != 0); + } #endif -/* ********************************************************************************* */ + /* ********************************************************************************* */ -/* check if the source ip address in packet and ip are equal */ -/* NTOP */ -int ndpi_packet_src_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t *ip) { + /* check if the source ip address in packet and ip are equal */ + /* NTOP */ + int ndpi_packet_src_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t *ip) { #ifdef NDPI_DETECTION_SUPPORT_IPV6 - /* IPv6 */ - if(packet->iphv6 != NULL) { - if(packet->iphv6->ip6_src.u6_addr.u6_addr32[0] == ip->ipv6.u6_addr.u6_addr32[0] && - packet->iphv6->ip6_src.u6_addr.u6_addr32[1] == ip->ipv6.u6_addr.u6_addr32[1] && - packet->iphv6->ip6_src.u6_addr.u6_addr32[2] == ip->ipv6.u6_addr.u6_addr32[2] && - packet->iphv6->ip6_src.u6_addr.u6_addr32[3] == ip->ipv6.u6_addr.u6_addr32[3]) + /* IPv6 */ + if(packet->iphv6 != NULL) { + if(packet->iphv6->ip6_src.u6_addr.u6_addr32[0] == ip->ipv6.u6_addr.u6_addr32[0] && + packet->iphv6->ip6_src.u6_addr.u6_addr32[1] == ip->ipv6.u6_addr.u6_addr32[1] && + packet->iphv6->ip6_src.u6_addr.u6_addr32[2] == ip->ipv6.u6_addr.u6_addr32[2] && + packet->iphv6->ip6_src.u6_addr.u6_addr32[3] == ip->ipv6.u6_addr.u6_addr32[3]) + return(1); + //else + return(0); + } +#endif + + /* IPv4 */ + if(packet->iph->saddr == ip->ipv4) return(1); - //else return(0); } -#endif - - /* IPv4 */ - if(packet->iph->saddr == ip->ipv4) - return(1); - return(0); -} -/* ********************************************************************************* */ + /* ********************************************************************************* */ -/* check if the destination ip address in packet and ip are equal */ -int ndpi_packet_dst_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t *ip) { + /* check if the destination ip address in packet and ip are equal */ + int ndpi_packet_dst_ip_eql(const struct ndpi_packet_struct *packet, const ndpi_ip_addr_t *ip) { #ifdef NDPI_DETECTION_SUPPORT_IPV6 - /* IPv6 */ - if(packet->iphv6 != NULL) { - if(packet->iphv6->ip6_dst.u6_addr.u6_addr32[0] == ip->ipv6.u6_addr.u6_addr32[0] && - packet->iphv6->ip6_dst.u6_addr.u6_addr32[1] == ip->ipv6.u6_addr.u6_addr32[1] && - packet->iphv6->ip6_dst.u6_addr.u6_addr32[2] == ip->ipv6.u6_addr.u6_addr32[2] && - packet->iphv6->ip6_dst.u6_addr.u6_addr32[3] == ip->ipv6.u6_addr.u6_addr32[3]) - return(1); - //else - return(0); - } + /* IPv6 */ + if(packet->iphv6 != NULL) { + if(packet->iphv6->ip6_dst.u6_addr.u6_addr32[0] == ip->ipv6.u6_addr.u6_addr32[0] && + packet->iphv6->ip6_dst.u6_addr.u6_addr32[1] == ip->ipv6.u6_addr.u6_addr32[1] && + packet->iphv6->ip6_dst.u6_addr.u6_addr32[2] == ip->ipv6.u6_addr.u6_addr32[2] && + packet->iphv6->ip6_dst.u6_addr.u6_addr32[3] == ip->ipv6.u6_addr.u6_addr32[3]) + return(1); + //else + return(0); + } #endif - /* IPv4 */ - if(packet->iph->saddr == ip->ipv4) - return(1); + /* IPv4 */ + if(packet->iph->saddr == ip->ipv4) + return(1); - return(0); -} + return(0); + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -/* get the source ip address from packet and put it into ip */ -/* NTOP */ -void ndpi_packet_src_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t *ip) { - NDPI_PROTOCOL_IP_clear(ip); + /* get the source ip address from packet and put it into ip */ + /* NTOP */ + void ndpi_packet_src_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t *ip) { + NDPI_PROTOCOL_IP_clear(ip); #ifdef NDPI_DETECTION_SUPPORT_IPV6 - /* IPv6 */ - if(packet->iphv6 != NULL) { - ip->ipv6.u6_addr.u6_addr32[0] = packet->iphv6->ip6_src.u6_addr.u6_addr32[0]; - ip->ipv6.u6_addr.u6_addr32[1] = packet->iphv6->ip6_src.u6_addr.u6_addr32[1]; - ip->ipv6.u6_addr.u6_addr32[2] = packet->iphv6->ip6_src.u6_addr.u6_addr32[2]; - ip->ipv6.u6_addr.u6_addr32[3] = packet->iphv6->ip6_src.u6_addr.u6_addr32[3]; + /* IPv6 */ + if(packet->iphv6 != NULL) { + ip->ipv6.u6_addr.u6_addr32[0] = packet->iphv6->ip6_src.u6_addr.u6_addr32[0]; + ip->ipv6.u6_addr.u6_addr32[1] = packet->iphv6->ip6_src.u6_addr.u6_addr32[1]; + ip->ipv6.u6_addr.u6_addr32[2] = packet->iphv6->ip6_src.u6_addr.u6_addr32[2]; + ip->ipv6.u6_addr.u6_addr32[3] = packet->iphv6->ip6_src.u6_addr.u6_addr32[3]; - } else + } else #endif - /* IPv4 */ - ip->ipv4 = packet->iph->saddr; -} + /* IPv4 */ + ip->ipv4 = packet->iph->saddr; + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -/* get the destination ip address from packet and put it into ip */ -/* NTOP */ -void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t *ip) { - NDPI_PROTOCOL_IP_clear(ip); + /* get the destination ip address from packet and put it into ip */ + /* NTOP */ + void ndpi_packet_dst_ip_get(const struct ndpi_packet_struct *packet, ndpi_ip_addr_t *ip) { + NDPI_PROTOCOL_IP_clear(ip); #ifdef NDPI_DETECTION_SUPPORT_IPV6 - if(packet->iphv6 != NULL) { - ip->ipv6.u6_addr.u6_addr32[0] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[0]; - ip->ipv6.u6_addr.u6_addr32[1] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[1]; - ip->ipv6.u6_addr.u6_addr32[2] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[2]; - ip->ipv6.u6_addr.u6_addr32[3] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[3]; + if(packet->iphv6 != NULL) { + ip->ipv6.u6_addr.u6_addr32[0] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[0]; + ip->ipv6.u6_addr.u6_addr32[1] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[1]; + ip->ipv6.u6_addr.u6_addr32[2] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[2]; + ip->ipv6.u6_addr.u6_addr32[3] = packet->iphv6->ip6_dst.u6_addr.u6_addr32[3]; - } else + } else #endif - ip->ipv4 = packet->iph->daddr; -} + ip->ipv4 = packet->iph->daddr; + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -u_int8_t ndpi_is_ipv6(const ndpi_ip_addr_t *ip) { + u_int8_t ndpi_is_ipv6(const ndpi_ip_addr_t *ip) { #ifdef NDPI_DETECTION_SUPPORT_IPV6 - return(ip->ipv6.u6_addr.u6_addr32[1] != 0 || ip->ipv6.u6_addr.u6_addr32[2] != 0 || - ip->ipv6.u6_addr.u6_addr32[3] != 0); + return(ip->ipv6.u6_addr.u6_addr32[1] != 0 || ip->ipv6.u6_addr.u6_addr32[2] != 0 || + ip->ipv6.u6_addr.u6_addr32[3] != 0); #else - return(0); + return(0); #endif -} + } -/* ********************************************************************************* */ + /* ********************************************************************************* */ -char *ndpi_get_ip_string(const ndpi_ip_addr_t *ip, char *buf, u_int buf_len) { - const u_int8_t *a = (const u_int8_t *) &ip->ipv4; + char *ndpi_get_ip_string(const ndpi_ip_addr_t *ip, char *buf, u_int buf_len) { + const u_int8_t *a = (const u_int8_t *) &ip->ipv4; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - if(ndpi_is_ipv6(ip)) { - if(inet_ntop(AF_INET6, &ip->ipv6.u6_addr, buf, buf_len) == NULL) - buf[0] = '\0'; + if(ndpi_is_ipv6(ip)) { + if(inet_ntop(AF_INET6, &ip->ipv6.u6_addr, buf, buf_len) == NULL) + buf[0] = '\0'; - return(buf); - } + return(buf); + } #endif - snprintf(buf, buf_len, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); + snprintf(buf, buf_len, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); - return(buf); -} + return(buf); + } -/* ****************************************************** */ + /* ****************************************************** */ -/* Returns -1 on failutre, otherwise fills parsed_ip and returns the IP version */ -int ndpi_parse_ip_string(const char *ip_str, ndpi_ip_addr_t *parsed_ip) { - int rv = -1; - memset(parsed_ip, 0, sizeof(*parsed_ip)); + /* Returns -1 on failutre, otherwise fills parsed_ip and returns the IP version */ + int ndpi_parse_ip_string(const char *ip_str, ndpi_ip_addr_t *parsed_ip) { + int rv = -1; + memset(parsed_ip, 0, sizeof(*parsed_ip)); - if(strchr(ip_str, '.')) { - if(inet_pton(AF_INET, ip_str, &parsed_ip->ipv4) > 0) - rv = 4; + if(strchr(ip_str, '.')) { + if(inet_pton(AF_INET, ip_str, &parsed_ip->ipv4) > 0) + rv = 4; #ifdef NDPI_DETECTION_SUPPORT_IPV6 - } else { - if(inet_pton(AF_INET6, ip_str, &parsed_ip->ipv6) > 0) - rv = 6; + } else { + if(inet_pton(AF_INET6, ip_str, &parsed_ip->ipv6) > 0) + rv = 6; #endif - } - - return(rv); -} - -/* ****************************************************** */ + } -u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t *str, - u_int16_t max_chars_to_read, u_int16_t *bytes_read) { - u_int16_t val = ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read); - return(ntohs(val)); -} + return(rv); + } -/* ****************************************************** */ + /* ****************************************************** */ -u_int8_t ndpi_is_proto(ndpi_protocol proto, u_int16_t p) { - return(((proto.app_protocol == p) || (proto.master_protocol == p)) ? 1 : 0); -} + u_int16_t ntohs_ndpi_bytestream_to_number(const u_int8_t *str, + u_int16_t max_chars_to_read, u_int16_t *bytes_read) { + u_int16_t val = ndpi_bytestream_to_number(str, max_chars_to_read, bytes_read); + return(ntohs(val)); + } -/* ****************************************************** */ + /* ****************************************************** */ -u_int16_t ndpi_get_lower_proto(ndpi_protocol proto) { - return((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) ? proto.master_protocol : proto.app_protocol); -} + u_int8_t ndpi_is_proto(ndpi_protocol proto, u_int16_t p) { + return(((proto.app_protocol == p) || (proto.master_protocol == p)) ? 1 : 0); + } -/* ****************************************************** */ + /* ****************************************************** */ -ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, 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_int32_t rc; - struct in_addr addr; - ndpi_protocol ret = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED}; - u_int8_t user_defined_proto; + u_int16_t ndpi_get_lower_proto(ndpi_protocol proto) { + return((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) ? proto.master_protocol : proto.app_protocol); + } - if((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) { - rc = ndpi_search_tcp_or_udp_raw(ndpi_str, flow, proto, shost, dhost, sport, dport); + /* ****************************************************** */ - if(rc != NDPI_PROTOCOL_UNKNOWN) { - if(flow && (proto == IPPROTO_UDP) && - NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_guessable_protocol(rc)) - ; - else { - ret.app_protocol = rc, - ret.master_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto); + ndpi_protocol ndpi_guess_undetected_protocol(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, 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_int32_t rc; + struct in_addr addr; + ndpi_protocol ret = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED}; + u_int8_t user_defined_proto; - if(ret.app_protocol == ret.master_protocol) - ret.master_protocol = NDPI_PROTOCOL_UNKNOWN; + if((proto == IPPROTO_TCP) || (proto == IPPROTO_UDP)) { + rc = ndpi_search_tcp_or_udp_raw(ndpi_str, flow, proto, shost, dhost, sport, dport); - ret.category = ndpi_get_proto_category(ndpi_str, ret); - return(ret); - } - } + if(rc != NDPI_PROTOCOL_UNKNOWN) { + if(flow && (proto == IPPROTO_UDP) && + NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_guessable_protocol(rc)) + ; + else { + ret.app_protocol = rc, + ret.master_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto); - rc = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto); - if(rc != NDPI_PROTOCOL_UNKNOWN) { - if(flow && (proto == IPPROTO_UDP) && - NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_guessable_protocol(rc)) - ; - else { - ret.app_protocol = rc; + if(ret.app_protocol == ret.master_protocol) + ret.master_protocol = NDPI_PROTOCOL_UNKNOWN; - if(rc == NDPI_PROTOCOL_TLS) - goto check_guessed_skype; - else { ret.category = ndpi_get_proto_category(ndpi_str, ret); return(ret); } } - } - check_guessed_skype: - addr.s_addr = htonl(shost); - if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE) { - ret.app_protocol = NDPI_PROTOCOL_SKYPE; - } else { - addr.s_addr = htonl(dhost); - if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE) - ret.app_protocol = NDPI_PROTOCOL_SKYPE; - } - } else - ret.app_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto); - - ret.category = ndpi_get_proto_category(ndpi_str, ret); - return(ret); -} + rc = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto); + if(rc != NDPI_PROTOCOL_UNKNOWN) { + if(flow && (proto == IPPROTO_UDP) && + NDPI_COMPARE_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, rc) && is_udp_guessable_protocol(rc)) + ; + else { + ret.app_protocol = rc; -/* ****************************************************** */ + if(rc == NDPI_PROTOCOL_TLS) + goto check_guessed_skype; + else { + ret.category = ndpi_get_proto_category(ndpi_str, ret); + return(ret); + } + } + } -char *ndpi_protocol2id(struct ndpi_detection_module_struct *ndpi_str, - ndpi_protocol proto, char *buf, u_int buf_len) { - if((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (proto.master_protocol != proto.app_protocol)) { - if(proto.app_protocol != NDPI_PROTOCOL_UNKNOWN) - snprintf(buf, buf_len, "%u.%u", proto.master_protocol, proto.app_protocol); - else - snprintf(buf, buf_len, "%u", proto.master_protocol); - } else - snprintf(buf, buf_len, "%u", proto.app_protocol); + check_guessed_skype: + addr.s_addr = htonl(shost); + if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE) { + ret.app_protocol = NDPI_PROTOCOL_SKYPE; + } else { + addr.s_addr = htonl(dhost); + if(ndpi_network_ptree_match(ndpi_str, &addr) == NDPI_PROTOCOL_SKYPE) + ret.app_protocol = NDPI_PROTOCOL_SKYPE; + } + } else + ret.app_protocol = ndpi_guess_protocol_id(ndpi_str, flow, proto, sport, dport, &user_defined_proto); - return(buf); -} + ret.category = ndpi_get_proto_category(ndpi_str, ret); + return(ret); + } -/* ****************************************************** */ + /* ****************************************************** */ -char *ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_str, + char *ndpi_protocol2id(struct ndpi_detection_module_struct *ndpi_str, ndpi_protocol proto, char *buf, u_int buf_len) { - if((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (proto.master_protocol != proto.app_protocol)) { - if(proto.app_protocol != NDPI_PROTOCOL_UNKNOWN) - snprintf(buf, buf_len, "%s.%s", ndpi_get_proto_name(ndpi_str, proto.master_protocol), - ndpi_get_proto_name(ndpi_str, proto.app_protocol)); - else - snprintf(buf, buf_len, "%s", ndpi_get_proto_name(ndpi_str, proto.master_protocol)); - } else - snprintf(buf, buf_len, "%s", ndpi_get_proto_name(ndpi_str, proto.app_protocol)); - - return(buf); -} - -/* ****************************************************** */ - -int ndpi_is_custom_category(ndpi_protocol_category_t category) { - switch(category) { - case NDPI_PROTOCOL_CATEGORY_CUSTOM_1: - case NDPI_PROTOCOL_CATEGORY_CUSTOM_2: - case NDPI_PROTOCOL_CATEGORY_CUSTOM_3: - case NDPI_PROTOCOL_CATEGORY_CUSTOM_4: - case NDPI_PROTOCOL_CATEGORY_CUSTOM_5: - return(1); - break; + if((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (proto.master_protocol != proto.app_protocol)) { + if(proto.app_protocol != NDPI_PROTOCOL_UNKNOWN) + snprintf(buf, buf_len, "%u.%u", proto.master_protocol, proto.app_protocol); + else + snprintf(buf, buf_len, "%u", proto.master_protocol); + } else + snprintf(buf, buf_len, "%u", proto.app_protocol); - default: - return(0); - break; + return(buf); } -} -/* ****************************************************** */ + /* ****************************************************** */ -void ndpi_category_set_name(struct ndpi_detection_module_struct *ndpi_str, - ndpi_protocol_category_t category, - char *name) { - if(!name) - return; - - switch(category) { - case NDPI_PROTOCOL_CATEGORY_CUSTOM_1: - snprintf(ndpi_str->custom_category_labels[0], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); - break; - - case NDPI_PROTOCOL_CATEGORY_CUSTOM_2: - snprintf(ndpi_str->custom_category_labels[1], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); - break; + char *ndpi_protocol2name(struct ndpi_detection_module_struct *ndpi_str, + ndpi_protocol proto, char *buf, u_int buf_len) { + if((proto.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (proto.master_protocol != proto.app_protocol)) { + if(proto.app_protocol != NDPI_PROTOCOL_UNKNOWN) + snprintf(buf, buf_len, "%s.%s", ndpi_get_proto_name(ndpi_str, proto.master_protocol), + ndpi_get_proto_name(ndpi_str, proto.app_protocol)); + else + snprintf(buf, buf_len, "%s", ndpi_get_proto_name(ndpi_str, proto.master_protocol)); + } else + snprintf(buf, buf_len, "%s", ndpi_get_proto_name(ndpi_str, proto.app_protocol)); - case NDPI_PROTOCOL_CATEGORY_CUSTOM_3: - snprintf(ndpi_str->custom_category_labels[2], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); - break; + return(buf); + } - case NDPI_PROTOCOL_CATEGORY_CUSTOM_4: - snprintf(ndpi_str->custom_category_labels[3], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); - break; + /* ****************************************************** */ - case NDPI_PROTOCOL_CATEGORY_CUSTOM_5: - snprintf(ndpi_str->custom_category_labels[4], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); - break; + int ndpi_is_custom_category(ndpi_protocol_category_t category) { + switch(category) { + case NDPI_PROTOCOL_CATEGORY_CUSTOM_1: + case NDPI_PROTOCOL_CATEGORY_CUSTOM_2: + case NDPI_PROTOCOL_CATEGORY_CUSTOM_3: + case NDPI_PROTOCOL_CATEGORY_CUSTOM_4: + case NDPI_PROTOCOL_CATEGORY_CUSTOM_5: + return(1); + break; - default: - break; + default: + return(0); + break; + } } -} -/* ****************************************************** */ + /* ****************************************************** */ -const char *ndpi_category_get_name(struct ndpi_detection_module_struct *ndpi_str, - ndpi_protocol_category_t category) { - if((!ndpi_str) || (category >= NDPI_PROTOCOL_NUM_CATEGORIES)) { - static char b[24]; - - if(!ndpi_str) - snprintf(b, sizeof(b), "NULL nDPI"); - else - snprintf(b, sizeof(b), "Invalid category %d", (int) category); - return(b); - } + void ndpi_category_set_name(struct ndpi_detection_module_struct *ndpi_str, + ndpi_protocol_category_t category, + char *name) { + if(!name) + return; - if((category >= NDPI_PROTOCOL_CATEGORY_CUSTOM_1) && (category <= NDPI_PROTOCOL_CATEGORY_CUSTOM_5)) { switch(category) { case NDPI_PROTOCOL_CATEGORY_CUSTOM_1: - return(ndpi_str->custom_category_labels[0]); + snprintf(ndpi_str->custom_category_labels[0], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); + break; + case NDPI_PROTOCOL_CATEGORY_CUSTOM_2: - return(ndpi_str->custom_category_labels[1]); + snprintf(ndpi_str->custom_category_labels[1], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); + break; + case NDPI_PROTOCOL_CATEGORY_CUSTOM_3: - return(ndpi_str->custom_category_labels[2]); + snprintf(ndpi_str->custom_category_labels[2], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); + break; + case NDPI_PROTOCOL_CATEGORY_CUSTOM_4: - return(ndpi_str->custom_category_labels[3]); + snprintf(ndpi_str->custom_category_labels[3], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); + break; + case NDPI_PROTOCOL_CATEGORY_CUSTOM_5: - return(ndpi_str->custom_category_labels[4]); - case NDPI_PROTOCOL_NUM_CATEGORIES: - return("Code should not use this internal constant"); + snprintf(ndpi_str->custom_category_labels[4], CUSTOM_CATEGORY_LABEL_LEN, "%s", name); + break; + default: - return("Unspecified"); + break; } - } else - return(categories[category]); -} - -/* ****************************************************** */ + } -ndpi_protocol_category_t ndpi_get_proto_category(struct ndpi_detection_module_struct *ndpi_str, - ndpi_protocol proto) { - if(proto.category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) - return(proto.category); + /* ****************************************************** */ - /* simple rule: sub protocol first, master after */ - else if((proto.master_protocol == NDPI_PROTOCOL_UNKNOWN) || - (ndpi_str->proto_defaults[proto.app_protocol].protoCategory != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)) { - if(proto.app_protocol < (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) - return(ndpi_str->proto_defaults[proto.app_protocol].protoCategory); - } else if(proto.master_protocol < (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) - return(ndpi_str->proto_defaults[proto.master_protocol].protoCategory); + const char *ndpi_category_get_name(struct ndpi_detection_module_struct *ndpi_str, + ndpi_protocol_category_t category) { + if((!ndpi_str) || (category >= NDPI_PROTOCOL_NUM_CATEGORIES)) { + static char b[24]; - return(NDPI_PROTOCOL_CATEGORY_UNSPECIFIED); -} + if(!ndpi_str) + snprintf(b, sizeof(b), "NULL nDPI"); + else + snprintf(b, sizeof(b), "Invalid category %d", (int) category); + return(b); + } -/* ****************************************************** */ + if((category >= NDPI_PROTOCOL_CATEGORY_CUSTOM_1) && (category <= NDPI_PROTOCOL_CATEGORY_CUSTOM_5)) { + switch(category) { + case NDPI_PROTOCOL_CATEGORY_CUSTOM_1: + return(ndpi_str->custom_category_labels[0]); + case NDPI_PROTOCOL_CATEGORY_CUSTOM_2: + return(ndpi_str->custom_category_labels[1]); + case NDPI_PROTOCOL_CATEGORY_CUSTOM_3: + return(ndpi_str->custom_category_labels[2]); + case NDPI_PROTOCOL_CATEGORY_CUSTOM_4: + return(ndpi_str->custom_category_labels[3]); + case NDPI_PROTOCOL_CATEGORY_CUSTOM_5: + return(ndpi_str->custom_category_labels[4]); + case NDPI_PROTOCOL_NUM_CATEGORIES: + return("Code should not use this internal constant"); + default: + return("Unspecified"); + } + } else + return(categories[category]); + } -char *ndpi_get_proto_name(struct ndpi_detection_module_struct *ndpi_str, - u_int16_t proto_id) { - if((proto_id >= ndpi_str->ndpi_num_supported_protocols) || - (proto_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) || - (ndpi_str->proto_defaults[proto_id].protoName == NULL)) - proto_id = NDPI_PROTOCOL_UNKNOWN; + /* ****************************************************** */ - return(ndpi_str->proto_defaults[proto_id].protoName); -} + ndpi_protocol_category_t ndpi_get_proto_category(struct ndpi_detection_module_struct *ndpi_str, + ndpi_protocol proto) { + if(proto.category != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) + return(proto.category); -/* ****************************************************** */ + /* simple rule: sub protocol first, master after */ + else if((proto.master_protocol == NDPI_PROTOCOL_UNKNOWN) || + (ndpi_str->proto_defaults[proto.app_protocol].protoCategory != NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)) { + if(proto.app_protocol < (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) + return(ndpi_str->proto_defaults[proto.app_protocol].protoCategory); + } else if(proto.master_protocol < (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) + return(ndpi_str->proto_defaults[proto.master_protocol].protoCategory); -ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_str, - u_int16_t proto_id) { - if((proto_id >= ndpi_str->ndpi_num_supported_protocols) || - (proto_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) || - (ndpi_str->proto_defaults[proto_id].protoName == NULL)) - proto_id = NDPI_PROTOCOL_UNKNOWN; + return(NDPI_PROTOCOL_CATEGORY_UNSPECIFIED); + } - return(ndpi_str->proto_defaults[proto_id].protoBreed); -} + /* ****************************************************** */ -/* ****************************************************** */ + char *ndpi_get_proto_name(struct ndpi_detection_module_struct *ndpi_str, + u_int16_t proto_id) { + if((proto_id >= ndpi_str->ndpi_num_supported_protocols) || + (proto_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) || + (ndpi_str->proto_defaults[proto_id].protoName == NULL)) + proto_id = NDPI_PROTOCOL_UNKNOWN; -char *ndpi_get_proto_breed_name(struct ndpi_detection_module_struct *ndpi_str, - ndpi_protocol_breed_t breed_id) { - switch(breed_id) { - case NDPI_PROTOCOL_SAFE: - return("Safe"); - break; - case NDPI_PROTOCOL_ACCEPTABLE: - return("Acceptable"); - break; - case NDPI_PROTOCOL_FUN: - return("Fun"); - break; - case NDPI_PROTOCOL_UNSAFE: - return("Unsafe"); - break; - case NDPI_PROTOCOL_POTENTIALLY_DANGEROUS: - return("Potentially Dangerous"); - break; - case NDPI_PROTOCOL_DANGEROUS: - return("Dangerous"); - break; - case NDPI_PROTOCOL_UNRATED: - default: - return("Unrated"); - break; + return(ndpi_str->proto_defaults[proto_id].protoName); } -} -/* ****************************************************** */ + /* ****************************************************** */ -int ndpi_get_protocol_id(struct ndpi_detection_module_struct *ndpi_str, char *proto) { - int i; + ndpi_protocol_breed_t ndpi_get_proto_breed(struct ndpi_detection_module_struct *ndpi_str, + u_int16_t proto_id) { + if((proto_id >= ndpi_str->ndpi_num_supported_protocols) || + (proto_id >= (NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS)) || + (ndpi_str->proto_defaults[proto_id].protoName == NULL)) + proto_id = NDPI_PROTOCOL_UNKNOWN; - for (i = 0; i < (int) ndpi_str->ndpi_num_supported_protocols; i++) - if(strcasecmp(proto, ndpi_str->proto_defaults[i].protoName) == 0) - return(i); + return(ndpi_str->proto_defaults[proto_id].protoBreed); + } - return(-1); -} + /* ****************************************************** */ -/* ****************************************************** */ + char *ndpi_get_proto_breed_name(struct ndpi_detection_module_struct *ndpi_str, + ndpi_protocol_breed_t breed_id) { + switch(breed_id) { + case NDPI_PROTOCOL_SAFE: + return("Safe"); + break; + case NDPI_PROTOCOL_ACCEPTABLE: + return("Acceptable"); + break; + case NDPI_PROTOCOL_FUN: + return("Fun"); + break; + case NDPI_PROTOCOL_UNSAFE: + return("Unsafe"); + break; + case NDPI_PROTOCOL_POTENTIALLY_DANGEROUS: + return("Potentially Dangerous"); + break; + case NDPI_PROTOCOL_DANGEROUS: + return("Dangerous"); + break; + case NDPI_PROTOCOL_UNRATED: + default: + return("Unrated"); + break; + } + } -int ndpi_get_category_id(struct ndpi_detection_module_struct *ndpi_str, char *cat) { - int i; + /* ****************************************************** */ - for (i = 0; i < NDPI_PROTOCOL_NUM_CATEGORIES; i++) { - const char *name = ndpi_category_get_name(ndpi_str, i); + int ndpi_get_protocol_id(struct ndpi_detection_module_struct *ndpi_str, char *proto) { + int i; - if(strcasecmp(cat, name) == 0) - return(i); + for (i = 0; i < (int) ndpi_str->ndpi_num_supported_protocols; i++) + if(strcasecmp(proto, ndpi_str->proto_defaults[i].protoName) == 0) + return(i); + + return(-1); } - return(-1); -} + /* ****************************************************** */ -/* ****************************************************** */ + int ndpi_get_category_id(struct ndpi_detection_module_struct *ndpi_str, char *cat) { + int i; -void ndpi_dump_protocols(struct ndpi_detection_module_struct *ndpi_str) { - int i; + for (i = 0; i < NDPI_PROTOCOL_NUM_CATEGORIES; i++) { + const char *name = ndpi_category_get_name(ndpi_str, i); - for (i = 0; i < (int) ndpi_str->ndpi_num_supported_protocols; i++) - printf("%3d %-22s %-8s %-12s %s\n", i, ndpi_str->proto_defaults[i].protoName, - ndpi_get_l4_proto_name(ndpi_get_l4_proto_info(ndpi_str, i)), - ndpi_get_proto_breed_name(ndpi_str, ndpi_str->proto_defaults[i].protoBreed), - ndpi_category_get_name(ndpi_str, ndpi_str->proto_defaults[i].protoCategory)); -} + if(strcasecmp(cat, name) == 0) + return(i); + } -/* ****************************************************** */ + return(-1); + } -/* - * Find the first occurrence of find in s, where the search is limited to the - * first slen characters of s. - */ -char *ndpi_strnstr(const char *s, const char *find, size_t slen) { - char c; - size_t len; + /* ****************************************************** */ + + void ndpi_dump_protocols(struct ndpi_detection_module_struct *ndpi_str) { + int i; + + for (i = 0; i < (int) ndpi_str->ndpi_num_supported_protocols; i++) + printf("%3d %-22s %-8s %-12s %s\n", i, ndpi_str->proto_defaults[i].protoName, + ndpi_get_l4_proto_name(ndpi_get_l4_proto_info(ndpi_str, i)), + ndpi_get_proto_breed_name(ndpi_str, ndpi_str->proto_defaults[i].protoBreed), + ndpi_category_get_name(ndpi_str, ndpi_str->proto_defaults[i].protoCategory)); + } - if((c = *find++) != '\0') { - len = strnlen(find, slen); - do { - char sc; + /* ****************************************************** */ + /* + * Find the first occurrence of find in s, where the search is limited to the + * first slen characters of s. + */ + char *ndpi_strnstr(const char *s, const char *find, size_t slen) { + char c; + size_t len; + + if((c = *find++) != '\0') { + len = strnlen(find, slen); do { - if(slen-- < 1 || (sc = *s++) == '\0') + char sc; + + do { + if(slen-- < 1 || (sc = *s++) == '\0') + return(NULL); + } while (sc != c); + if(len > slen) return(NULL); - } while (sc != c); - if(len > slen) - return(NULL); - } while (strncmp(s, find, len) != 0); - s--; + } while (strncmp(s, find, len) != 0); + s--; + } + + return((char *) s); } - return((char *) s); -} + /* ****************************************************** */ -/* ****************************************************** */ + /* + * Same as ndpi_strnstr but case-insensitive + */ + const char * ndpi_strncasestr(const char *str1, const char *str2, size_t len) { + size_t str1_len = strnlen(str1, len); + size_t str2_len = strlen(str2); + size_t i; + + for(i = 0; i < (str1_len - str2_len + 1); i++){ + if(str1[0] == '\0') + return NULL; + else if(strncasecmp(str1, str2, str2_len) == 0) + return(str1); + + str1++; + } -/* - * Same as ndpi_strnstr but case-insensitive - */ -const char * ndpi_strncasestr(const char *str1, const char *str2, size_t len) { - size_t str1_len = strnlen(str1, len); - size_t str2_len = strlen(str2); - size_t i; + return NULL; + } - for(i = 0; i < (str1_len - str2_len + 1); i++){ - if(str1[0] == '\0') - return NULL; - else if(strncasecmp(str1, str2, str2_len) == 0) - return(str1); + /* ****************************************************** */ - str1++; + int ndpi_match_prefix(const u_int8_t *payload, + size_t payload_len, const char *str, size_t str_len) { + int rc = str_len <= payload_len ? memcmp(payload, str, str_len) == 0 : 0; + + return(rc); } - return NULL; -} + /* ****************************************************** */ -/* ****************************************************** */ + int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_str, char *string_to_match, + u_int string_to_match_len, ndpi_protocol_match_result *ret_match, + u_int8_t is_host_match) { + AC_TEXT_t ac_input_text; + ndpi_automa *automa = is_host_match ? &ndpi_str->host_automa : &ndpi_str->content_automa; + AC_REP_t match = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED}; + int rc; -int ndpi_match_prefix(const u_int8_t *payload, - size_t payload_len, const char *str, size_t str_len) { - int rc = str_len <= payload_len ? memcmp(payload, str, str_len) == 0 : 0; + if((automa->ac_automa == NULL) || (string_to_match_len == 0)) + return(NDPI_PROTOCOL_UNKNOWN); - return(rc); -} + if(!automa->ac_automa_finalized) { + printf("[%s:%d] [NDPI] Internal error: please call ndpi_finalize_initalization()\n", __FILE__, __LINE__); + return(0); /* No matches */ + } -/* ****************************************************** */ + ac_input_text.astring = string_to_match, ac_input_text.length = string_to_match_len; + rc = ac_automata_search(((AC_AUTOMATA_t *) automa->ac_automa), &ac_input_text, &match); -int ndpi_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_str, char *string_to_match, - u_int string_to_match_len, ndpi_protocol_match_result *ret_match, - u_int8_t is_host_match) { - AC_TEXT_t ac_input_text; - ndpi_automa *automa = is_host_match ? &ndpi_str->host_automa : &ndpi_str->content_automa; - AC_REP_t match = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED}; - int rc; + /* + 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; - if((automa->ac_automa == NULL) || (string_to_match_len == 0)) - return(NDPI_PROTOCOL_UNKNOWN); + /* We need to take into account also rc == 0 that is used for partial matches */ + ret_match->protocol_id = match.number, ret_match->protocol_category = match.category, + ret_match->protocol_breed = match.breed; - if(!automa->ac_automa_finalized) { - printf("[%s:%d] [NDPI] Internal error: please call ndpi_finalize_initalization()\n", __FILE__, __LINE__); - return(0); /* No matches */ + return(rc ? match.number : 0); } - ac_input_text.astring = string_to_match, ac_input_text.length = string_to_match_len; - rc = ac_automata_search(((AC_AUTOMATA_t *) automa->ac_automa), &ac_input_text, &match); - - /* - 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; - - /* We need to take into account also rc == 0 that is used for partial matches */ - ret_match->protocol_id = match.number, ret_match->protocol_category = match.category, - ret_match->protocol_breed = match.breed; + /* **************************************** */ - return(rc ? match.number : 0); -} + static u_int8_t ndpi_is_more_generic_protocol(u_int16_t previous_proto, u_int16_t new_proto) { + /* Sometimes certificates are more generic than previously identified protocols */ -/* **************************************** */ + if((previous_proto == NDPI_PROTOCOL_UNKNOWN) || (previous_proto == new_proto)) + return(0); -static u_int8_t ndpi_is_more_generic_protocol(u_int16_t previous_proto, u_int16_t new_proto) { - /* Sometimes certificates are more generic than previously identified protocols */ + switch(previous_proto) { + case NDPI_PROTOCOL_WHATSAPP_CALL: + case NDPI_PROTOCOL_WHATSAPP_FILES: + if(new_proto == NDPI_PROTOCOL_WHATSAPP) + return(1); + } - if((previous_proto == NDPI_PROTOCOL_UNKNOWN) || (previous_proto == new_proto)) return(0); - - switch(previous_proto) { - case NDPI_PROTOCOL_WHATSAPP_CALL: - case NDPI_PROTOCOL_WHATSAPP_FILES: - if(new_proto == NDPI_PROTOCOL_WHATSAPP) - return(1); } - return(0); -} - -/* ****************************************************** */ + /* ****************************************************** */ -static u_int16_t ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, char *string_to_match, - u_int string_to_match_len, u_int16_t master_protocol_id, - ndpi_protocol_match_result *ret_match, u_int8_t is_host_match) { - int matching_protocol_id; - struct ndpi_packet_struct *packet = &flow->packet; + static u_int16_t ndpi_automa_match_string_subprotocol(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, char *string_to_match, + u_int string_to_match_len, u_int16_t master_protocol_id, + ndpi_protocol_match_result *ret_match, u_int8_t is_host_match) { + int matching_protocol_id; + struct ndpi_packet_struct *packet = &flow->packet; - matching_protocol_id = - ndpi_match_string_subprotocol(ndpi_str, string_to_match, string_to_match_len, ret_match, is_host_match); + matching_protocol_id = + ndpi_match_string_subprotocol(ndpi_str, string_to_match, string_to_match_len, ret_match, is_host_match); #ifdef DEBUG - { - char m[256]; - int len = ndpi_min(sizeof(m), string_to_match_len); + { + char m[256]; + int len = ndpi_min(sizeof(m), string_to_match_len); - strncpy(m, string_to_match, len); - m[len] = '\0'; + strncpy(m, string_to_match, len); + m[len] = '\0'; - NDPI_LOG_DBG2(ndpi_str, "[NDPI] ndpi_match_host_subprotocol(%s): %s\n", m, - ndpi_str->proto_defaults[matching_protocol_id].protoName); - } + NDPI_LOG_DBG2(ndpi_str, "[NDPI] ndpi_match_host_subprotocol(%s): %s\n", m, + ndpi_str->proto_defaults[matching_protocol_id].protoName); + } #endif - if((matching_protocol_id != NDPI_PROTOCOL_UNKNOWN) && - (!ndpi_is_more_generic_protocol(packet->detected_protocol_stack[0], matching_protocol_id))) { - /* Move the protocol on slot 0 down one position */ - packet->detected_protocol_stack[1] = master_protocol_id, - packet->detected_protocol_stack[0] = matching_protocol_id; + if((matching_protocol_id != NDPI_PROTOCOL_UNKNOWN) && + (!ndpi_is_more_generic_protocol(packet->detected_protocol_stack[0], matching_protocol_id))) { + /* Move the protocol on slot 0 down one position */ + packet->detected_protocol_stack[1] = master_protocol_id, + 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]; + flow->detected_protocol_stack[0] = packet->detected_protocol_stack[0], + flow->detected_protocol_stack[1] = packet->detected_protocol_stack[1]; - if(flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) - flow->category = ret_match->protocol_category; + if(flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) + flow->category = ret_match->protocol_category; - return(packet->detected_protocol_stack[0]); - } + return(packet->detected_protocol_stack[0]); + } #ifdef DEBUG - string_to_match[string_to_match_len] = '\0'; - NDPI_LOG_DBG2(ndpi_str, "[NTOP] Unable to find a match for '%s'\n", string_to_match); + string_to_match[string_to_match_len] = '\0'; + NDPI_LOG_DBG2(ndpi_str, "[NTOP] Unable to find a match for '%s'\n", string_to_match); #endif - ret_match->protocol_id = NDPI_PROTOCOL_UNKNOWN, ret_match->protocol_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, - ret_match->protocol_breed = NDPI_PROTOCOL_UNRATED; + ret_match->protocol_id = NDPI_PROTOCOL_UNKNOWN, ret_match->protocol_category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, + ret_match->protocol_breed = NDPI_PROTOCOL_UNRATED; - return(NDPI_PROTOCOL_UNKNOWN); -} + return(NDPI_PROTOCOL_UNKNOWN); + } -/* ****************************************************** */ + /* ****************************************************** */ -u_int16_t ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, - char *string_to_match, u_int string_to_match_len, - ndpi_protocol_match_result *ret_match, u_int16_t master_protocol_id) { - u_int16_t rc = ndpi_automa_match_string_subprotocol(ndpi_str, flow, string_to_match, string_to_match_len, - master_protocol_id, ret_match, 1); - ndpi_protocol_category_t id = ret_match->protocol_category; - - if(ndpi_get_custom_category_match(ndpi_str, string_to_match, string_to_match_len, &id) != -1) { - /* if(id != -1) */ { - flow->category = ret_match->protocol_category = id; - rc = master_protocol_id; + u_int16_t ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_str, struct ndpi_flow_struct *flow, + char *string_to_match, u_int string_to_match_len, + ndpi_protocol_match_result *ret_match, u_int16_t master_protocol_id) { + u_int16_t rc = ndpi_automa_match_string_subprotocol(ndpi_str, flow, string_to_match, string_to_match_len, + master_protocol_id, ret_match, 1); + ndpi_protocol_category_t id = ret_match->protocol_category; + + if(ndpi_get_custom_category_match(ndpi_str, string_to_match, string_to_match_len, &id) != -1) { + /* if(id != -1) */ { + flow->category = ret_match->protocol_category = id; + rc = master_protocol_id; + } } + + return(rc); } - return(rc); -} + /* **************************************** */ -/* **************************************** */ + int ndpi_match_hostname_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, + u_int16_t master_protocol, char *name, u_int name_len) { + ndpi_protocol_match_result ret_match; + u_int16_t subproto, what_len, i; + char *what; -int ndpi_match_hostname_protocol(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - u_int16_t master_protocol, char *name, u_int name_len) { - ndpi_protocol_match_result ret_match; - u_int16_t subproto, what_len, i; - char *what; + if((name_len > 2) && (name[0] == '*') && (name[1] == '.')) + what = &name[1], what_len = name_len - 1; + else + what = name, what_len = name_len; - if((name_len > 2) && (name[0] == '*') && (name[1] == '.')) - what = &name[1], what_len = name_len - 1; - else - what = name, what_len = name_len; + /* Convert it first to lowercase: we assume meory is writable as in nDPI dissctors */ + for(i=0; i<name_len; i++) what[i] = tolower(what[i]); - /* Convert it first to lowercase: we assume meory is writable as in nDPI dissctors */ - for(i=0; i<name_len; i++) what[i] = tolower(what[i]); + subproto = ndpi_match_host_subprotocol(ndpi_struct, flow, what, what_len, &ret_match, master_protocol); - subproto = ndpi_match_host_subprotocol(ndpi_struct, flow, what, what_len, &ret_match, master_protocol); + if(subproto != NDPI_PROTOCOL_UNKNOWN) { + ndpi_set_detected_protocol(ndpi_struct, flow, subproto, master_protocol); + ndpi_int_change_category(ndpi_struct, flow, ret_match.protocol_category); + return(1); + } else + return(0); + } - if(subproto != NDPI_PROTOCOL_UNKNOWN) { - ndpi_set_detected_protocol(ndpi_struct, flow, subproto, master_protocol); - ndpi_int_change_category(ndpi_struct, flow, ret_match.protocol_category); - return(1); - } else - return(0); -} + /* ****************************************************** */ -/* ****************************************************** */ + u_int16_t ndpi_match_content_subprotocol(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + char *string_to_match, u_int string_to_match_len, + ndpi_protocol_match_result *ret_match, + u_int16_t master_protocol_id) { + return(ndpi_automa_match_string_subprotocol(ndpi_str, flow, string_to_match, string_to_match_len, + master_protocol_id, ret_match, 0)); + } -u_int16_t ndpi_match_content_subprotocol(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - char *string_to_match, u_int string_to_match_len, - ndpi_protocol_match_result *ret_match, - u_int16_t master_protocol_id) { - return(ndpi_automa_match_string_subprotocol(ndpi_str, flow, string_to_match, string_to_match_len, - master_protocol_id, ret_match, 0)); -} + /* ****************************************************** */ -/* ****************************************************** */ + int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_str, + ndpi_automa *automa, char *bigram_to_match) { + AC_TEXT_t ac_input_text; + AC_REP_t match = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED}; + int rc; -int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_str, - ndpi_automa *automa, char *bigram_to_match) { - AC_TEXT_t ac_input_text; - AC_REP_t match = {NDPI_PROTOCOL_UNKNOWN, NDPI_PROTOCOL_CATEGORY_UNSPECIFIED, NDPI_PROTOCOL_UNRATED}; - int rc; + if((automa->ac_automa == NULL) || (bigram_to_match == NULL)) + return(-1); - if((automa->ac_automa == NULL) || (bigram_to_match == NULL)) - return(-1); - - if(!automa->ac_automa_finalized) { + if(!automa->ac_automa_finalized) { #if 1 - ndpi_finalize_initalization(ndpi_str); + ndpi_finalize_initalization(ndpi_str); #else - printf("[%s:%d] [NDPI] Internal error: please call ndpi_finalize_initalization()\n", __FILE__, __LINE__); - return(0); /* No matches */ + printf("[%s:%d] [NDPI] Internal error: please call ndpi_finalize_initalization()\n", __FILE__, __LINE__); + return(0); /* No matches */ #endif - } + } - ac_input_text.astring = bigram_to_match, ac_input_text.length = 2; - rc = ac_automata_search(((AC_AUTOMATA_t *) automa->ac_automa), &ac_input_text, &match); + ac_input_text.astring = bigram_to_match, ac_input_text.length = 2; + rc = ac_automata_search(((AC_AUTOMATA_t *) automa->ac_automa), &ac_input_text, &match); - /* - 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; + /* + 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); -} + return(rc ? match.number : 0); + } -/* ****************************************************** */ + /* ****************************************************** */ -void ndpi_free_flow_data(struct ndpi_flow_struct *flow) { - if(flow) { - u_int is_quic = flow_is_proto(flow, NDPI_PROTOCOL_QUIC); + void ndpi_free_flow_data(struct ndpi_flow_struct *flow) { + if(flow) { + u_int is_quic = flow_is_proto(flow, NDPI_PROTOCOL_QUIC); - if(flow->http.url) - ndpi_free(flow->http.url); + if(flow->http.url) + ndpi_free(flow->http.url); - if(flow->http.content_type) - ndpi_free(flow->http.content_type); + if(flow->http.content_type) + ndpi_free(flow->http.content_type); - if(flow->http.request_content_type) - ndpi_free(flow->http.request_content_type); + if(flow->http.request_content_type) + ndpi_free(flow->http.request_content_type); - if(flow->http.user_agent) - ndpi_free(flow->http.user_agent); + if(flow->http.user_agent) + ndpi_free(flow->http.user_agent); - if(flow->kerberos_buf.pktbuf) - ndpi_free(flow->kerberos_buf.pktbuf); + if(flow->kerberos_buf.pktbuf) + ndpi_free(flow->kerberos_buf.pktbuf); - if(is_quic - || flow_is_proto(flow, NDPI_PROTOCOL_TLS) - || flow_is_proto(flow, NDPI_PROTOCOL_DTLS) - ) { - if(flow->protos.tls_quic_stun.tls_quic.server_names) - ndpi_free(flow->protos.tls_quic_stun.tls_quic.server_names); + if(is_quic + || flow_is_proto(flow, NDPI_PROTOCOL_TLS) + || flow_is_proto(flow, NDPI_PROTOCOL_DTLS) + ) { + if(flow->protos.tls_quic_stun.tls_quic.server_names) + ndpi_free(flow->protos.tls_quic_stun.tls_quic.server_names); - if(flow->protos.tls_quic_stun.tls_quic.alpn) - ndpi_free(flow->protos.tls_quic_stun.tls_quic.alpn); + if(flow->protos.tls_quic_stun.tls_quic.alpn) + ndpi_free(flow->protos.tls_quic_stun.tls_quic.alpn); - if(flow->protos.tls_quic_stun.tls_quic.tls_supported_versions) - ndpi_free(flow->protos.tls_quic_stun.tls_quic.tls_supported_versions); + if(flow->protos.tls_quic_stun.tls_quic.tls_supported_versions) + ndpi_free(flow->protos.tls_quic_stun.tls_quic.tls_supported_versions); - if(flow->protos.tls_quic_stun.tls_quic.issuerDN) - ndpi_free(flow->protos.tls_quic_stun.tls_quic.issuerDN); + if(flow->protos.tls_quic_stun.tls_quic.issuerDN) + ndpi_free(flow->protos.tls_quic_stun.tls_quic.issuerDN); - if(flow->protos.tls_quic_stun.tls_quic.subjectDN) - ndpi_free(flow->protos.tls_quic_stun.tls_quic.subjectDN); + if(flow->protos.tls_quic_stun.tls_quic.subjectDN) + ndpi_free(flow->protos.tls_quic_stun.tls_quic.subjectDN); - if(flow->protos.tls_quic_stun.tls_quic.encrypted_sni.esni) - ndpi_free(flow->protos.tls_quic_stun.tls_quic.encrypted_sni.esni); - } + if(flow->protos.tls_quic_stun.tls_quic.encrypted_sni.esni) + ndpi_free(flow->protos.tls_quic_stun.tls_quic.encrypted_sni.esni); + } - if(flow->l4_proto == IPPROTO_TCP) { - if(flow->l4.tcp.tls.message.buffer) - ndpi_free(flow->l4.tcp.tls.message.buffer); + if(flow->l4_proto == IPPROTO_TCP) { + if(flow->l4.tcp.tls.message.buffer) + ndpi_free(flow->l4.tcp.tls.message.buffer); #ifdef FRAG_MAN - free_fragment(&flow->tcp_segments_list[0]); - free_fragment(&flow->tcp_segments_list[1]); + free_fragment(&flow->tcp_segments_list[0]); + free_fragment(&flow->tcp_segments_list[1]); #endif + } } } -} -void ndpi_free_flow(struct ndpi_flow_struct *flow) { - if (flow) { - ndpi_free_flow_data(flow); - ndpi_free(flow); + void ndpi_free_flow(struct ndpi_flow_struct *flow) { + if(flow) { + ndpi_free_flow_data(flow); + ndpi_free(flow); + } } -} -/* ****************************************************** */ + /* ****************************************************** */ -char *ndpi_revision() { - return(NDPI_GIT_RELEASE); -} + char *ndpi_revision() { + return(NDPI_GIT_RELEASE); + } -/* ****************************************************** */ + /* ****************************************************** */ #ifdef WIN32 -/* https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows */ -int gettimeofday(struct timeval *tp, struct timezone *tzp) { - // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's - // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) - // until 00:00:00 January 1, 1970 - static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + /* https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows */ + int gettimeofday(struct timeval *tp, struct timezone *tzp) { + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); - SYSTEMTIME system_time; - FILETIME file_time; - uint64_t time; + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; - GetSystemTime(&system_time); - SystemTimeToFileTime(&system_time, &file_time); - time = ((uint64_t) file_time.dwLowDateTime); - time += ((uint64_t) file_time.dwHighDateTime) << 32; + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + time = ((uint64_t) file_time.dwLowDateTime); + time += ((uint64_t) file_time.dwHighDateTime) << 32; - tp->tv_sec = (long) ((time - EPOCH) / 10000000L); - tp->tv_usec = (long) (system_time.wMilliseconds * 1000); - return(0); -} + tp->tv_sec = (long) ((time - EPOCH) / 10000000L); + tp->tv_usec = (long) (system_time.wMilliseconds * 1000); + return(0); + } #endif -int NDPI_BITMASK_COMPARE(NDPI_PROTOCOL_BITMASK a, NDPI_PROTOCOL_BITMASK b) { - int i; + int NDPI_BITMASK_COMPARE(NDPI_PROTOCOL_BITMASK a, NDPI_PROTOCOL_BITMASK b) { + int i; - for (i = 0; i < NDPI_NUM_FDS_BITS; i++) { - if(a.fds_bits[i] & b.fds_bits[i]) - return(1); - } + for (i = 0; i < NDPI_NUM_FDS_BITS; i++) { + if(a.fds_bits[i] & b.fds_bits[i]) + return(1); + } - return(0); -} + return(0); + } #ifdef CODE_UNUSED -int NDPI_BITMASK_IS_EMPTY(NDPI_PROTOCOL_BITMASK a) { - int i; + int NDPI_BITMASK_IS_EMPTY(NDPI_PROTOCOL_BITMASK a) { + int i; - for (i = 0; i < NDPI_NUM_FDS_BITS; i++) - if(a.fds_bits[i] != 0) - return(0); + for (i = 0; i < NDPI_NUM_FDS_BITS; i++) + if(a.fds_bits[i] != 0) + return(0); - return(1); -} + return(1); + } -void NDPI_DUMP_BITMASK(NDPI_PROTOCOL_BITMASK a) { - int i; + void NDPI_DUMP_BITMASK(NDPI_PROTOCOL_BITMASK a) { + int i; - for (i = 0; i < NDPI_NUM_FDS_BITS; i++) - printf("[%d=%u]", i, a.fds_bits[i]); + for (i = 0; i < NDPI_NUM_FDS_BITS; i++) + printf("[%d=%u]", i, a.fds_bits[i]); - printf("\n"); -} + printf("\n"); + } #endif -u_int16_t ndpi_get_api_version() { - return(NDPI_API_VERSION); -} + u_int16_t ndpi_get_api_version() { + return(NDPI_API_VERSION); + } -const char *ndpi_get_gcrypt_version(void) { + const char *ndpi_get_gcrypt_version(void) { #ifdef HAVE_LIBGCRYPT - return gcry_check_version(NULL); + return gcry_check_version(NULL); #endif - return NULL; -} + return NULL; + } -ndpi_proto_defaults_t *ndpi_get_proto_defaults(struct ndpi_detection_module_struct *ndpi_str) { - return(ndpi_str->proto_defaults); -} + ndpi_proto_defaults_t *ndpi_get_proto_defaults(struct ndpi_detection_module_struct *ndpi_str) { + return(ndpi_str->proto_defaults); + } -u_int ndpi_get_ndpi_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_str) { - return(ndpi_str->ndpi_num_supported_protocols); -} + u_int ndpi_get_ndpi_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_str) { + return(ndpi_str->ndpi_num_supported_protocols); + } -u_int ndpi_get_ndpi_num_custom_protocols(struct ndpi_detection_module_struct *ndpi_str) { - return(ndpi_str->ndpi_num_custom_protocols); -} + u_int ndpi_get_ndpi_num_custom_protocols(struct ndpi_detection_module_struct *ndpi_str) { + return(ndpi_str->ndpi_num_custom_protocols); + } -u_int ndpi_get_ndpi_detection_module_size() { - return(sizeof(struct ndpi_detection_module_struct)); -} + u_int ndpi_get_ndpi_detection_module_size() { + return(sizeof(struct ndpi_detection_module_struct)); + } -void ndpi_set_debug_bitmask(struct ndpi_detection_module_struct *ndpi_str, NDPI_PROTOCOL_BITMASK debug_bitmask) { + void ndpi_set_debug_bitmask(struct ndpi_detection_module_struct *ndpi_str, NDPI_PROTOCOL_BITMASK debug_bitmask) { #ifdef NDPI_ENABLE_DEBUG_MESSAGES - ndpi_str->debug_bitmask = debug_bitmask; + ndpi_str->debug_bitmask = debug_bitmask; #endif -} + } -void ndpi_set_log_level(struct ndpi_detection_module_struct *ndpi_str, u_int l){ - ndpi_str->ndpi_log_level = l; -} + void ndpi_set_log_level(struct ndpi_detection_module_struct *ndpi_str, u_int l){ + ndpi_str->ndpi_log_level = l; + } -/* ******************************************************************** */ + /* ******************************************************************** */ -/* LRU cache */ -struct ndpi_lru_cache *ndpi_lru_cache_init(u_int32_t num_entries) { - struct ndpi_lru_cache *c = (struct ndpi_lru_cache *) ndpi_malloc(sizeof(struct ndpi_lru_cache)); + /* LRU cache */ + struct ndpi_lru_cache *ndpi_lru_cache_init(u_int32_t num_entries) { + struct ndpi_lru_cache *c = (struct ndpi_lru_cache *) ndpi_malloc(sizeof(struct ndpi_lru_cache)); - if(!c) - return(NULL); + if(!c) + return(NULL); - c->entries = (struct ndpi_lru_cache_entry *) ndpi_calloc(num_entries, sizeof(struct ndpi_lru_cache_entry)); + c->entries = (struct ndpi_lru_cache_entry *) ndpi_calloc(num_entries, sizeof(struct ndpi_lru_cache_entry)); - if(!c->entries) { - ndpi_free(c); - return(NULL); - } else - c->num_entries = num_entries; + if(!c->entries) { + ndpi_free(c); + return(NULL); + } else + c->num_entries = num_entries; - return(c); -} + return(c); + } -void ndpi_lru_free_cache(struct ndpi_lru_cache *c) { - ndpi_free(c->entries); - ndpi_free(c); -} + void ndpi_lru_free_cache(struct ndpi_lru_cache *c) { + ndpi_free(c->entries); + ndpi_free(c); + } -u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key, - u_int16_t *value, u_int8_t clean_key_when_found) { - u_int32_t slot = key % c->num_entries; + u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key, + u_int16_t *value, u_int8_t clean_key_when_found) { + u_int32_t slot = key % c->num_entries; - if(c->entries[slot].is_full) { - *value = c->entries[slot].value; - if(clean_key_when_found) - c->entries[slot].is_full = 0; - return(1); - } else - return(0); -} + if(c->entries[slot].is_full) { + *value = c->entries[slot].value; + if(clean_key_when_found) + c->entries[slot].is_full = 0; + return(1); + } else + return(0); + } -void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t value) { - u_int32_t slot = key % c->num_entries; + void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t value) { + u_int32_t slot = key % c->num_entries; - c->entries[slot].is_full = 1, c->entries[slot].key = key, c->entries[slot].value = value; -} + c->entries[slot].is_full = 1, c->entries[slot].key = key, c->entries[slot].value = value; + } -/* ******************************************************************** */ + /* ******************************************************************** */ -/* - 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_str, - struct ndpi_flow_struct *flow) { - u_int16_t proto = - flow->detected_protocol_stack[1] ? flow->detected_protocol_stack[1] : flow->detected_protocol_stack[0]; + /* + 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_str, + struct ndpi_flow_struct *flow) { + u_int16_t proto = + flow->detected_protocol_stack[1] ? flow->detected_protocol_stack[1] : flow->detected_protocol_stack[0]; #if 0 - printf("[DEBUG] %s(%u.%u): %u\n", __FUNCTION__, - flow->detected_protocol_stack[0], - flow->detected_protocol_stack[1], - proto); + printf("[DEBUG] %s(%u.%u): %u\n", __FUNCTION__, + flow->detected_protocol_stack[0], + flow->detected_protocol_stack[1], + proto); #endif - switch(proto) { - case NDPI_PROTOCOL_TLS: - if(flow->l4.tcp.tls.certificate_processed) return(0); + switch(proto) { + case NDPI_PROTOCOL_TLS: + if(flow->l4.tcp.tls.certificate_processed) return(0); - if(flow->l4.tcp.tls.num_tls_blocks <= ndpi_str->num_tls_blocks_to_follow) { - // printf("*** %u/%u\n", flow->l4.tcp.tls.num_tls_blocks, ndpi_str->num_tls_blocks_to_follow); - return(1); - } - break; + if(flow->l4.tcp.tls.num_tls_blocks <= ndpi_str->num_tls_blocks_to_follow) { + // printf("*** %u/%u\n", flow->l4.tcp.tls.num_tls_blocks, ndpi_str->num_tls_blocks_to_follow); + return(1); + } + break; - case NDPI_PROTOCOL_HTTP: - if((flow->host_server_name[0] == '\0') || (flow->http.response_status_code == 0)) - return(1); - break; + case NDPI_PROTOCOL_HTTP: + if((flow->host_server_name[0] == '\0') || (flow->http.response_status_code == 0)) + return(1); + break; - case NDPI_PROTOCOL_DNS: - case NDPI_PROTOCOL_MDNS: - if(flow->protos.dns.num_answers == 0) - return(1); - break; + case NDPI_PROTOCOL_DNS: + case NDPI_PROTOCOL_MDNS: + if(flow->protos.dns.num_answers == 0) + return(1); + break; - case NDPI_PROTOCOL_FTP_CONTROL: - case NDPI_PROTOCOL_MAIL_POP: - case NDPI_PROTOCOL_MAIL_IMAP: - case NDPI_PROTOCOL_MAIL_SMTP: - if(flow->protos.ftp_imap_pop_smtp.password[0] == '\0') - return(1); - break; + case NDPI_PROTOCOL_FTP_CONTROL: + case NDPI_PROTOCOL_MAIL_POP: + case NDPI_PROTOCOL_MAIL_IMAP: + case NDPI_PROTOCOL_MAIL_SMTP: + if(flow->protos.ftp_imap_pop_smtp.password[0] == '\0') + return(1); + break; - case NDPI_PROTOCOL_SSH: - if((flow->protos.ssh.hassh_client[0] == '\0') || (flow->protos.ssh.hassh_server[0] == '\0')) - return(1); - break; + case NDPI_PROTOCOL_SSH: + if((flow->protos.ssh.hassh_client[0] == '\0') || (flow->protos.ssh.hassh_server[0] == '\0')) + return(1); + break; - case NDPI_PROTOCOL_TELNET: - if(!flow->protos.telnet.password_detected) - return(1); - break; + case NDPI_PROTOCOL_TELNET: + if(!flow->protos.telnet.password_detected) + return(1); + break; - case NDPI_PROTOCOL_SKYPE: - if (flow->extra_packets_func) - return(1); - break; + case NDPI_PROTOCOL_SKYPE: + if(flow->extra_packets_func) + return(1); + break; + } + + return(0); } - return(0); -} + /* ******************************************************************** */ -/* ******************************************************************** */ + const char *ndpi_get_l4_proto_name(ndpi_l4_proto_info proto) { + switch(proto) { + case ndpi_l4_proto_unknown: + return(""); + break; -const char *ndpi_get_l4_proto_name(ndpi_l4_proto_info proto) { - switch(proto) { - case ndpi_l4_proto_unknown: - return(""); - break; + case ndpi_l4_proto_tcp_only: + return("TCP"); + break; - case ndpi_l4_proto_tcp_only: - return("TCP"); - break; + case ndpi_l4_proto_udp_only: + return("UDP"); + break; - case ndpi_l4_proto_udp_only: - return("UDP"); - break; + case ndpi_l4_proto_tcp_and_udp: + return("TCP/UDP"); + break; + } - case ndpi_l4_proto_tcp_and_udp: - return("TCP/UDP"); - break; + return(""); } - return(""); -} + /* ******************************************************************** */ -/* ******************************************************************** */ + ndpi_l4_proto_info ndpi_get_l4_proto_info(struct ndpi_detection_module_struct *ndpi_struct, + u_int16_t ndpi_proto_id) { + if(ndpi_proto_id < ndpi_struct->ndpi_num_supported_protocols) { + u_int16_t idx = ndpi_struct->proto_defaults[ndpi_proto_id].protoIdx; + NDPI_SELECTION_BITMASK_PROTOCOL_SIZE bm = ndpi_struct->callback_buffer[idx].ndpi_selection_bitmask; -ndpi_l4_proto_info ndpi_get_l4_proto_info(struct ndpi_detection_module_struct *ndpi_struct, - u_int16_t ndpi_proto_id) { - if(ndpi_proto_id < ndpi_struct->ndpi_num_supported_protocols) { - u_int16_t idx = ndpi_struct->proto_defaults[ndpi_proto_id].protoIdx; - NDPI_SELECTION_BITMASK_PROTOCOL_SIZE bm = ndpi_struct->callback_buffer[idx].ndpi_selection_bitmask; + if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP) + return(ndpi_l4_proto_tcp_only); + else if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP) + return(ndpi_l4_proto_udp_only); + else if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP) + return(ndpi_l4_proto_tcp_and_udp); + } - if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP) - return(ndpi_l4_proto_tcp_only); - else if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP) - return(ndpi_l4_proto_udp_only); - else if(bm & NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP) - return(ndpi_l4_proto_tcp_and_udp); + return(ndpi_l4_proto_unknown); /* default */ } - return(ndpi_l4_proto_unknown); /* default */ -} - -/* ******************************************************************** */ + /* ******************************************************************** */ -ndpi_ptree_t *ndpi_ptree_create(void) { - ndpi_ptree_t *tree = (ndpi_ptree_t *) ndpi_malloc(sizeof(ndpi_ptree_t)); + ndpi_ptree_t *ndpi_ptree_create(void) { + ndpi_ptree_t *tree = (ndpi_ptree_t *) ndpi_malloc(sizeof(ndpi_ptree_t)); - if(tree) { - tree->v4 = ndpi_New_Patricia(32); - tree->v6 = ndpi_New_Patricia(128); + if(tree) { + tree->v4 = ndpi_New_Patricia(32); + tree->v6 = ndpi_New_Patricia(128); - if((!tree->v4) || (!tree->v6)) { - ndpi_ptree_destroy(tree); - return(NULL); + if((!tree->v4) || (!tree->v6)) { + ndpi_ptree_destroy(tree); + return(NULL); + } } - } - return(tree); -} + return(tree); + } -/* ******************************************************************** */ + /* ******************************************************************** */ -void ndpi_ptree_destroy(ndpi_ptree_t *tree) { - if(tree) { - if(tree->v4) - ndpi_Destroy_Patricia(tree->v4, free_ptree_data); - if(tree->v6) - ndpi_Destroy_Patricia(tree->v6, free_ptree_data); + void ndpi_ptree_destroy(ndpi_ptree_t *tree) { + if(tree) { + if(tree->v4) + ndpi_Destroy_Patricia(tree->v4, free_ptree_data); + if(tree->v6) + ndpi_Destroy_Patricia(tree->v6, free_ptree_data); - ndpi_free(tree); + ndpi_free(tree); + } } -} -/* ******************************************************************** */ + /* ******************************************************************** */ -int ndpi_ptree_insert(ndpi_ptree_t *tree, const ndpi_ip_addr_t *addr, - u_int8_t bits, u_int64_t user_data) { - u_int8_t is_v6 = ndpi_is_ipv6(addr); - patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; - prefix_t prefix; - patricia_node_t *node; + int ndpi_ptree_insert(ndpi_ptree_t *tree, const ndpi_ip_addr_t *addr, + u_int8_t bits, u_int64_t user_data) { + u_int8_t is_v6 = ndpi_is_ipv6(addr); + patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; + prefix_t prefix; + patricia_node_t *node; - if(bits > ptree->maxbits) - return(-1); + if(bits > ptree->maxbits) + return(-1); - if(is_v6) - fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); - else - fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); + if(is_v6) + fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); + else + fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); - /* Verify that the node does not already exist */ - node = ndpi_patricia_search_best(ptree, &prefix); + /* Verify that the node does not already exist */ + node = ndpi_patricia_search_best(ptree, &prefix); - if(node && (node->prefix->bitlen == bits)) - return(-2); + if(node && (node->prefix->bitlen == bits)) + return(-2); - node = ndpi_patricia_lookup(ptree, &prefix); + node = ndpi_patricia_lookup(ptree, &prefix); - if(node != NULL) { - node->value.u.uv64 = user_data; + if(node != NULL) { + node->value.u.uv64 = user_data; - return(0); + return(0); + } + + return(-3); } - return(-3); -} + /* ******************************************************************** */ -/* ******************************************************************** */ + int ndpi_ptree_match_addr(ndpi_ptree_t *tree, + const ndpi_ip_addr_t *addr, u_int64_t *user_data) { + u_int8_t is_v6 = ndpi_is_ipv6(addr); + patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; + prefix_t prefix; + patricia_node_t *node; + int bits = ptree->maxbits; -int ndpi_ptree_match_addr(ndpi_ptree_t *tree, - const ndpi_ip_addr_t *addr, u_int64_t *user_data) { - u_int8_t is_v6 = ndpi_is_ipv6(addr); - patricia_tree_t *ptree = is_v6 ? tree->v6 : tree->v4; - prefix_t prefix; - patricia_node_t *node; - int bits = ptree->maxbits; + if(is_v6) + fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); + else + fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); - if(is_v6) - fill_prefix_v6(&prefix, (const struct in6_addr *) &addr->ipv6, bits, ptree->maxbits); - else - fill_prefix_v4(&prefix, (const struct in_addr *) &addr->ipv4, bits, ptree->maxbits); + node = ndpi_patricia_search_best(ptree, &prefix); - node = ndpi_patricia_search_best(ptree, &prefix); + if(node) { + *user_data = node->value.u.uv64; - if(node) { - *user_data = node->value.u.uv64; + return(0); + } - return(0); + return(-1); } - return(-1); -} + /* ******************************************************************** */ -/* ******************************************************************** */ + void ndpi_md5(const u_char *data, size_t data_len, u_char hash[16]) { + ndpi_MD5_CTX ctx; -void ndpi_md5(const u_char *data, size_t data_len, u_char hash[16]) { - ndpi_MD5_CTX ctx; - - ndpi_MD5Init(&ctx); - ndpi_MD5Update(&ctx, data, data_len); - ndpi_MD5Final(hash, &ctx); -} + ndpi_MD5Init(&ctx); + ndpi_MD5Update(&ctx, data, data_len); + ndpi_MD5Final(hash, &ctx); + } -/* ******************************************************************** */ + /* ******************************************************************** */ -static int enough(int a, int b) { - u_int8_t percentage = 20; + static int enough(int a, int b) { + u_int8_t percentage = 20; - if(b == 0) return(0); - if(a == 0) return(1); + if(b == 0) return(0); + if(a == 0) return(1); - if(b > (((a+1)*percentage)/100)) return(1); + if(b > (((a+1)*percentage)/100)) return(1); - return(0); -} + return(0); + } -/* ******************************************************************** */ + /* ******************************************************************** */ -static u_int8_t endsWith(char *str, char *ends, u_int8_t ends_len) { - u_int str_len = str ? strlen(str) : 0; - u_int8_t rc; + static u_int8_t endsWith(char *str, char *ends, u_int8_t ends_len) { + u_int str_len = str ? strlen(str) : 0; + u_int8_t rc; - if(str_len < ends_len) return(0); + if(str_len < ends_len) return(0); - rc = (strncmp(&str[str_len-ends_len], ends, ends_len) != 0) ? 0 : 1; + rc = (strncmp(&str[str_len-ends_len], ends, ends_len) != 0) ? 0 : 1; #ifdef DGA_DEBUG - printf("[DGA] %s / %s [rc: %u]\n", str, ends, rc); + printf("[DGA] %s / %s [rc: %u]\n", str, ends, rc); #endif - return(rc); -} + return(rc); + } -/* ******************************************************************** */ + /* ******************************************************************** */ -int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, - char *name, u_int8_t is_hostname) { - int len, rc = 0; - u_int8_t max_num_char_repetitions = 0, last_char = 0, num_char_repetitions = 0, num_dots = 0; - u_int8_t max_domain_element_len = 0, curr_domain_element_len = 0, first_element_is_numeric = 1; + int ndpi_check_dga_name(struct ndpi_detection_module_struct *ndpi_str, + struct ndpi_flow_struct *flow, + char *name, u_int8_t is_hostname) { + int len, rc = 0; + u_int8_t max_num_char_repetitions = 0, last_char = 0, num_char_repetitions = 0, num_dots = 0; + u_int8_t max_domain_element_len = 0, curr_domain_element_len = 0, first_element_is_numeric = 1; - if(!name) return(0); + if(!name) return(0); #ifdef DGA_DEBUG - printf("[DGA] %s\n", name); + printf("[DGA] %s\n", name); #endif - len = strlen(name); + len = strlen(name); - if(len >= 5) { - int i, j, num_found = 0, num_impossible = 0, num_bigram_checks = 0, num_digits = 0, num_vowels = 0, num_words = 0; - char tmp[128], *word, *tok_tmp; - u_int max_tmp_len = sizeof(tmp)-1; + if(len >= 5) { + int i, j, num_found = 0, num_impossible = 0, num_bigram_checks = 0, num_digits = 0, num_vowels = 0, num_words = 0; + char tmp[128], *word, *tok_tmp; + u_int max_tmp_len = sizeof(tmp)-1; - len = snprintf(tmp, max_tmp_len, "%s", name); - if(len < 0) { + len = snprintf(tmp, max_tmp_len, "%s", name); + if(len < 0) { #ifdef DGA_DEBUG - printf("[DGA] Too short"); + printf("[DGA] Too short"); #endif - return(0); - } else - tmp[len < max_tmp_len ? len : max_tmp_len] = '\0'; + return(0); + } else + tmp[len < max_tmp_len ? len : max_tmp_len] = '\0'; - for(i=0, j=0; (i<len) && (j<max_tmp_len); i++) { - tmp[j] = tolower(name[i]); + for(i=0, j=0; (i<len) && (j<max_tmp_len); i++) { + tmp[j] = tolower(name[i]); - if(tmp[j] == '.') - num_dots++; - else if(num_dots == 0) { - if(!isdigit(tmp[j])) - first_element_is_numeric = 0; - } + if(tmp[j] == '.') + num_dots++; + else if(num_dots == 0) { + if(!isdigit(tmp[j])) + first_element_is_numeric = 0; + } - if(last_char == tmp[j]) { - if(++num_char_repetitions > max_num_char_repetitions) - max_num_char_repetitions = num_char_repetitions; - } else - num_char_repetitions = 1, last_char = tmp[j]; - - switch(tmp[j]) { - case '.': - case '-': - case '_': - case '/': - case ')': - case '(': - case ';': - case ':': - case '[': - case ']': - case ' ': - /* - Domain/word separator chars + if(last_char == tmp[j]) { + if(++num_char_repetitions > max_num_char_repetitions) + max_num_char_repetitions = num_char_repetitions; + } else + num_char_repetitions = 1, last_char = tmp[j]; - NOTE: - this function is used also to detect other type of issues - such as invalid/suspiciuous user agent - */ - if(curr_domain_element_len > max_domain_element_len) - max_domain_element_len = curr_domain_element_len; + switch(tmp[j]) { + case '.': + case '-': + case '_': + case '/': + case ')': + case '(': + case ';': + case ':': + case '[': + case ']': + case ' ': + /* + Domain/word separator chars - curr_domain_element_len = 0; - break; + NOTE: + this function is used also to detect other type of issues + such as invalid/suspiciuous user agent + */ + if(curr_domain_element_len > max_domain_element_len) + max_domain_element_len = curr_domain_element_len; - default: - curr_domain_element_len++; - break; - } + curr_domain_element_len = 0; + break; - j++; - } + default: + curr_domain_element_len++; + break; + } + + j++; + } - if(curr_domain_element_len > max_domain_element_len) - max_domain_element_len = curr_domain_element_len; + if(curr_domain_element_len > max_domain_element_len) + max_domain_element_len = curr_domain_element_len; #ifdef DGA_DEBUG - printf("[DGA] [max_num_char_repetitions: %u][max_domain_element_len: %u]\n", - max_num_char_repetitions, max_domain_element_len); + printf("[DGA] [max_num_char_repetitions: %u][max_domain_element_len: %u]\n", + max_num_char_repetitions, max_domain_element_len); #endif - if( - (is_hostname - && (num_dots > 5) - && (!first_element_is_numeric) - && (!endsWith(tmp, "in-addr.arpa", 12)) - ) - || (max_num_char_repetitions > 5 /* num or consecutive repeated chars */) - /* - In case of a name with too many consecutive chars an alert is triggered - This is the case for instance of the wildcard DNS query used by NetBIOS - (ckaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) and that can be exploited - for reflection attacks - - https://www.akamai.com/uk/en/multimedia/documents/state-of-the-internet/ddos-reflection-netbios-name-server-rpc-portmap-sentinel-udp-threat-advisory.pdf - - http://ubiqx.org/cifs/NetBIOS.html - */ - || (max_domain_element_len >= 19 /* word too long. Example bbcbedxhgjmdobdprmen.com */) - ) { - if(flow) NDPI_SET_BIT(flow->risk, NDPI_SUSPICIOUS_DGA_DOMAIN); + if( + (is_hostname + && (num_dots > 5) + && (!first_element_is_numeric) + && (!endsWith(tmp, "in-addr.arpa", 12)) + ) + || (max_num_char_repetitions > 5 /* num or consecutive repeated chars */) + /* + In case of a name with too many consecutive chars an alert is triggered + This is the case for instance of the wildcard DNS query used by NetBIOS + (ckaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) and that can be exploited + for reflection attacks + - https://www.akamai.com/uk/en/multimedia/documents/state-of-the-internet/ddos-reflection-netbios-name-server-rpc-portmap-sentinel-udp-threat-advisory.pdf + - http://ubiqx.org/cifs/NetBIOS.html + */ + || (max_domain_element_len >= 19 /* word too long. Example bbcbedxhgjmdobdprmen.com */) + ) { + if(flow) NDPI_SET_BIT(flow->risk, NDPI_SUSPICIOUS_DGA_DOMAIN); #ifdef DGA_DEBUG - printf("[DGA] Found!"); + printf("[DGA] Found!"); #endif - return(1); - } + return(1); + } - tmp[j] = '\0'; - len = j; + tmp[j] = '\0'; + len = j; - for(word = strtok_r(tmp, ".", &tok_tmp); ; word = strtok_r(NULL, ".", &tok_tmp)) { - if(!word) break; + for(word = strtok_r(tmp, ".", &tok_tmp); ; word = strtok_r(NULL, ".", &tok_tmp)) { + if(!word) break; - num_words++; + num_words++; - if(strlen(word) < 3) continue; + if(strlen(word) < 3) continue; #ifdef DGA_DEBUG - printf("-> %s [%s][len: %u]\n", word, name, (unsigned int)strlen(word)); + printf("-> %s [%s][len: %u]\n", word, name, (unsigned int)strlen(word)); #endif - for(i = 0; word[i+1] != '\0'; i++) { - if(isdigit(word[i])) { - num_digits++; + for(i = 0; word[i+1] != '\0'; i++) { + if(isdigit(word[i])) { + num_digits++; - // if(!isdigit(word[i+1])) num_impossible++; + // if(!isdigit(word[i+1])) num_impossible++; - continue; - } + continue; + } - switch(word[i]) { - case '-': - /* - Let's check for double+consecutive -- - that are usually ok - r2---sn-uxaxpu5ap5-2n5e.gvt1.com - */ - if(word[i+1] == '-') - return(0); /* Double dash */ + switch(word[i]) { + case '-': + /* + Let's check for double+consecutive -- + that are usually ok + r2---sn-uxaxpu5ap5-2n5e.gvt1.com + */ + if(word[i+1] == '-') + return(0); /* Double dash */ - case '_': - case ':': - continue; - break; - - case '.': - continue; - break; - } + case '_': + case ':': + continue; + break; + + case '.': + continue; + break; + } - switch(word[i]) { - case 'a': - case 'e': - case 'i': - case 'o': - case 'u': - num_vowels++; - break; - } + switch(word[i]) { + case 'a': + case 'e': + case 'i': + case 'o': + case 'u': + num_vowels++; + break; + } - if(isdigit(word[i+1])) { - num_digits++; - // num_impossible++; - continue; - } + if(isdigit(word[i+1])) { + num_digits++; + // num_impossible++; + continue; + } - num_bigram_checks++; + num_bigram_checks++; #ifdef DGA_DEBUG - printf("-> Checking %c%c\n", word[i], word[i+1]); + printf("-> Checking %c%c\n", word[i], word[i+1]); #endif - if(ndpi_match_bigram(ndpi_str, - &ndpi_str->impossible_bigrams_automa, - &word[i])) { + if(ndpi_match_bigram(ndpi_str, + &ndpi_str->impossible_bigrams_automa, + &word[i])) { #ifdef DGA_DEBUG - printf("IMPOSSIBLE %s\n", &word[i]); + printf("IMPOSSIBLE %s\n", &word[i]); #endif - num_impossible++; - } else if(ndpi_match_bigram(ndpi_str, &ndpi_str->bigrams_automa, &word[i])) { - num_found++; - } + num_impossible++; + } else if(ndpi_match_bigram(ndpi_str, &ndpi_str->bigrams_automa, &word[i])) { + num_found++; + } + } /* for */ } /* for */ - } /* for */ #ifdef DGA_DEBUG - printf("[num_found: %u][num_impossible: %u][num_digits: %u][num_bigram_checks: %u][num_vowels: %u/%u]\n", - num_found, num_impossible, num_digits, num_bigram_checks, num_vowels, j-num_vowels); + printf("[num_found: %u][num_impossible: %u][num_digits: %u][num_bigram_checks: %u][num_vowels: %u/%u]\n", + num_found, num_impossible, num_digits, num_bigram_checks, num_vowels, j-num_vowels); #endif - if(num_bigram_checks - && ((num_found == 0) || ((num_digits > 5) && (num_words <= 3)) || enough(num_found, num_impossible))) - rc = 1; + if(num_bigram_checks + && ((num_found == 0) || ((num_digits > 5) && (num_words <= 3)) || enough(num_found, num_impossible))) + rc = 1; - if(rc && flow) - NDPI_SET_BIT(flow->risk, NDPI_SUSPICIOUS_DGA_DOMAIN); + if(rc && flow) + NDPI_SET_BIT(flow->risk, NDPI_SUSPICIOUS_DGA_DOMAIN); #ifdef DGA_DEBUG - if(rc) - printf("DGA %s [num_found: %u][num_impossible: %u]\n", - name, num_found, num_impossible); + if(rc) + printf("DGA %s [num_found: %u][num_impossible: %u]\n", + name, num_found, num_impossible); #endif - } + } #ifdef DGA_DEBUG - printf("[DGA] Result: %u", rc); + printf("[DGA] Result: %u", rc); #endif - return(rc); -} + return(rc); + } diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index 49f829fb1..3af0d3d23 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -57,6 +57,10 @@ // #define MATCH_DEBUG 1 +// #define DEBUG_REASSEMBLY + +/* ****************************************** */ + /* implementation of the punycode check function */ int ndpi_check_punycode_string(char * buffer , int len) { int i = 0; @@ -74,6 +78,8 @@ int ndpi_check_punycode_string(char * buffer , int len) { return 0; } +/* ****************************************** */ + /* ftp://ftp.cc.uoc.gr/mirrors/OpenBSD/src/lib/libc/stdlib/tsearch.c */ /* find or insert datum into search tree */ void * ndpi_tsearch(const void *vkey, void **vrootp, @@ -103,6 +109,8 @@ void * ndpi_tsearch(const void *vkey, void **vrootp, return ((void *)q->key); } +/* ****************************************** */ + /* delete node with given key */ void * ndpi_tdelete(const void *vkey, void **vrootp, int (*compar)(const void *, const void *)) @@ -145,6 +153,8 @@ void * ndpi_tdelete(const void *vkey, void **vrootp, return(key); } +/* ****************************************** */ + /* Walk the nodes of a tree */ static void ndpi_trecurse(ndpi_node *root, void (*action)(const void *, ndpi_VISIT, int, void*), int level, void *user_data) { @@ -161,6 +171,8 @@ static void ndpi_trecurse(ndpi_node *root, void (*action)(const void *, ndpi_VIS } } +/* ****************************************** */ + /* Walk the nodes of a tree */ void ndpi_twalk(const void *vroot, void (*action)(const void *, ndpi_VISIT, int, void *), void *user_data) { @@ -170,6 +182,8 @@ void ndpi_twalk(const void *vroot, void (*action)(const void *, ndpi_VISIT, int, ndpi_trecurse(root, action, 0, user_data); } +/* ****************************************** */ + /* find a node, or return 0 */ void * ndpi_tfind(const void *vkey, void *vrootp, int (*compar)(const void *, const void *)) @@ -987,43 +1001,43 @@ u_char* ndpi_base64_decode(const u_char *src, size_t len, size_t *out_len) { int pad = 0; memset(dtable, 0x80, 256); - for (i = 0; i < sizeof(base64_table) - 1; i++) + for(i = 0; i < sizeof(base64_table) - 1; i++) dtable[base64_table[i]] = (u_char) i; dtable['='] = 0; count = 0; - for (i = 0; i < len; i++) { - if (dtable[src[i]] != 0x80) + for(i = 0; i < len; i++) { + if(dtable[src[i]] != 0x80) count++; } - if (count == 0 || count % 4) + if(count == 0 || count % 4) return NULL; olen = count / 4 * 3; pos = out = ndpi_malloc(olen); - if (out == NULL) + if(out == NULL) return NULL; count = 0; - for (i = 0; i < len; i++) { + for(i = 0; i < len; i++) { tmp = dtable[src[i]]; - if (tmp == 0x80) + if(tmp == 0x80) continue; - if (src[i] == '=') + if(src[i] == '=') pad++; block[count] = tmp; count++; - if (count == 4) { + if(count == 4) { *pos++ = (block[0] << 2) | (block[1] >> 4); *pos++ = (block[1] << 4) | (block[2] >> 2); *pos++ = (block[2] << 6) | block[3]; count = 0; - if (pad) { - if (pad == 1) + if(pad) { + if(pad == 1) pos--; - else if (pad == 2) + else if(pad == 2) pos -= 2; else { /* Invalid padding */ @@ -1507,7 +1521,7 @@ static void ndpi_compile_rce_regex() { } static int ndpi_is_rce_injection(char* query) { - if (!initialized_comp_rx) { + if(!initialized_comp_rx) { ndpi_compile_rce_regex(); initialized_comp_rx = 1; } @@ -1522,7 +1536,7 @@ static int ndpi_is_rce_injection(char* query) { comp_rx[i]->optimized, query, length, 0, 0, subStrVec, 30); - if (pcreExecRet >= 0) { + if(pcreExecRet >= 0) { return 1; } #ifdef DEBUG @@ -1795,13 +1809,13 @@ ndpi_http_method ndpi_http_str2method(const char* method, u_int16_t method_len) void printRawData(const uint8_t *ptr, size_t len) { uint8_t *p=(uint8_t*)ptr; DBGINFO("ptr=%p, len=%llu", ptr, (unsigned long long)len) - if (p && len>0) { + if(p && len > 0) { size_t ctLines=0,i,j; char line1[ARRAYSZ_255]={0}, line2[ARRAYSZ_255]={0}, temp[ARRAYSZ_255]; snprintf(line1,sizeof(line1),"\t%05X",(unsigned int)(16*ctLines)); - for (i=0; i<len; i++) { + for(i=0; i<len; i++) { - if (i>0 && i%16==0) { + if(i > 0 && i%16==0) { printf("%s\t%s\n", line1,line2); ctLines++; snprintf(line1,ARRAYSZ_255,"\t%05X",(unsigned int)(16*ctLines)); @@ -1814,7 +1828,7 @@ void printRawData(const uint8_t *ptr, size_t len) { p++; } uint8_t exv= i%16; - for(j=exv;exv>0 && j<16;j++) { + for(j=exv;exv > 0 && j<16;j++) { strncat(line1, " ", 3); } printf("%s\t%s\n", line1,line2); @@ -1827,8 +1841,8 @@ void printRawData(const uint8_t *ptr, size_t len) { void ins_sort_array(sorter_index_item_t arr[], int len) { DBGINFO("sorting no. %u items", (unsigned)len) - for (int i=1; i<len; i++) { - for (int j=i; j>0 && arr[j].sort_value<arr[j-1].sort_value; j--) { + for(int i=1; i<len; i++) { + for(int j=i; j > 0 && arr[j].sort_value<arr[j-1].sort_value; j--) { sorter_index_item_t temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; @@ -1839,16 +1853,17 @@ void ins_sort_array(sorter_index_item_t arr[], int len) { void shell_sort_array(sorter_index_item_t arr[], int n) { // Rearrange elements at each n/2, n/4, n/8, ... intervals DBGINFO("sorting no. %u items", (unsigned)n) - for (int interval = n / 2; interval > 0; interval /= 2) { - for (int i = interval; i < n; i += 1) { + for(int interval = n / 2; interval > 0; interval /= 2) { + for(int i = interval; i < n; i += 1) { sorter_index_item_t temp = arr[i]; int j; - for (j = i; j >= interval && arr[j - interval].sort_value > temp.sort_value; j -= interval) { + for(j = i; j >= interval && arr[j - interval].sort_value > temp.sort_value; j -= interval) { arr[j] = arr[j - interval]; - DBGTRACER("exchanged item no. %d (%d) with: %d (%d)", j, arr[j].sort_value, j-interval, temp.sort_value) - } - DBGTRACER("item no. %d value: %d", j, temp.sort_value) - arr[j] = temp; + DBGTRACER("exchanged item no. %d (%d) with: %d (%d)", j, arr[j].sort_value, j-interval, temp.sort_value); + } + + DBGTRACER("item no. %d value: %d", j, temp.sort_value); + arr[j] = temp; } } } @@ -1858,35 +1873,37 @@ void shell_sort_array(sorter_index_item_t arr[], int n) { void free_fragment(fragments_wrapper_t *frag) { /* - * - typedef struct fragment_wrapper { - uint16_t id; - uint8_t l4_protocol; - uint8_t ct_frag; - #ifdef NDPI_DETECTION_SUPPORT_IPV6 - char *flow_label; // IP6 - #endif - fragment_t **fragments_list; - } fragments_wrapper_t; - * - * */ - if (frag) { - DBGTRACER("(frag:%p) freeing fragments list -> %p",frag, frag->fragments_list) - if (frag->fragments_list) { - DBGTRACER("fragments are %u.",frag->ct_frag) - for (int y=0;y<frag->ct_frag;y++) { - if (frag->fragments_list[y]) { - if (frag->fragments_list[y]->data) { - DBGPOINTER("freeing fragment item %d -> %p",y, frag->fragments_list[y]) - ndpi_free(frag->fragments_list[y]->data); - } - ndpi_free(frag->fragments_list[y]); - } - } - DBGPOINTER("freeing fragments list -> %p",frag->fragments_list) - ndpi_free(frag->fragments_list); - frag->fragments_list= NULL; - } + * + typedef struct fragment_wrapper { + uint16_t id; + uint8_t l4_protocol; + uint8_t ct_frag; + #ifdef NDPI_DETECTION_SUPPORT_IPV6 + char *flow_label; // IP6 + #endif + fragment_t **fragments_list; + } fragments_wrapper_t; + * + * */ + if(frag) { + DBGTRACER("(frag:%p) freeing fragments list -> %p",frag, frag->fragments_list); + if(frag->fragments_list) { + DBGTRACER("fragments are %u.",frag->ct_frag); + + for(int y=0;y<frag->ct_frag;y++) { + if(frag->fragments_list[y]) { + if(frag->fragments_list[y]->data) { + DBGPOINTER("freeing fragment item %d -> %p",y, frag->fragments_list[y]); + ndpi_free(frag->fragments_list[y]->data); + } + + ndpi_free(frag->fragments_list[y]); + } + } + DBGPOINTER("freeing fragments list -> %p",frag->fragments_list) + ndpi_free(frag->fragments_list); + frag->fragments_list= NULL; + } //reset counter and initial offset frag->ct_frag=0; frag->initial_offset=0; @@ -1899,87 +1916,93 @@ uint8_t add_segment_to_buffer(struct ndpi_flow_struct *flow, struct ndpi_tcphdr DBGINFO("[flow:%p], dir: %d, seq:%u, ack:%u, len: %ubytes", flow, flow->packet.packet_direction, ntohl(tcph->seq), ntohl(tcph->ack_seq), flow->packet.payload_packet_len) - if (flow->tcp_segments_management) { - fragments_wrapper_t *fragW= &flow->tcp_segments_list[flow->packet.packet_direction]; - DBGTRACER("tcp segments management enabled (list container: %p)",fragW) + if(flow->tcp_segments_management) { + fragments_wrapper_t *fragW= &flow->tcp_segments_list[flow->packet.packet_direction]; + DBGTRACER("tcp segments management enabled (list container: %p)", fragW); - if (fragW->ct_frag == 0) { - if (fragW->fragments_list) - free_fragment(fragW); + if(fragW->ct_frag == 0) { + if(fragW->fragments_list) + free_fragment(fragW); - // initialize the offset with the first fragment seq number - fragW->initial_offset = new_expected_seq; - DBGTRACER("initialized initial_offset: %u)",fragW->initial_offset) - } - - if (flow->packet.payload_packet_len>0) { - uint32_t seq; - - // allocate memory for pointer - size_t new_len= (1+fragW->ct_frag) * sizeof(fragment_t*); - DBGTRACER("actual fragment list ct=%d, new size: %llu", fragW->ct_frag, (unsigned long long)new_len) - - fragW->fragments_list = ndpi_realloc(fragW->fragments_list,(fragW->ct_frag * sizeof(fragment_t*)),new_len); - if (fragW->fragments_list == NULL) { - flow->tcp_segments_management= 0; - fprintf(stderr, "[%8u] Not enough memory for new fragment \n", flow->packet_counter); - return 0; + // initialize the offset with the first fragment seq number + fragW->initial_offset = new_expected_seq; + DBGTRACER("initialized initial_offset: %u)",fragW->initial_offset); } + + if(flow->packet.payload_packet_len > 0) { + uint32_t seq; + + // allocate memory for pointer + size_t new_len= (1+fragW->ct_frag) * sizeof(fragment_t*); + DBGTRACER("actual fragment list ct=%d, new size: %llu", fragW->ct_frag, (unsigned long long)new_len); + + fragW->fragments_list = ndpi_realloc(fragW->fragments_list,(fragW->ct_frag * sizeof(fragment_t*)),new_len); + if(fragW->fragments_list == NULL) { + flow->tcp_segments_management= 0; + // fprintf(stderr, "[%8u] Not enough memory for new fragment \n", flow->packet_counter); + return 0; + } - DBGPOINTER("fragments_list initialized for item no. %u, list->%p i-esimo->%p", - fragW->ct_frag, fragW->fragments_list, fragW->fragments_list[fragW->ct_frag]) - - // allocate memory for item - fragment_t *new_frag = (fragment_t*)ndpi_calloc(1, sizeof(fragment_t)); - if (new_frag == NULL) { - flow->tcp_segments_management= 0; - free_fragment(fragW); - fprintf(stderr, "[%8u] Not enough memory for new fragment \n", flow->packet_counter); - return 0; - } - - DBGPOINTER("new_frag=> %p",new_frag) - - // fill item with offsetm len and data fragment/segment - seq = (0xffffffff & ntohl(tcph->seq)); - if (seq >= fragW->initial_offset /* safety check */) { - new_frag->offset = seq - fragW->initial_offset; - } else { - /* CHECK THIS CASE - fprintf(stderr, "[%8u] Bad seq or initial offset (seq = %u, initial offset = %u)\n", - flow->packet_counter, seq, fragW->initial_offset); - */ - flow->tcp_segments_management= 0; - ndpi_free(new_frag); - free_fragment(fragW); - return 0; - } + DBGPOINTER("fragments_list initialized for item no. %u, list->%p i-esimo->%p", + fragW->ct_frag, fragW->fragments_list, fragW->fragments_list[fragW->ct_frag]); + + // allocate memory for item + fragment_t *new_frag = (fragment_t*)ndpi_calloc(1, sizeof(fragment_t)); + if(new_frag == NULL) { + flow->tcp_segments_management= 0; + free_fragment(fragW); + // fprintf(stderr, "[%8u] Not enough memory for new fragment \n", flow->packet_counter); + return 0; + } + + DBGPOINTER("new_frag=> %p",new_frag); + + // fill item with offsetm len and data fragment/segment + seq = (0xffffffff & ntohl(tcph->seq)); + if(seq >= fragW->initial_offset /* safety check */) { + new_frag->offset = seq - fragW->initial_offset; + } else { + /* CHECK THIS CASE + fprintf(stderr, "[%8u] Bad seq or initial offset (seq = %u, initial offset = %u)\n", + flow->packet_counter, seq, fragW->initial_offset); + */ + flow->tcp_segments_management= 0; + ndpi_free(new_frag); + free_fragment(fragW); + return 0; + } - DBGTRACER("offset calculation: seq %u, init: %u, offset result: %u", ntohl(tcph->seq), - fragW->initial_offset, new_frag->offset) - new_frag->len= flow->packet.payload_packet_len; + DBGTRACER("offset calculation: seq %u, init: %u, offset result: %u", ntohl(tcph->seq), + fragW->initial_offset, new_frag->offset); + new_frag->len = flow->packet.payload_packet_len; - new_frag->data = (void*)ndpi_calloc(new_frag->len, sizeof(char)); - DBGPOINTER("new_frag->data=> %p",new_frag->data) - if (new_frag->data) { - memcpy(new_frag->data,flow->packet.payload,new_frag->len); - fragW->fragments_list[fragW->ct_frag++]= new_frag; - } else { - flow->tcp_segments_management= 0; - ndpi_free(new_frag); - free_fragment(fragW); - fprintf(stderr, "[%8u] Not enough memory for new fragment data \n", flow->packet_counter); - return 0; - } + new_frag->data = (void*)ndpi_calloc(new_frag->len, sizeof(char)); + DBGPOINTER("new_frag->data=> %p",new_frag->data) + if(new_frag->data) { + memcpy(new_frag->data,flow->packet.payload,new_frag->len); + +#ifdef DEBUG_REASSEMBLY + printf("[%s:%u] ==>> %s() [%p][offset: %u]\n", + __FILE__, __LINE__, __FUNCTION__, new_frag, new_frag->offset); +#endif - DBGINFO("item no. %u: %p->%p [off:%u, len:%u, data:%p]", - fragW->ct_frag, fragW->fragments_list, *fragW->fragments_list, - (unsigned int) new_frag->offset, (unsigned int)new_frag->len, new_frag->data) + fragW->fragments_list[fragW->ct_frag++]= new_frag; /* Add it to the list */ + } else { + flow->tcp_segments_management= 0; + ndpi_free(new_frag); + free_fragment(fragW); + // fprintf(stderr, "[%8u] Not enough memory for new fragment data \n", flow->packet_counter); + return 0; + } - return fragW->ct_frag; - } - } + DBGINFO("item no. %u: %p->%p [off:%u, len:%u, data:%p]", + fragW->ct_frag, fragW->fragments_list, *fragW->fragments_list, + (unsigned int) new_frag->offset, (unsigned int)new_frag->len, new_frag->data); + return fragW->ct_frag; + } + } + return 0; } @@ -1987,14 +2010,20 @@ uint8_t add_segment_to_buffer(struct ndpi_flow_struct *flow, struct ndpi_tcphdr /* ******************************************************************** */ -uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tcphdr const * tcph, uint8_t **ret_buffer, size_t *len_buffer) { +uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, + struct ndpi_tcphdr const * tcph, + uint8_t **ret_buffer, size_t *len_buffer) { uint32_t ret_value = 0; uint16_t last_item = 0; - size_t length = 0,tot_length = 0; + size_t length = 0, tot_length = 0; sorter_index_item_t *sorted_indexes; fragments_wrapper_t *fragW; uint8_t *buffer; +#ifdef DEBUG_REASSEMBLY + printf("[%s:%u] ==>> %s()\n", __FILE__, __LINE__, __FUNCTION__); +#endif + fragW = &flow->tcp_segments_list[flow->packet.packet_direction]; DBGTRACER("tcph:%p, ret_buffer:%p, len_buffer:%u", tcph, ret_buffer, len_buffer); @@ -2002,83 +2031,87 @@ uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tc // phase 1: calculate the size and fill the indexes array DBGINFO("phase 1: init sorter, calculate the size of buffer to reassemble: %u items", fragW->ct_frag); - sorted_indexes = ndpi_calloc(fragW->ct_frag, sizeof(sorter_index_item_t)); + sorted_indexes = (sorter_index_item_t*)ndpi_calloc(fragW->ct_frag, sizeof(sorter_index_item_t)); - if (sorted_indexes == NULL) { - fprintf(stderr, "[%8u] Not enough memory to sort the %u segments \n", - flow->packet_counter, fragW->ct_frag); + if(sorted_indexes == NULL) { + //fprintf(stderr, "[%8u] Not enough memory to sort the %u segments \n", flow->packet_counter, fragW->ct_frag); free_fragment(fragW); return 0; } - DBGPOINTER("sorted_indexes=> %p", sorted_indexes) + DBGPOINTER("sorted_indexes=> %p", sorted_indexes); - for (int i=0; i<fragW->ct_frag; i++) { + for(int i=0; i<fragW->ct_frag; i++) { fragment_t *item = (fragment_t*)fragW->fragments_list[i]; - + sorted_indexes[i].sort_value = item->offset; sorted_indexes[i].item_index = i; tot_length += item->len; - + DBGTRACER("segment (%d): len:%lu, offset: %u => partial buffer len: %lu", - i, (long unsigned int)item->len, (unsigned int)item->offset, (long unsigned int)tot_length); + i, (long unsigned int)item->len, (unsigned int)item->offset, (long unsigned int)tot_length); } // phase 2: sorts fragments and check fragments and sequences DBGINFO(" phase 2 sorting %d segments and checking",fragW->ct_frag); - if (fragW->ct_frag>1) shell_sort_array(sorted_indexes, fragW->ct_frag); + if(fragW->ct_frag>1) shell_sort_array(sorted_indexes, fragW->ct_frag); // checks - for (uint i=0; i<fragW->ct_frag; i++) { + for(uint i=0; i<fragW->ct_frag; i++) { fragment_t *item = (fragment_t*)fragW->fragments_list[ sorted_indexes[i].item_index ]; // 1: no segment offset can be > tot_length DBGTRACER("checking %d/%d element: offset=%lu vs t_length=%lu", i, sorted_indexes[i].item_index, (unsigned long)item->offset, (unsigned long)tot_length); - if (item->offset > (uint32_t)tot_length) { + if((item->offset+item->len) > (uint32_t)tot_length) { // update the last index of elements to elaborate DBGINFO("stop processing at %d/%d element: len= %u; offset= %u", i, sorted_indexes[i].item_index, (unsigned)length, (unsigned)item->offset) - tot_length = length; + // tot_length = length; /* CHECK THIS CASE */ +#ifdef DEBUG_REASSEMBLY + printf("[%s:%u] ==>> Too long [last_item: %u][offset: %u/len: %u][%p]\n", __FILE__, __LINE__, + last_item, item->offset, item->len, item); +#endif + tot_length = item->offset+item->len; /* CHECK THIS CASE */ + // set the first offset to wait for the next segment ret_value = fragW->initial_offset + item->offset; - break; - - // 2: for every len(buffer) must exists a offset fragment - } else if (item->offset != (uint32_t)length) { - + // 2: for every len(buffer) must exists a offset fragment + } else if(item->offset != (uint32_t)length) { // update the last index of elements to elaborate DBGINFO("checking %d/%d element: stop processing! len: %u; n_offset: %u", i, sorted_indexes[i].item_index, (unsigned)length, (unsigned)item->offset); - tot_length = length; + // tot_length = length; /* CHECK THIS CASE */ // set the first offset to wait for the next segment ret_value = fragW->initial_offset + item->offset; - break; - } else { // continue to sum length data bytes - length+= item->len; - last_item= i; + length += item->len; + last_item = i; } } last_item++; // index to number aligment // phase 3: allocate memory and fill the buffer DBGINFO("phase 3: allocate memory for %u items and fill the buffer tot: %lu", last_item, (unsigned long int)tot_length); + +#ifdef DEBUG_REASSEMBLY + printf("[%s:%u] ==>> [tot_length: %u][length: %u]\n", + __FILE__, __LINE__, (u_int32_t)tot_length, (u_int32_t)length); +#endif buffer = ndpi_calloc(tot_length, sizeof(uint8_t)); - if (buffer == NULL) { - fprintf(stderr, "[%8u] Not enough memory for buffer for %u segments \n", - flow->packet_counter,last_item); + if(buffer == NULL) { + // fprintf(stderr, "[%8u] Not enough memory for buffer for %u segments \n", flow->packet_counter,last_item); free_fragment(fragW); ndpi_free(sorted_indexes); return 0; @@ -2086,13 +2119,29 @@ uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tc DBGPOINTER("buffer (len:%lu)=> %p", (unsigned long)tot_length, buffer); - for (uint i=0; i<last_item; i++) { + for(uint i=0; i<last_item; i++) { fragment_t *item = (fragment_t*) fragW->fragments_list[sorted_indexes[i].item_index]; DBGINFO("copying data item no:%u of len: %lu to buffer: %p (offset:%lu)", sorted_indexes[i].item_index, (unsigned long int)item->len, buffer, (unsigned long int)item->offset); + if((item->offset+item->len) > tot_length) { + //#ifdef DEBUG_REASSEMBLY + printf("[%s:%u] ==>> Out of boundary [%u vs %u][offset: %u][len: %u][item: %u/%u]\n", __FILE__, __LINE__, + (u_int32_t)(item->offset+item->len), (u_int32_t)tot_length, + (u_int32_t)item->offset, (u_int32_t)item->len, i, last_item); + //#endif + continue; + } else { +#ifdef DEBUG_REASSEMBLY + printf("[%s:%u] ==>> memcpy OK [%u vs %u][offset: %u][item: %u/%u]\n", + __FILE__, __LINE__, + (u_int32_t)(item->offset+item->len), (u_int32_t)tot_length, + item->offset, i, last_item); +#endif + } + memcpy((void*)(buffer + item->offset), item->data, item->len); // free memory item @@ -2102,7 +2151,7 @@ uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tc fragW->fragments_list[sorted_indexes[i].item_index]=NULL; } - if (last_item == fragW->ct_frag) { + if(last_item == fragW->ct_frag) { DBGTRACER("all processed: free all memory!"); free_fragment(fragW); } else { @@ -2113,8 +2162,8 @@ uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tc DBGPOINTER("old segments list: %p, new segments list: %p.", fragW_old_list, fragW->fragments_list); - if (!fragW->fragments_list) { - fprintf(stderr, "[%8u] Not enough memory for new segments list \n", flow->packet_counter); + if(!fragW->fragments_list) { + // fprintf(stderr, "[%8u] Not enough memory for new segments list \n", flow->packet_counter); free_fragment(fragW); ndpi_free(buffer); ndpi_free(sorted_indexes); @@ -2122,17 +2171,17 @@ uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tc } // re-fill the new segments list, updating the offsets - for (uint i = last_item; i < fragW->ct_frag; i++) { + for(uint i = last_item; i < fragW->ct_frag; i++) { fragment_t *item = (fragment_t*)fragW_old_list[sorted_indexes[i].item_index]; fragW->fragments_list[i-last_item] = item; - if (item->offset >= tot_length /* safety check */) { + if(item->offset >= tot_length /* safety check */) { item->offset -= tot_length; } /* CHECK THIS CASE - else { - fprintf(stderr, "[%8u] Bad offset update (item->offset = %u, tot_length = %lu)\n", - flow->packet_counter, item->offset, tot_length); - } + else { + fprintf(stderr, "[%8u] Bad offset update (item->offset = %u, tot_length = %lu)\n", + flow->packet_counter, item->offset, tot_length); + } */ DBGTRACER("moving the item (%p), index %u - to position %u of new segments list; new offset: %u.", @@ -2147,10 +2196,10 @@ uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tc (unsigned)fragW->ct_frag, (unsigned)fragW->initial_offset); DBGPOINTER("freeing old segments list: %p ", fragW_old_list) - ndpi_free(fragW_old_list); + ndpi_free(fragW_old_list); } - if (sorted_indexes) { + if(sorted_indexes) { DBGPOINTER("freeing sorter indexes: %p ", sorted_indexes); ndpi_free(sorted_indexes); } @@ -2171,7 +2220,7 @@ uint32_t reassembly_fragment(struct ndpi_flow_struct *const flow, struct ndpi_tc } DBGINFO("returning: %d", ret_value); - return ret_value; + return(ret_value); } /* ******************************************************************** */ @@ -2182,7 +2231,7 @@ uint8_t check_for_sequence(struct ndpi_flow_struct *flow, struct ndpi_tcphdr con DBGINFO("## sorted flags: %d/%d ",flow->not_sorted[0],flow->not_sorted[1]); - if (flow->next_tcp_seq_nr[flow->packet.packet_direction]) { + if(flow->next_tcp_seq_nr[flow->packet.packet_direction]) { uint32_t *trigger, expected; uint8_t *not_sorted; @@ -2190,16 +2239,17 @@ uint8_t check_for_sequence(struct ndpi_flow_struct *flow, struct ndpi_tcphdr con not_sorted = &flow->not_sorted[flow->packet.packet_direction]; trigger = &flow->trigger[flow->packet.packet_direction]; - DBGTRACER("dir:%d, trg:%u, next:%u", flow->packet.packet_direction,*trigger, flow->next_tcp_seq_nr[flow->packet.packet_direction]); + DBGTRACER("dir:%d, trg:%u, next:%u", flow->packet.packet_direction,*trigger, + flow->next_tcp_seq_nr[flow->packet.packet_direction]); - expected = (*not_sorted && *trigger) ? ndpi_min(*trigger,flow->next_tcp_seq_nr[flow->packet.packet_direction]) : flow->next_tcp_seq_nr[flow->packet.packet_direction]; + expected = (*not_sorted && *trigger) ? ndpi_min(*trigger, flow->next_tcp_seq_nr[flow->packet.packet_direction]) : flow->next_tcp_seq_nr[flow->packet.packet_direction]; - if (expected < (0xffffffff & ntohl(tcph->seq))) { + if(expected < (0xffffffff & ntohl(tcph->seq))) { // segment not in order... almost 1 has been skipped! add this fragment to buffer DBGINFO("received a segment (seq:%u) over the expected (next:%u)", (0xffffffff & ntohl(tcph->seq)), expected); - if (add_segment_to_buffer(flow, tcph, expected)) { - DBGTRACER("segment (seq:%u) bufferized, waiting for (next:%u)", (0xffffffff & ntohl(tcph->seq)), expected); + if(add_segment_to_buffer(flow, tcph, expected)) { + DBGTRACER("segment (seq:%u) bufferized, waiting for(next:%u)", (0xffffffff & ntohl(tcph->seq)), expected); // set flag a save the expected sequence number *not_sorted=1; @@ -2208,7 +2258,7 @@ uint8_t check_for_sequence(struct ndpi_flow_struct *flow, struct ndpi_tcphdr con } return 1; - } else if (expected>(0xffffffff & ntohl(tcph->seq))) { + } else if(expected>(0xffffffff & ntohl(tcph->seq))) { DBGINFO("received a segment (seq:%u) minus than the expected (next:%u): retransmission!!", (0xffffffff & ntohl(tcph->seq)), flow->next_tcp_seq_nr[flow->packet.packet_direction]); flow->packet.tcp_retransmission = 1; @@ -2228,14 +2278,17 @@ uint8_t check_for_sequence(struct ndpi_flow_struct *flow, struct ndpi_tcphdr con } } else { - DBGTRACER("seq (%u) and expected (%u) matched! sorted flag: %d", (0xffffffff & ntohl(tcph->seq)), flow->next_tcp_seq_nr[flow->packet.packet_direction], *not_sorted); + DBGTRACER("seq (%u) and expected (%u) matched! sorted flag: %d", + (0xffffffff & ntohl(tcph->seq)), + flow->next_tcp_seq_nr[flow->packet.packet_direction], + *not_sorted); - if (*not_sorted) { - if (add_segment_to_buffer(flow, tcph, 0)) { + if(*not_sorted) { + if(add_segment_to_buffer(flow, tcph, 0)) { *trigger= reassembly_fragment(flow,tcph,&ret_buffer,&len_buffer); - *not_sorted=(*trigger>0); + *not_sorted=(*trigger > 0); - if (len_buffer>0) { + if(len_buffer > 0) { // the previous pointers must not be free, because managed in other part flow->packet.payload_packet_len= len_buffer; flow->packet.payload= ret_buffer; |