diff options
Diffstat (limited to 'src/lib/ndpi_main.c')
-rw-r--r-- | src/lib/ndpi_main.c | 220 |
1 files changed, 151 insertions, 69 deletions
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index d12041dcb..b3271f8ca 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -455,7 +455,7 @@ static int ndpi_string_to_automa(struct ndpi_detection_module_struct *ndpi_struc /* TODO This function should free the memory during program termination - + */ static void ndpi_free_memory_at_termination(struct ndpi_detection_module_struct *ndpi_struct, char *buf) { @@ -471,7 +471,7 @@ static int ndpi_add_host_url_subprotocol(struct ndpi_detection_module_struct *nd char *value = ndpi_strdup(_value); if(!value) return(-1); else ndpi_free_memory_at_termination(ndpi_struct, value); - + #ifdef DEBUG NDPI_LOG_DEBUG2(ndpi_struct, "[NDPI] Adding [%s][%d]\n", value, protocol_id); #endif @@ -966,7 +966,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp no_master, "SkypeCall", NDPI_PROTOCOL_CATEGORY_VOIP, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); - ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TIKTOK, + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_TIKTOK, 0 /* can_have_a_subprotocol */, no_master, no_master, "TikTok", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, @@ -978,7 +978,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp ndpi_build_default_ports(ports_b, 3544, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_WECHAT, 0 /* can_have_a_subprotocol */, no_master, /* wechat.com */ - no_master, "WeChat", NDPI_PROTOCOL_CATEGORY_SOCIAL_NETWORK, + no_master, "WeChat", NDPI_PROTOCOL_CATEGORY_CHAT, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_MEMCACHED, @@ -1006,9 +1006,9 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp no_master, "Modbus", NDPI_PROTOCOL_CATEGORY_NETWORK, /* Perhaps IoT in the future */ ndpi_build_default_ports(ports_a, 502, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); - ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_VIDEO, + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_CALL, 0 /* can_have_a_subprotocol */, no_master, - no_master, "WhatsAppVideo", NDPI_PROTOCOL_CATEGORY_VOIP, + no_master, "WhatsAppCall", NDPI_PROTOCOL_CATEGORY_VOIP, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_PROTOCOL_DATASAVER, @@ -1122,9 +1122,9 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); - ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_FUN, NDPI_FREE_64, + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_PS_VUE, 0 /* can_have_a_subprotocol */, no_master, - no_master, "Free64", NDPI_PROTOCOL_CATEGORY_DOWNLOAD_FT, + no_master, "PS_VUE", NDPI_PROTOCOL_CATEGORY_VIDEO, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_UNSAFE, NDPI_PROTOCOL_IRC, @@ -1249,9 +1249,9 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp no_master, "PcAnywhere", NDPI_PROTOCOL_CATEGORY_REMOTE_ACCESS, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); - ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_VOICE, + ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_ZOOM, 0 /* can_have_a_subprotocol */, no_master, - no_master, "WhatsAppVoice", NDPI_PROTOCOL_CATEGORY_VOIP, + no_master, "Zoom", NDPI_PROTOCOL_CATEGORY_VIDEO, ndpi_build_default_ports(ports_a, 0, 0, 0, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 0, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_WHATSAPP_FILES, @@ -1555,7 +1555,7 @@ static void ndpi_init_protocol_defaults(struct ndpi_detection_module_struct *ndp ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_CISCOVPN, 0 /* can_have_a_subprotocol */, no_master, no_master, "CiscoVPN", NDPI_PROTOCOL_CATEGORY_VPN, - ndpi_build_default_ports(ports_a, 10000, 0, 0, 0, 0) /* TCP */, + ndpi_build_default_ports(ports_a, 10000, 8008, 8009, 0, 0) /* TCP */, ndpi_build_default_ports(ports_b, 10000, 0, 0, 0, 0) /* UDP */); ndpi_set_proto_defaults(ndpi_mod, NDPI_PROTOCOL_ACCEPTABLE, NDPI_PROTOCOL_TEAMSPEAK, 0 /* can_have_a_subprotocol */, no_master, @@ -1803,10 +1803,14 @@ static int ac_match_handler(AC_MATCH_t *m, AC_TEXT_t *txt, AC_REP_t *match) { if(whatfound && (whatfound != buf) && (m->patterns->astring[0] != '.') /* The searched pattern does not start with . */ - && strchr(m->patterns->astring, '.') /* The matched pattern has a . (e.g. numeric or sym IPs) */ - && (whatfound[-1] != '.') - ) - return(0); + && strchr(m->patterns->astring, '.') /* The matched pattern has a . (e.g. numeric or sym IPs) */) { + if(whatfound[-1] != '.') { + return(0); + } else { + memcpy(match, &m->patterns[0].rep, sizeof(AC_REP_t)); /* Partial match? */ + return(0); /* Keep searching as probably there is a better match */ + } + } } /* @@ -2224,6 +2228,13 @@ int ndpi_match_string(void *_automa, char *string_to_match) { rc = ac_automata_search(automa, &ac_input_text, &match); ac_automata_reset(automa); + /* + As ac_automata_search can detect partial matches and continue the search process + in case rc == 0 (i.e. no match), we need to check if there is a partial match + and in this case return it + */ + if((rc == 0) && (match.number != 0)) rc = 1; + return(rc ? match.number : 0); } @@ -2245,6 +2256,13 @@ int ndpi_match_string_id(void *_automa, char *string_to_match, unsigned long *id rc = ac_automata_search(automa, &ac_input_text, &match); ac_automata_reset(automa); + /* + As ac_automata_search can detect partial matches and continue the search process + in case rc == 0 (i.e. no match), we need to check if there is a partial match + and in this case return it + */ + if((rc == 0) && (match.number != 0)) rc = 1; + *id = rc ? match.number : NDPI_PROTOCOL_UNKNOWN; return(*id != NDPI_PROTOCOL_UNKNOWN ? 0 : -1); @@ -3552,7 +3570,7 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str u_int8_t l4_result; if (!flow) - return 1; + return 1; /* reset payload_packet_len, will be set if ipv4 tcp or udp */ flow->packet.payload_packet_len = 0; @@ -3615,7 +3633,7 @@ static int ndpi_init_packet_header(struct ndpi_detection_module_struct *ndpi_str flow->packet.l4_protocol = l4protocol; flow->packet.l4_packet_len = l4len; flow->l4_proto = l4protocol; - + /* tcp / udp detection */ if(l4protocol == IPPROTO_TCP && flow->packet.l4_packet_len >= 20 /* min size of tcp */ ) { /* tcp */ @@ -3869,7 +3887,7 @@ void check_ndpi_udp_flow_func(struct ndpi_detection_module_struct *ndpi_struct, && NDPI_BITMASK_COMPARE(ndpi_struct->callback_buffer_udp[a].detection_bitmask, detection_bitmask) != 0) { ndpi_struct->callback_buffer_udp[a].func(ndpi_struct, flow); - + // NDPI_LOG_DBG(ndpi_struct, "[UDP,CALL] dissector of protocol as callback_buffer idx = %d\n",a); if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) break; /* Stop after detecting the first protocol */ @@ -4053,8 +4071,14 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st if(flow == NULL) return(ret); - else - ret.category = flow->category; + + /* Init defaults */ + ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; + ret.category = flow->category; + + /* Ensure that we don't change our mind if detection is already complete */ + if((ret.master_protocol != NDPI_PROTOCOL_UNKNOWN) && (ret.app_protocol != NDPI_PROTOCOL_UNKNOWN)) + return(ret); /* TODO: add the remaining stage_XXXX protocols */ if(flow->detected_protocol_stack[0] == NDPI_PROTOCOL_UNKNOWN) { @@ -4064,7 +4088,7 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st 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_VOICE)) + || (flow->guessed_protocol_id == NDPI_PROTOCOL_WHATSAPP_CALL)) ndpi_set_detected_protocol(ndpi_struct, flow, flow->guessed_protocol_id, NDPI_PROTOCOL_UNKNOWN); else if((flow->l4.tcp.tls_seen_client_cert == 1) && (flow->protos.stun_ssl.ssl.client_certificate[0] != '\0')) { @@ -4140,13 +4164,9 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st check_stun_export: if(flow->protos.stun_ssl.stun.num_processed_pkts || flow->protos.stun_ssl.stun.num_udp_pkts) { // if(/* (flow->protos.stun_ssl.stun.num_processed_pkts >= NDPI_MIN_NUM_STUN_DETECTION) */ - if(flow->protos.stun_ssl.stun.num_processed_pkts && flow->protos.stun_ssl.stun.is_skype) { - ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_SKYPE_CALL, NDPI_PROTOCOL_SKYPE); - } else { - ndpi_set_detected_protocol(ndpi_struct, flow, - flow->guessed_host_protocol_id, - NDPI_PROTOCOL_STUN); - } + ndpi_set_detected_protocol(ndpi_struct, flow, + flow->guessed_host_protocol_id, + NDPI_PROTOCOL_STUN); } } @@ -4473,6 +4493,44 @@ void ndpi_fill_protocol_category(struct ndpi_detection_module_struct *ndpi_struc /* ********************************************************************************* */ +static void ndpi_reset_packet_line_info(struct ndpi_packet_struct *packet) { + packet->parsed_lines = 0, + packet->empty_line_position_set = 0, + packet->host_line.ptr = NULL, + packet->host_line.len = 0, + packet->referer_line.ptr = NULL, + packet->referer_line.len = 0, + packet->content_line.ptr = NULL, + packet->content_line.len = 0, + packet->accept_line.ptr = NULL, + packet->accept_line.len = 0, + packet->user_agent_line.ptr = NULL, + packet->user_agent_line.len = 0, + packet->http_url_name.ptr = NULL, + packet->http_url_name.len = 0, + packet->http_encoding.ptr = NULL, + packet->http_encoding.len = 0, + packet->http_transfer_encoding.ptr = NULL, + packet->http_transfer_encoding.len = 0, + packet->http_contentlen.ptr = NULL, + packet->http_contentlen.len = 0, + packet->http_cookie.ptr = NULL, + packet->http_cookie.len = 0, + packet->http_origin.len = 0, + packet->http_origin.ptr = NULL, + packet->http_x_session_type.ptr = NULL, + packet->http_x_session_type.len = 0, + packet->server_line.ptr = NULL, + packet->server_line.len = 0, + packet->http_method.ptr = NULL, + packet->http_method.len = 0, + packet->http_response.ptr = NULL, + packet->http_response.len = 0, + packet->http_num_headers = 0; +} + +/* ********************************************************************************* */ + ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, const unsigned char *packet, @@ -4497,7 +4555,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct /* Init default */ ret.master_protocol = flow->detected_protocol_stack[1], ret.app_protocol = flow->detected_protocol_stack[0]; - + if(flow->server_id == NULL) flow->server_id = dst; /* Default */ if(flow->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) { /* @@ -4510,7 +4568,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct */ ) { ndpi_process_extra_packet(ndpi_struct, flow, packet, packetlen, current_tick_l, src, dst); - + return(ret); } else goto ret_protocols; @@ -4689,8 +4747,12 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct } else ret.app_protocol = flow->detected_protocol_stack[0]; - ndpi_fill_protocol_category(ndpi_struct, flow, &ret); - + /* Don;t overwrite the category if already set */ + if(flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) + ndpi_fill_protocol_category(ndpi_struct, flow, &ret); + else + ret.category = flow->category; + if((flow->num_processed_pkts == 1) && (ret.master_protocol == NDPI_PROTOCOL_UNKNOWN) && (ret.app_protocol == NDPI_PROTOCOL_UNKNOWN) @@ -4714,7 +4776,8 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct Invalidate packet memory to avoid accessing the pointers below when the packet is no longer accessible */ - flow->packet.iph = NULL, flow->packet.tcp = NULL, flow->packet.udp = NULL; + flow->packet.iph = NULL, flow->packet.tcp = NULL, flow->packet.udp = NULL, flow->packet.payload = NULL; + ndpi_reset_packet_line_info(&flow->packet); return(ret); } @@ -4877,39 +4940,7 @@ void ndpi_parse_packet_line_info(struct ndpi_detection_module_struct *ndpi_struc return; packet->packet_lines_parsed_complete = 1; - packet->parsed_lines = 0; - packet->empty_line_position_set = 0; - packet->host_line.ptr = NULL; - packet->host_line.len = 0; - packet->referer_line.ptr = NULL; - packet->referer_line.len = 0; - packet->content_line.ptr = NULL; - packet->content_line.len = 0; - packet->accept_line.ptr = NULL; - packet->accept_line.len = 0; - packet->user_agent_line.ptr = NULL; - packet->user_agent_line.len = 0; - packet->http_url_name.ptr = NULL; - packet->http_url_name.len = 0; - packet->http_encoding.ptr = NULL; - packet->http_encoding.len = 0; - packet->http_transfer_encoding.ptr = NULL; - packet->http_transfer_encoding.len = 0; - packet->http_contentlen.ptr = NULL; - packet->http_contentlen.len = 0; - packet->http_cookie.ptr = NULL; - packet->http_cookie.len = 0; - packet->http_origin.len = 0; - packet->http_origin.ptr = NULL; - packet->http_x_session_type.ptr = NULL; - packet->http_x_session_type.len = 0; - packet->server_line.ptr = NULL; - packet->server_line.len = 0; - packet->http_method.ptr = NULL; - packet->http_method.len = 0; - packet->http_response.ptr = NULL; - packet->http_response.len = 0; - packet->http_num_headers=0; + ndpi_reset_packet_line_info(packet); if((packet->payload_packet_len < 3) || (packet->payload == NULL)) @@ -5875,8 +5906,13 @@ int ndpi_get_category_id(struct ndpi_detection_module_struct *ndpi_mod, char *ca void ndpi_dump_protocols(struct ndpi_detection_module_struct *ndpi_mod) { int i; + for(i=0; i<(int)ndpi_mod->ndpi_num_supported_protocols; i++) - printf("[%3d] %s\n", i, ndpi_mod->proto_defaults[i].protoName); + printf("%3d %-22s %-12s %s\n", i, + ndpi_mod->proto_defaults[i].protoName, + ndpi_get_proto_breed_name(ndpi_mod, ndpi_mod->proto_defaults[i].protoBreed), + ndpi_category_get_name(ndpi_mod, ndpi_mod->proto_defaults[i].protoCategory) + ); } /* ****************************************************** */ @@ -6110,6 +6146,13 @@ int ndpi_match_bigram(struct ndpi_detection_module_struct *ndpi_struct, rc = ac_automata_search(((AC_AUTOMATA_t*)automa->ac_automa), &ac_input_text, &match); ac_automata_reset(((AC_AUTOMATA_t*)automa->ac_automa)); + /* + As ac_automata_search can detect partial matches and continue the search process + in case rc == 0 (i.e. no match), we need to check if there is a partial match + and in this case return it + */ + if((rc == 0) && (match.number != 0)) rc = 1; + return(rc ? match.number : 0); } @@ -6124,7 +6167,7 @@ void ndpi_free_flow(struct ndpi_flow_struct *flow) { if(flow->l4.tcp.tls_srv_cert_fingerprint_ctx) ndpi_free(flow->l4.tcp.tls_srv_cert_fingerprint_ctx); } - + ndpi_free(flow); } } @@ -6283,4 +6326,43 @@ int ndpi_flowv6_flow_hash(u_int8_t l4_proto, struct ndpi_in6_addr *src_ip, struc return(0); /* OK */ } -/* **************************************** */ +/* ******************************************************************** */ + +/* + This function tells if it's possible to further dissect a given flow + 0 - All possible dissection has been completed + 1 - Additional dissection is possible +*/ +u_int8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow) { + +#if 0 + printf("[DEBUG] %s(%u.%u)\n", __FUNCTION__, + flow->detected_protocol_stack[0], + flow->detected_protocol_stack[1]); +#endif + + if(flow->check_extra_packets) return(1); + + switch(flow->detected_protocol_stack[0]) { + case NDPI_PROTOCOL_TLS: + if(!flow->l4.tcp.tls_srv_cert_fingerprint_processed) + return(1); + break; + + case NDPI_PROTOCOL_HTTP: + if(flow->host_server_name[0] == '\0') + return(1); + break; + + case NDPI_PROTOCOL_DNS: + if((ndpi_struct->dns_dont_dissect_response == 0) + && (flow->host_server_name[0] == '\0')) + return(1); + break; + } + + return(0); +} + +/* ******************************************************************** */ |