diff options
author | Luca Deri <deri@ntop.org> | 2019-10-11 18:19:50 +0200 |
---|---|---|
committer | Luca Deri <deri@ntop.org> | 2019-10-11 18:19:50 +0200 |
commit | 6a38ede42be3006782267d6d1bfabc56f8caa738 (patch) | |
tree | fc52fef2c05f93b792367b13ad00cdd69ac9c5cc | |
parent | 206ce0a317c63c61655b4b2dbce94b1dcdb8f965 (diff) |
Updated nDPI API ndpi_ssl_version2str ndpi_get_l4_proto_name
-rw-r--r-- | example/ndpiReader.c | 73 | ||||
-rw-r--r-- | example/reader_util.c | 17 | ||||
-rw-r--r-- | src/include/ndpi_api.h | 30 | ||||
-rw-r--r-- | src/include/ndpi_typedefs.h | 11 | ||||
-rw-r--r-- | src/lib/ndpi_main.c | 219 | ||||
-rw-r--r-- | src/lib/ndpi_utils.c | 16 |
6 files changed, 244 insertions, 122 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c index 2a1bbd8bb..0c0c2c8a6 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -412,9 +412,15 @@ static void help(u_int long_help) { #endif if(long_help) { + NDPI_PROTOCOL_BITMASK all; + printf("\n\nnDPI supported protocols:\n"); - printf("%3s %-22s %-12s %s\n", "Id", "Protocol", "Breed", "Category"); + printf("%3s %-22s %-8s %-12s %s\n", "Id", "Protocol", "Layer_4", "Breed", "Category"); num_threads = 1; + + NDPI_BITMASK_SET_ALL(all); + ndpi_set_protocol_detection_bitmask2(ndpi_info_mod, &all); + ndpi_dump_protocols(ndpi_info_mod); } exit(!long_help); @@ -1000,12 +1006,13 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa json_object *jObj; #endif FILE *out = results_file ? results_file : stdout; - + u_int8_t known_tls; + if(csv_fp != NULL) { char buf[32]; float data_ratio = ndpi_data_ratio(flow->src2dst_bytes, flow->dst2src_bytes); float f = (float)flow->first_seen, l = (float)flow->last_seen; - + /* PLEASE KEEP IN SYNC WITH printCSVHeader() */ fprintf(csv_fp, "%u,%u,%.3f,%.3f,%s,%u,%s,%u,", @@ -1043,7 +1050,7 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa (flow->ssh_tls.server_info[0] != '\0') ? flow->ssh_tls.server_info : ""); fprintf(csv_fp, "%s,%s,%s,", - (flow->ssh_tls.ssl_version != 0) ? ndpi_ssl_version2str(flow->ssh_tls.ssl_version) : "", + (flow->ssh_tls.ssl_version != 0) ? ndpi_ssl_version2str(flow->ssh_tls.ssl_version, &known_tls) : "", (flow->ssh_tls.ja3_client[0] != '\0') ? flow->ssh_tls.ja3_client : "", (flow->ssh_tls.ja3_client[0] != '\0') ? is_unsafe_cipher(flow->ssh_tls.client_unsafe_cipher) : ""); @@ -1140,7 +1147,7 @@ static void printFlow(u_int16_t id, struct ndpi_flow_info *flow, u_int16_t threa fprintf(out, "[URL: %s][StatusCode: %u]", flow->http.url, flow->http.response_status_code); - if(flow->ssh_tls.ssl_version != 0) fprintf(out, "[%s]", ndpi_ssl_version2str(flow->ssh_tls.ssl_version)); + if(flow->ssh_tls.ssl_version != 0) fprintf(out, "[%s]", ndpi_ssl_version2str(flow->ssh_tls.ssl_version, &known_tls)); if(flow->ssh_tls.client_info[0] != '\0') fprintf(out, "[Client: %s]", flow->ssh_tls.client_info); if(flow->ssh_tls.client_hassh[0] != '\0') fprintf(out, "[HASSH-C: %s]", flow->ssh_tls.client_hassh); @@ -1304,9 +1311,13 @@ static void node_proto_guess_walker(const void *node, ndpi_VISIT which, int dept u_int16_t thread_id = *((u_int16_t *) user_data); if((which == ndpi_preorder) || (which == ndpi_leaf)) { /* Avoid walking the same node multiple times */ - if((!flow->detection_completed) && flow->ndpi_flow) - flow->detected_protocol = ndpi_detection_giveup(ndpi_thread_info[0].workflow->ndpi_struct, flow->ndpi_flow, enable_protocol_guess); - + if((!flow->detection_completed) && flow->ndpi_flow) { + u_int8_t proto_guessed; + + flow->detected_protocol = ndpi_detection_giveup(ndpi_thread_info[0].workflow->ndpi_struct, + flow->ndpi_flow, enable_protocol_guess, &proto_guessed); + } + process_ndpi_collected_info(ndpi_thread_info[thread_id].workflow, flow); ndpi_thread_info[thread_id].workflow->stats.protocol_counter[flow->detected_protocol.app_protocol] += flow->src2dst_packets + flow->dst2src_packets; @@ -1873,50 +1884,8 @@ static void setupDetection(u_int16_t thread_id, pcap_t * pcap_handle) { if(_protoFilePath != NULL) ndpi_load_protocols_file(ndpi_thread_info[thread_id].workflow->ndpi_struct, _protoFilePath); - if(_customCategoryFilePath) { - FILE *fd = fopen(_customCategoryFilePath, "r"); - - if(fd) { - while(fd) { - char buffer[512], *line, *name, *category; - int i; - - if(!(line = fgets(buffer, sizeof(buffer), fd))) - break; - - if(((i = strlen(line)) <= 1) || (line[0] == '#')) - continue; - else - line[i-1] = '\0'; - - name = strtok(line, "\t"); - if(name) { - category = strtok(NULL, "\t"); - - if(category) { - int fields[4]; - - - if(verbose && !quiet_mode) printf("[Category] Loading %s\t%s\n", name, category); - - if(sscanf(name, "%d.%d.%d.%d", &fields[0], &fields[1], &fields[2], &fields[3]) == 4) - ndpi_load_ip_category(ndpi_thread_info[thread_id].workflow->ndpi_struct, - name, (ndpi_protocol_category_t)atoi(category)); - else { - /* TODO free the strdup */ - ndpi_load_hostname_category(ndpi_thread_info[thread_id].workflow->ndpi_struct, - strdup(name), (ndpi_protocol_category_t)atoi(category)); - } - } - } - } - - ndpi_enable_loaded_categories(ndpi_thread_info[thread_id].workflow->ndpi_struct); - } else - printf("ERROR: Unable to read file %s\n", _customCategoryFilePath); - - fclose(fd); - } + if(_customCategoryFilePath) + ndpi_load_categories_file(ndpi_thread_info[thread_id].workflow->ndpi_struct, _customCategoryFilePath); } /* *********************************************** */ diff --git a/example/reader_util.c b/example/reader_util.c index 4859d69e5..8848f6f05 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -966,6 +966,14 @@ void process_ndpi_collected_info(struct ndpi_workflow * workflow, struct ndpi_fl else if(flow->detected_protocol.app_protocol == NDPI_PROTOCOL_UBNTAC2) { snprintf(flow->info, sizeof(flow->info), "%s", flow->ndpi_flow->protos.ubntac2.version); } + /* KERBEROS */ + else if(flow->detected_protocol.app_protocol == NDPI_PROTOCOL_KERBEROS) { + if(flow->ndpi_flow->protos.kerberos.cname[0] != '\0') { + snprintf(flow->info, sizeof(flow->info), "%s (%s)", + flow->ndpi_flow->protos.kerberos.cname, + flow->ndpi_flow->protos.kerberos.realm); + } + } /* HTTP */ else if(flow->detected_protocol.master_protocol == NDPI_PROTOCOL_HTTP) { if(flow->ndpi_flow->http.url != NULL) { @@ -1230,10 +1238,13 @@ static struct ndpi_proto packet_processing(struct ndpi_workflow * workflow, if(ndpi_flow && ndpi_flow->check_extra_packets) flow->check_extra_packets = 1; - if(flow->detected_protocol.app_protocol == NDPI_PROTOCOL_UNKNOWN) + if(flow->detected_protocol.app_protocol == NDPI_PROTOCOL_UNKNOWN) { + u_int8_t proto_guessed; + flow->detected_protocol = ndpi_detection_giveup(workflow->ndpi_struct, flow->ndpi_flow, - enable_protocol_guess); - + enable_protocol_guess, &proto_guessed); + } + process_ndpi_collected_info(workflow, flow); } } diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h index 6bf2d5779..3c30f1f69 100644 --- a/src/include/ndpi_api.h +++ b/src/include/ndpi_api.h @@ -225,12 +225,14 @@ extern "C" { * @par ndpi_struct = the detection module * @par flow = the flow given for the detection module * @par enable_guess = guess protocol if unknown + * @par protocol_was_guessed = 1 if the protocol was guesses (requires enable_guess = 1), 0 otherwise * @return the detected protocol even if the flow is not completed; * */ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow, - u_int8_t enable_guess); + u_int8_t enable_guess, + u_int8_t *protocol_was_guessed); /** * Processes an extra packet in order to get more information for a given protocol @@ -613,6 +615,16 @@ extern "C" { int ndpi_load_protocols_file(struct ndpi_detection_module_struct *ndpi_mod, const char* path); + /** + * Read a file and load the categories + * + * @par ndpi_mod = the detection module + * @par path = the path of the file + * @return 0 if the file is loaded correctly; + * -1 else + */ + int ndpi_load_categories_file(struct ndpi_detection_module_struct *ndpi_str, const char* path); + /** * Get the total number of the supported protocols * @@ -744,10 +756,12 @@ extern "C" { */ int ndpi_match_string(void *_automa, char *string_to_match); - void ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_struct, - char *ip_address_and_mask, ndpi_protocol_category_t category); + int ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_struct, + const char *ip_address_and_mask, ndpi_protocol_category_t category); int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_struct, - char *name, ndpi_protocol_category_t category); + const char *name_to_add, ndpi_protocol_category_t category); + int ndpi_load_category(struct ndpi_detection_module_struct *ndpi_struct, + const char *ip_or_name, ndpi_protocol_category_t category); int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_struct); int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t saddr, @@ -759,11 +773,15 @@ extern "C" { struct ndpi_flow_struct *flow, ndpi_protocol *ret); int ndpi_get_custom_category_match(struct ndpi_detection_module_struct *ndpi_struct, - char *name_or_ip, u_int name_len, unsigned long *id); + char *name_or_ip, u_int name_len, unsigned long *id); int ndpi_set_detection_preferences(struct ndpi_detection_module_struct *ndpi_mod, ndpi_detection_preference pref, int value); + /* Tells to called on what l4 protocol given application protocol can be found */ + ndpi_l4_proto_info ndpi_get_l4_proto_info(struct ndpi_detection_module_struct *ndpi_struct, u_int16_t ndpi_proto_id); + const char* ndpi_get_l4_proto_name(ndpi_l4_proto_info proto); + ndpi_proto_defaults_t* ndpi_get_proto_defaults(struct ndpi_detection_module_struct *ndpi_mod); u_int ndpi_get_ndpi_num_supported_protocols(struct ndpi_detection_module_struct *ndpi_mod); u_int ndpi_get_ndpi_num_custom_protocols(struct ndpi_detection_module_struct *ndpi_mod); @@ -817,7 +835,7 @@ extern "C" { char *buffer, u_int buffer_size, u_int8_t min_string_match_len, /* Will return 0 if no string > min_string_match_len have been found */ char *outbuf, u_int outbuf_len); - char* ndpi_ssl_version2str(u_int16_t version); + char* ndpi_ssl_version2str(u_int16_t version, u_int8_t *unknown_tls_version); /* Serializer */ int ndpi_init_serializer_ll(ndpi_serializer *serializer, ndpi_serialization_format fmt, diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h index 486213269..4366df5c1 100644 --- a/src/include/ndpi_typedefs.h +++ b/src/include/ndpi_typedefs.h @@ -35,6 +35,13 @@ typedef enum { NDPI_LOG_DEBUG_EXTRA } ndpi_log_level_t; +typedef enum { + ndpi_l4_proto_unknown = 0, + ndpi_l4_proto_tcp_only, + ndpi_l4_proto_udp_only, + ndpi_l4_proto_tcp_and_udp, +} ndpi_l4_proto_info; + /* NDPI_VISIT */ typedef enum { ndpi_preorder, @@ -1183,6 +1190,10 @@ struct ndpi_flow_struct { } ntp; struct { + char cname[24], realm[24]; + } kerberos; + + struct { struct { u_int16_t ssl_version; char client_certificate[64], server_certificate[64], server_organization[64]; diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c index 61fbbcd07..a72917b7f 100644 --- a/src/lib/ndpi_main.c +++ b/src/lib/ndpi_main.c @@ -368,7 +368,7 @@ static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_str, for(port=range->port_low; port<=range->port_high; port++) { ndpi_default_ports_tree_node_t *node = (ndpi_default_ports_tree_node_t*)ndpi_malloc(sizeof(ndpi_default_ports_tree_node_t)); ndpi_default_ports_tree_node_t *ret; - + if(!node) { NDPI_LOG_ERR(ndpi_str, "%s:%d not enough memory\n", _func, _line); break; @@ -404,7 +404,7 @@ static int removeDefaultPort(ndpi_port_range *range, for(port=range->port_low; port<=range->port_high; port++) { ndpi_default_ports_tree_node_t *ret; - + node.proto = def, node.default_port = port; ret = (ndpi_default_ports_tree_node_t*)ndpi_tdelete(&node, (void*)root, ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */ @@ -2411,10 +2411,10 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) { free_hyperscan_memory(ndpi_str->custom_categories.hostnames); #else if(ndpi_str->custom_categories.hostnames.ac_automa != NULL) - ac_automata_release((AC_AUTOMATA_t*)ndpi_str->custom_categories.hostnames.ac_automa, 0); + ac_automata_release((AC_AUTOMATA_t*)ndpi_str->custom_categories.hostnames.ac_automa, 1 /* free patterns strings memory */); if(ndpi_str->custom_categories.hostnames_shadow.ac_automa != NULL) - ac_automata_release((AC_AUTOMATA_t*)ndpi_str->custom_categories.hostnames_shadow.ac_automa, 0); + ac_automata_release((AC_AUTOMATA_t*)ndpi_str->custom_categories.hostnames_shadow.ac_automa, 1 /* free patterns strings memory */); #endif if(ndpi_str->custom_categories.ipAddresses != NULL) @@ -2455,7 +2455,7 @@ static ndpi_default_ports_tree_node_t* ndpi_get_guessed_protocol_id(struct ndpi_ int low = ndpi_min(sport, dport); int high = ndpi_max(sport, dport); const void *ret; - + node.default_port = low; /* Check server port first */ ret = ndpi_tfind(&node, (proto == IPPROTO_TCP) ? (void*)&ndpi_str->tcpRoot : (void*)&ndpi_str->udpRoot, @@ -2698,6 +2698,57 @@ int ndpi_handle_rule(struct ndpi_detection_module_struct *ndpi_str, /* ******************************************************************** */ /* + * Format: + * + * <host|ip> <category_id> + * + * Notes: + * - host and category are separated by a single TAB + * - empty lines or lines starting with # are ignored + */ +int ndpi_load_categories_file(struct ndpi_detection_module_struct *ndpi_str, const char* path) { + char buffer[512], *line, *name, *category, *saveptr; + FILE *fd; + int len; + + fd = fopen(path, "r"); + + if(fd == NULL) { + NDPI_LOG_ERR(ndpi_str, "Unable to open file %s [%s]\n", path, strerror(errno)); + return(-1); + } + + while(fd) { + line = fgets(buffer, sizeof(buffer), fd); + + if(line == NULL) + break; + + len = strlen(line); + + if((len <= 1) || (line[0] == '#')) + continue; + + line[len-1] = '\0'; + name = strtok_r(line, "\t", &saveptr); + + if(name) { + category = strtok_r(NULL, "\t", &saveptr); + + if(category) + ndpi_load_category(ndpi_str, name, (ndpi_protocol_category_t) atoi(category)); + } + } + + fclose(fd); + ndpi_enable_loaded_categories(ndpi_str); + + return(0); +} + +/* ******************************************************************** */ + +/* Format: <tcp|udp>:<port>,<tcp|udp>:<port>,.....@<proto> @@ -3374,8 +3425,7 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n for(a = 0; a < ndpi_str->callback_buffer_size; a++) { if((ndpi_str->callback_buffer[a].ndpi_selection_bitmask & (NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP | NDPI_SELECTION_BITMASK_PROTOCOL_INT_UDP | - NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP)) - == 0 + NDPI_SELECTION_BITMASK_PROTOCOL_INT_TCP_OR_UDP)) == 0 || (ndpi_str-> callback_buffer[a].ndpi_selection_bitmask & NDPI_SELECTION_BITMASK_PROTOCOL_COMPLETE_TRAFFIC) != 0) { if(_ndpi_debug_callbacks) NDPI_LOG_DBG2(ndpi_str, @@ -4049,9 +4099,13 @@ ndpi_protocol ndpi_get_partial_detection(struct ndpi_detection_module_struct *nd /* ********************************************************************************* */ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_str, - struct ndpi_flow_struct *flow, u_int8_t enable_guess) { + 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; + if(flow == NULL) return(ret); @@ -4115,7 +4169,6 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st && (flow->protos.stun_ssl.stun.num_processed_pkts > 0)) guessed_protocol_id = NDPI_PROTOCOL_STUN; - if(flow->host_server_name[0] != '\0') { ndpi_protocol_match_result ret_match; @@ -4172,7 +4225,7 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st && (ret.app_protocol == NDPI_PROTOCOL_UNKNOWN) && flow->packet.iph /* Guess only IPv4 */ && (flow->packet.tcp || flow->packet.udp) - ) + ) { ret = ndpi_guess_undetected_protocol(ndpi_str, flow, flow->packet.l4_protocol, @@ -4181,7 +4234,9 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st ntohl(flow->packet.iph->daddr), ntohs(flow->packet.udp ? flow->packet.udp->dest : flow->packet.tcp->dest) ); - + *protocol_was_guessed = 1; + } + ndpi_fill_protocol_category(ndpi_str, flow, &ret); return(ret); @@ -4232,8 +4287,8 @@ void ndpi_process_extra_packet(struct ndpi_detection_module_struct *ndpi_str, /* ********************************************************************************* */ -void ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_str, - char *ip_address_and_mask, ndpi_protocol_category_t category) { +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; @@ -4253,26 +4308,25 @@ void ndpi_load_ip_category(struct ndpi_detection_module_struct *ndpi_str, if(inet_pton(AF_INET, ipbuf, &pin) != 1) { NDPI_LOG_DBG2(ndpi_str, "Invalid ip/ip+netmask: %s\n", ip_address_and_mask); - return; + return(-1); } if((node = add_to_ptree(ndpi_str->custom_categories.ipAddresses_shadow, AF_INET, &pin, bits)) != NULL) node->value.user_value = (int)category; + return(0); } /* ********************************************************************************* */ -/* - * - * IMPORTANT - * - * The *name pointer MUST be kept allocated until the automa is finalized and it - * cannot be recycled across multiple ndpi_load_hostname_category() calls - * - */ int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_str, - char *name, ndpi_protocol_category_t category) { + const char *name_to_add, ndpi_protocol_category_t category) { + char *name; + + if(name_to_add == NULL) + return(-1); + + name = ndpi_strdup(name_to_add); if(name == NULL) return(-1); @@ -4286,30 +4340,32 @@ int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_str, struct hs_list *h = (struct hs_list*)ndpi_malloc(sizeof(struct hs_list)); if(h) { - h->expression = ndpi_strdup(name), h->id = (unsigned int)category; - if(h->expression == NULL) { - ndpi_free(h); - return(-2); - } - + h->expression = name, h->id = (unsigned int)category; h->next = ndpi_str->custom_categories.to_load; ndpi_str->custom_categories.to_load = h; ndpi_str->custom_categories.num_to_load++; - } else - return(-1); + } else { + free(name); + return(-1); + } } #else AC_PATTERN_t ac_pattern; memset(&ac_pattern, 0, sizeof(ac_pattern)); - if(ndpi_str->custom_categories.hostnames_shadow.ac_automa == NULL) + if(ndpi_str->custom_categories.hostnames_shadow.ac_automa == NULL) { + free(name); return(-1); + } ac_pattern.astring = name, ac_pattern.length = strlen(ac_pattern.astring); ac_pattern.rep.number = (int)category; - ac_automata_add(ndpi_str->custom_categories.hostnames_shadow.ac_automa, &ac_pattern); + if(ac_automata_add(ndpi_str->custom_categories.hostnames_shadow.ac_automa, &ac_pattern) != ACERR_SUCCESS) { + free(name); + return(-1); + } #endif return(0); @@ -4317,21 +4373,30 @@ int ndpi_load_hostname_category(struct ndpi_detection_module_struct *ndpi_str, /* ********************************************************************************* */ +/* 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); + + 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, ip_addr[4]; + int i; /* First add the nDPI known categories matches */ - for(i=0; category_match[i].string_to_match != NULL; i++) { - if(sscanf(category_match[i].string_to_match, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3]) == 4){ - ndpi_load_ip_category(ndpi_str, - category_match[i].string_to_match, - category_match[i].protocol_category); - } else{ - ndpi_load_hostname_category(ndpi_str, - category_match[i].string_to_match, - category_match[i].protocol_category); - } - } + 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); #ifdef HAVE_HYPERSCAN if(ndpi_str->custom_categories.num_to_load > 0) { @@ -4398,7 +4463,7 @@ int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_str) } #else /* Free */ - ac_automata_release((AC_AUTOMATA_t*)ndpi_str->custom_categories.hostnames.ac_automa, 0); + ac_automata_release((AC_AUTOMATA_t*)ndpi_str->custom_categories.hostnames.ac_automa, 1 /* free patterns strings memory */); /* Finalize */ ac_automata_finalize((AC_AUTOMATA_t*)ndpi_str->custom_categories.hostnames_shadow.ac_automa); @@ -4440,7 +4505,7 @@ int ndpi_fill_ip_protocol_category(struct ndpi_detection_module_struct *ndpi_str 32, ((patricia_tree_t*)ndpi_str->protocols_ptree)->maxbits); node = ndpi_patricia_search_best(ndpi_str->custom_categories.ipAddresses, &prefix); } - + if(!node) { if(daddr != 0) fill_prefix_v4(&prefix, (struct in_addr *)&daddr, @@ -4673,8 +4738,10 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct 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; + /* ret.master_protocol = flow->guessed_protocol_id , ret.app_protocol = flow->guessed_host_protocol_id; /\* ****** *\/ */ - ret = ndpi_detection_giveup(ndpi_str, flow, 0); + ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed); } ndpi_fill_protocol_category(ndpi_str, flow, &ret); @@ -4767,6 +4834,8 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct && (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 @@ -4775,7 +4844,7 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct We don't see how future packets can match anything hence we giveup here */ - ret = ndpi_detection_giveup(ndpi_str, flow, 0); + ret = ndpi_detection_giveup(ndpi_str, flow, 0, &protocol_was_guessed); } invalidate_ptr: @@ -5906,7 +5975,7 @@ int ndpi_get_category_id(struct ndpi_detection_module_struct *ndpi_str, char *ca for(i = 0; i < NDPI_PROTOCOL_NUM_CATEGORIES; i++) { const char *name = ndpi_category_get_name(ndpi_str, i); - + if(strcasecmp(cat, name) == 0) return(i); } @@ -5920,8 +5989,9 @@ 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 %-12s %s\n", 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) ); @@ -5941,7 +6011,7 @@ char* ndpi_strnstr(const char *s, const char *find, size_t slen) { len = strnlen(find, slen); do { char sc; - + do { if(slen-- < 1 || (sc = *s++) == '\0') return(NULL); @@ -5968,7 +6038,7 @@ char* ndpi_strncasestr(const char *s, const char *find, size_t slen) { len = strlen(find); do { char sc; - + do { if(slen-- < 1 || (sc = *s++) == '\0') return(NULL); @@ -6134,7 +6204,7 @@ u_int16_t ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_ if((flow->category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED) && (ret_match->protocol_category == NDPI_PROTOCOL_CATEGORY_UNSPECIFIED)) { unsigned long 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; @@ -6142,7 +6212,7 @@ u_int16_t ndpi_match_host_subprotocol(struct ndpi_detection_module_struct *ndpi_ } } } - + return(rc); } @@ -6403,3 +6473,42 @@ u_int8_t ndpi_extra_dissection_possible(struct ndpi_detection_module_struct *ndp } /* ******************************************************************** */ + +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_udp_only: + return("UDP"); + break; + + case ndpi_l4_proto_tcp_and_udp: + return("TCP/UDP"); + break; + } + + 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; + + 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 */ +} diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c index b8ffe2e17..de268c191 100644 --- a/src/lib/ndpi_utils.c +++ b/src/lib/ndpi_utils.c @@ -710,24 +710,28 @@ int ndpi_has_human_readeable_string(struct ndpi_detection_module_struct *ndpi_st /* ********************************** */ -char* ndpi_ssl_version2str(u_int16_t version) { - static char v[8]; +char* ndpi_ssl_version2str(u_int16_t version, u_int8_t *unknown_tls_version) { + static char v[12]; + *unknown_tls_version = 0; + switch(version) { case 0x0300: return("SSLv3"); case 0x0301: return("TLSv1"); case 0x0302: return("TLSv1.1"); case 0x0303: return("TLSv1.2"); case 0x0304: return("TLSv1.3"); - case 0xfb1a: return("TLSv1.3 (Fizz)"); /* https://engineering.fb.com/security/fizz/ */ - case 0xfeff: return("DTLSv1.0"); - case 0xfefd: return("DTLSv1.2"); + case 0XFB1A: return("TLSv1.3 (Fizz)"); /* https://engineering.fb.com/security/fizz/ */ + case 0XFEFF: return("DTLSv1.0"); + case 0XFEFD: return("DTLSv1.2"); } if((version >= 0x7f00) && (version <= 0x7fff)) return("TLSv1.3 (draft)"); - snprintf(v, sizeof(v), "%04X", version); + *unknown_tls_version = 1; + snprintf(v, sizeof(v), "TLS (%04X)", version); + return(v); } |