aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Deri <deri@ntop.org>2019-10-11 18:19:50 +0200
committerLuca Deri <deri@ntop.org>2019-10-11 18:19:50 +0200
commit6a38ede42be3006782267d6d1bfabc56f8caa738 (patch)
treefc52fef2c05f93b792367b13ad00cdd69ac9c5cc
parent206ce0a317c63c61655b4b2dbce94b1dcdb8f965 (diff)
Updated nDPI API ndpi_ssl_version2str ndpi_get_l4_proto_name
-rw-r--r--example/ndpiReader.c73
-rw-r--r--example/reader_util.c17
-rw-r--r--src/include/ndpi_api.h30
-rw-r--r--src/include/ndpi_typedefs.h11
-rw-r--r--src/lib/ndpi_main.c219
-rw-r--r--src/lib/ndpi_utils.c16
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);
}