From ad6bfbad4d0b8ae6c0c6b2d58c68eee542110e8a Mon Sep 17 00:00:00 2001 From: Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> Date: Sun, 18 Dec 2022 09:10:57 +0100 Subject: Add protocol disabling feature (#1808) The application may enable only some protocols. Disabling a protocol means: *) don't register/use the protocol dissector code (if any) *) disable classification by-port for such a protocol *) disable string matchings for domains/certificates involving this protocol *) disable subprotocol registration (if any) This feature can be tested with `ndpiReader -B list_of_protocols_to_disable`. Custom protocols are always enabled. Technically speaking, this commit doesn't introduce any API/ABI incompatibility. However, calling `ndpi_set_protocol_detection_bitmask2()` is now mandatory, just after having called `ndpi_init_detection_module()`. Most of the diffs (and all the diffs in `/src/lib/protocols/`) are due to the removing of some function parameters. Fix the low level macro `NDPI_LOG`. This issue hasn't been detected sooner simply because almost all the code uses only the helpers `NDPI_LOG_*` --- example/ndpiReader.c | 26 ++++++++++++++++++++------ example/reader_util.c | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 50 insertions(+), 18 deletions(-) (limited to 'example') diff --git a/example/ndpiReader.c b/example/ndpiReader.c index e6b054c92..33ef020f4 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -95,6 +95,7 @@ u_int8_t enable_protocol_guess = 1, enable_payload_analyzer = 0, num_bin_cluster u_int8_t verbose = 0, enable_flow_stats = 0; int nDPI_LogLevel = 0; char *_debug_protocols = NULL; +char *_disabled_protocols = NULL; static u_int8_t stats_flag = 0; ndpi_init_prefs init_prefs = ndpi_no_prefs; u_int8_t human_readeable_string_len = 5; @@ -252,6 +253,7 @@ static int dpdk_port_id = 0, dpdk_run_capture = 1; void test_lib(); /* Forward */ extern void ndpi_report_payload_stats(); +extern int parse_proto_name_list(char *str, NDPI_PROTOCOL_BITMASK *bitmask, int inverted_logic); /* ********************************** */ @@ -449,7 +451,7 @@ static void help(u_int long_help) { " [-p ][-l [-q][-d][-h][-H][-D][-e ][-E][-t][-v ]\n" " [-n ][-w ][-c ][-C ][-j ][-x ]\n" " [-r ][-j ][-S ][-T ][-U ] [-x ][-z]\n" - " [-a ]\n\n" + " [-a ][-B proto_list]\n\n" "Usage:\n" " -i | Specify a pcap file/playlist to read packets from or a\n" " | device for live capture (comma-separated list)\n" @@ -504,6 +506,7 @@ static void help(u_int long_help) { " -u all|proto|num[,...] | Enable logging only for such protocol(s)\n" " | If this flag is present multiple times (directly, or via '-V'),\n" " | only the last instance will be considered\n" + " -B all|proto|num[,...] | Disable such protocol(s). By defaul all protocols are enabled\n" " -T | Max number of TCP processed packets before giving up [default: %u]\n" " -U | Max number of UDP processed packets before giving up [default: %u]\n" " -D | Enable DoH traffic analysis based on content (no DPI)\n" @@ -814,7 +817,7 @@ static void parseOptions(int argc, char **argv) { } #endif - while((opt = getopt_long(argc, argv, "a:Ab:e:Ec:C:dDf:g:i:Ij:k:K:S:hHp:pP:l:r:s:tu:v:V:n:rp:x:w:zq0123:456:7:89:m:MT:U:", + while((opt = getopt_long(argc, argv, "a:Ab:B:e:Ec:C:dDf:g:i:Ij:k:K:S:hHp:pP:l:r:s:tu:v:V:n:rp:x:w:zq0123:456:7:89:m:MT:U:", longopts, &option_idx)) != EOF) { #ifdef DEBUG_TRACE if(trace) fprintf(trace, " #### Handling option -%c [%s] #### \n", opt, optarg ? optarg : ""); @@ -941,6 +944,11 @@ static void parseOptions(int argc, char **argv) { _debug_protocols = ndpi_strdup(optarg); break; + case 'B': + ndpi_free(_disabled_protocols); + _disabled_protocols = ndpi_strdup(optarg); + break; + case 'h': help(0); break; @@ -2408,7 +2416,7 @@ static void debug_printf(u_int32_t protocol, void *id_struct, * @brief Setup for detection begin */ static void setupDetection(u_int16_t thread_id, pcap_t * pcap_handle) { - NDPI_PROTOCOL_BITMASK all; + NDPI_PROTOCOL_BITMASK enabled_bitmask; struct ndpi_workflow_prefs prefs; memset(&prefs, 0, sizeof(prefs)); @@ -2427,9 +2435,14 @@ static void setupDetection(u_int16_t thread_id, pcap_t * pcap_handle) { on_protocol_discovered, (void *)(uintptr_t)thread_id); - // enable all protocols - NDPI_BITMASK_SET_ALL(all); - ndpi_set_protocol_detection_bitmask2(ndpi_thread_info[thread_id].workflow->ndpi_struct, &all); + /* Protocols to enable/disable. Default: everything is enabled */ + NDPI_BITMASK_SET_ALL(enabled_bitmask); + if(_disabled_protocols != NULL) { + if(parse_proto_name_list(_disabled_protocols, &enabled_bitmask, 1)) + exit(-1); + } + + ndpi_set_protocol_detection_bitmask2(ndpi_thread_info[thread_id].workflow->ndpi_struct, &enabled_bitmask); // clear memory for results memset(ndpi_thread_info[thread_id].workflow->stats.protocol_counter, 0, @@ -5190,6 +5203,7 @@ void zscoreUnitTest() { ndpi_free_bin(&malloc_bins); if(csv_fp) fclose(csv_fp); ndpi_free(_debug_protocols); + ndpi_free(_disabled_protocols); #ifdef DEBUG_TRACE if(trace) fclose(trace); diff --git a/example/reader_util.c b/example/reader_util.c index 2e285a7f1..67b27f70b 100644 --- a/example/reader_util.c +++ b/example/reader_util.c @@ -373,50 +373,67 @@ static uint16_t ndpi_get_proto_id(struct ndpi_detection_module_struct *ndpi_mod, /* ***************************************************** */ -static NDPI_PROTOCOL_BITMASK debug_bitmask; static char _proto_delim[] = " \t,:;"; -static int parse_debug_proto(struct ndpi_detection_module_struct *ndpi_mod, char *str) { +int parse_proto_name_list(char *str, NDPI_PROTOCOL_BITMASK *bitmask, int inverted_logic) { char *n; uint16_t proto; - char op=1; + char op; + struct ndpi_detection_module_struct *module; + NDPI_PROTOCOL_BITMASK all; + + if(!inverted_logic) + op = 1; /* Default action: add to the bitmask */ + else + op = 0; /* Default action: remove from the bitmask */ + /* Use a temporary module with all protocols enabled */ + module = ndpi_init_detection_module(0); + if(!module) + return 1; + NDPI_BITMASK_SET_ALL(all); + ndpi_set_protocol_detection_bitmask2(module, &all); + ndpi_finalize_initialization(module); + for(n = strtok(str,_proto_delim); n && *n; n = strtok(NULL,_proto_delim)) { if(*n == '-') { - op = 0; + op = !inverted_logic ? 0 : 1; n++; } else if(*n == '+') { - op = 1; + op = !inverted_logic ? 1 : 0; n++; } if(!strcmp(n,"all")) { if(op) - NDPI_BITMASK_SET_ALL(debug_bitmask); + NDPI_BITMASK_SET_ALL(*bitmask); else - NDPI_BITMASK_RESET(debug_bitmask); + NDPI_BITMASK_RESET(*bitmask); continue; } - proto = ndpi_get_proto_id(ndpi_mod, n); + proto = ndpi_get_proto_id(module, n); if(proto == NDPI_PROTOCOL_UNKNOWN && strcmp(n,"unknown") && strcmp(n,"0")) { fprintf(stderr,"Invalid protocol %s\n",n); + ndpi_exit_detection_module(module); return 1; } if(op) - NDPI_BITMASK_ADD(debug_bitmask,proto); + NDPI_BITMASK_ADD(*bitmask,proto); else - NDPI_BITMASK_DEL(debug_bitmask,proto); + NDPI_BITMASK_DEL(*bitmask,proto); } + ndpi_exit_detection_module(module); return 0; } /* ***************************************************** */ extern char *_debug_protocols; -static int _debug_protocols_ok = 0; struct ndpi_workflow* ndpi_workflow_init(const struct ndpi_workflow_prefs * prefs, pcap_t * pcap_handle, int do_init_flows_root, ndpi_serialization_format serialization_format) { struct ndpi_detection_module_struct * module; struct ndpi_workflow * workflow; + static NDPI_PROTOCOL_BITMASK debug_bitmask; + static int _debug_protocols_ok = 0; set_ndpi_malloc(ndpi_malloc_wrapper), set_ndpi_free(free_wrapper); set_ndpi_flow_malloc(NULL), set_ndpi_flow_free(NULL); @@ -443,7 +460,8 @@ struct ndpi_workflow* ndpi_workflow_init(const struct ndpi_workflow_prefs * pref ndpi_set_log_level(module, nDPI_LogLevel); if(_debug_protocols != NULL && ! _debug_protocols_ok) { - if(parse_debug_proto(module,_debug_protocols)) + NDPI_BITMASK_RESET(debug_bitmask); + if(parse_proto_name_list(_debug_protocols, &debug_bitmask, 0)) exit(-1); _debug_protocols_ok = 1; } -- cgit v1.2.3