diff options
author | Nardi Ivan <nardi.ivan@gmail.com> | 2024-01-09 08:41:44 +0100 |
---|---|---|
committer | Ivan Nardi <12729895+IvanNardi@users.noreply.github.com> | 2024-01-18 10:21:24 +0100 |
commit | d72a760ac3895dd8a0bd3e55d4b51f9e22e04e6c (patch) | |
tree | c00c477a043b58c5c05f4afe6b5ecde5864011df /example/ndpiReader.c | |
parent | ca7df1db82e97954724f547c5966a5f99ad86e6b (diff) |
New API for library configuration
This is the first step into providing (more) configuration options in nDPI.
The idea is to have a simple way to configure (most of) nDPI: only one
function (`ndpi_set_config()`) to set any configuration parameters
(in the present or on in the future) and we try to keep this function
prototype as agnostic as possible.
You can configure the library:
* via API, using `ndpi_set_config()`
* via a configuration file, in a text format
This way, anytime we need to add a new configuration parameter:
* we don't need to add two public functions (a getter and a setter)
* we don't break API/ABI compatibility of the library; even changing
the parameter type (from integer to a list of integer, for example)
doesn't break the compatibility.
The complete list of configuration options is provided in
`doc/configuration_parameters.md`.
As a first example, two configuration knobs are provided:
* the ability to enable/disable the extraction of the sha1 fingerprint of
the TLS certificates.
* the upper limit on the number of packets per flow that will be subject
to inspection
Diffstat (limited to 'example/ndpiReader.c')
-rw-r--r-- | example/ndpiReader.c | 133 |
1 files changed, 125 insertions, 8 deletions
diff --git a/example/ndpiReader.c b/example/ndpiReader.c index c7f641650..e597de3d4 100644 --- a/example/ndpiReader.c +++ b/example/ndpiReader.c @@ -94,6 +94,16 @@ static u_int8_t ignore_vlanid = 0; /** User preferences **/ u_int8_t enable_realtime_output = 0, enable_protocol_guess = 1, enable_payload_analyzer = 0, num_bin_clusters = 0, extcap_exit = 0; u_int8_t verbose = 0, enable_flow_stats = 0; + +struct cfg { + char *proto; + char *param; + char *value; +}; +#define MAX_NUM_CFGS 32 +static struct cfg cfgs[MAX_NUM_CFGS]; +static int num_cfgs = 0; + int nDPI_LogLevel = 0; char *_debug_protocols = NULL; char *_disabled_protocols = NULL; @@ -363,6 +373,8 @@ static void ndpiCheckIPMatch(char *testChar) { struct in_addr addr; char appBufStr[64]; ndpi_protocol detected_protocol; + int i; + ndpi_cfg_error rc; NDPI_PROTOCOL_BITMASK all; if(!testChar) @@ -375,6 +387,14 @@ static void ndpiCheckIPMatch(char *testChar) { if(_protoFilePath != NULL) ndpi_load_protocols_file(ndpi_str, _protoFilePath); + for(i = 0; i < num_cfgs; i++) { + rc = ndpi_set_config(ndpi_str, + cfgs[i].proto, cfgs[i].param, cfgs[i].value); + if (rc < NDPI_CFG_OK) + fprintf(stderr, "Error setting config [%s][%s][%s]: %d\n", + cfgs[i].proto, cfgs[i].param, cfgs[i].value, rc); + } + ndpi_finalize_initialization(ndpi_str); ip_str = strtok_r(testChar, ":", &saveptr); @@ -571,7 +591,7 @@ static void help(u_int long_help) { " | 1 = verbose\n" " | 2 = very verbose\n" " | 3 = port stats\n" - " | 4 = hash stats\n" + " | 4 = hash stats\n" " -V <1-4> | nDPI logging level\n" " | 1 - trace, 2 - debug, 3 - full debug\n" " | >3 - full debug + log enabled for all protocols (i.e. '-u all')\n" @@ -589,6 +609,7 @@ static void help(u_int long_help) { " -Z proto:value | Set this value of aggressiveness for this protocol (0 to disable it). This flag can be used multiple times\n" " --lru-cache-size=NAME:size | Specify the size for this LRU cache (0 to disable it). This flag can be used multiple times\n" " --lru-cache-ttl=NAME:size | Specify the TTL [in seconds] for this LRU cache (0 to disable it). This flag can be used multiple times\n" + " --cfg=proto,param,value | Configure the specific attribute of this protocol\n" , human_readeable_string_len, min_pattern_len, max_pattern_len, max_num_packets_per_flow, max_packet_payload_dissection, @@ -596,6 +617,15 @@ static void help(u_int long_help) { printf("\nLRU Cache names: ookla, bittorrent, zoom, stun, tls_cert, mining, msteams, stun_zoom\n"); + NDPI_PROTOCOL_BITMASK all; + struct ndpi_detection_module_struct *ndpi_info_mod = ndpi_init_detection_module(init_prefs); + NDPI_BITMASK_SET_ALL(all); + ndpi_set_protocol_detection_bitmask2(ndpi_info_mod, &all); + ndpi_finalize_initialization(ndpi_info_mod); + + printf("\nProtocols configuration parameters:\n"); + ndpi_dump_config(ndpi_info_mod, stdout); + #ifndef WIN32 printf("\nExcap (wireshark) options:\n" " --extcap-interfaces\n" @@ -616,24 +646,19 @@ static void help(u_int long_help) { ndpi_detection_get_sizeof_ndpi_flow_struct(), sizeof(((struct ndpi_flow_struct *)0)->protos)); - NDPI_PROTOCOL_BITMASK all; - struct ndpi_detection_module_struct *ndpi_info_mod = ndpi_init_detection_module(init_prefs); printf("\n\nnDPI supported protocols:\n"); printf("%3s %-22s %-10s %-8s %-12s %s\n", "Id", "Protocol", "Layer_4", "Nw_Proto", "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, stdout); printf("\n\nnDPI supported risks:\n"); ndpi_dump_risks_score(stdout); - - ndpi_exit_detection_module(ndpi_info_mod); } + ndpi_exit_detection_module(ndpi_info_mod); + exit(!long_help); } @@ -641,6 +666,8 @@ static void help(u_int long_help) { #define OPTLONG_VALUE_LRU_CACHE_SIZE 1000 #define OPTLONG_VALUE_LRU_CACHE_TTL 1001 +#define OPTLONG_VALUE_CFG 3000 + static struct option longopts[] = { /* mandatory extcap options */ { "extcap-interfaces", no_argument, NULL, '0'}, @@ -685,6 +712,8 @@ static struct option longopts[] = { { "lru-cache-size", required_argument, NULL, OPTLONG_VALUE_LRU_CACHE_SIZE}, { "lru-cache-ttl", required_argument, NULL, OPTLONG_VALUE_LRU_CACHE_TTL}, + { "cfg", required_argument, NULL, OPTLONG_VALUE_CFG}, + {0, 0, 0, 0} }; @@ -941,6 +970,69 @@ static int parse_two_unsigned_integer(char *param, u_int32_t *num1, u_int32_t *n return -1; } +static int parse_three_strings(char *param, char **s1, char **s2, char **s3) +{ + char *saveptr, *tmp_str, *s1_str, *s2_str = NULL, *s3_str; + int num_commas; + unsigned int i; + + tmp_str = ndpi_strdup(param); + if(tmp_str) { + + /* First parameter might be missing */ + num_commas = 0; + for(i = 0; i < strlen(tmp_str); i++) { + if(tmp_str[i] == ',') + num_commas++; + } + + if(num_commas == 1) { + s1_str = NULL; + s2_str = strtok_r(tmp_str, ",", &saveptr); + } else if(num_commas == 2) { + s1_str = strtok_r(tmp_str, ",", &saveptr); + if(s1_str) { + s2_str = strtok_r(NULL, ",", &saveptr); + } + } else { + ndpi_free(tmp_str); + return -1; + } + + if(s2_str) { + s3_str = strtok_r(NULL, ",", &saveptr); + if(s3_str) { + *s1 = ndpi_strdup(s1_str); + *s2 = ndpi_strdup(s2_str); + *s3 = ndpi_strdup(s3_str); + ndpi_free(tmp_str); + if(!s1 || !s2 || !s3) { + ndpi_free(s1); + ndpi_free(s2); + ndpi_free(s3); + return -1; + } + return 0; + } + } + } + ndpi_free(tmp_str); + return -1; +} + +int reader_add_cfg(char *proto, char *param, char *value, int dup) +{ + if(num_cfgs >= MAX_NUM_CFGS) { + printf("Too many parameter! [num:%d/%d]\n", num_cfgs, MAX_NUM_CFGS); + return -1; + } + cfgs[num_cfgs].proto = dup ? ndpi_strdup(proto) : proto; + cfgs[num_cfgs].param = dup ? ndpi_strdup(param) : param; + cfgs[num_cfgs].value = dup ? ndpi_strdup(value) : value; + num_cfgs++; + return 0; +} + /* ********************************** */ /** @@ -958,6 +1050,7 @@ static void parseOptions(int argc, char **argv) { #endif #endif int cache_idx, cache_size, cache_ttl; + char *s1, *s2, *s3; #ifdef USE_DPDK { @@ -1301,6 +1394,14 @@ static void parseOptions(int argc, char **argv) { lru_cache_ttls[cache_idx] = cache_ttl; break; + case OPTLONG_VALUE_CFG: + if(parse_three_strings(optarg, &s1, &s2, &s3) == -1 || + reader_add_cfg(s1, s2, s3, 0) == -1) { + printf("Invalid parameter [%s] [num:%d/%d]\n", optarg, num_cfgs, MAX_NUM_CFGS); + exit(1); + } + break; + default: #ifdef DEBUG_TRACE if(trace) fprintf(trace, " #### Unknown option -%c: skipping it #### \n", opt); @@ -2731,6 +2832,7 @@ static void setupDetection(u_int16_t thread_id, pcap_t * pcap_handle) { NDPI_PROTOCOL_BITMASK enabled_bitmask; struct ndpi_workflow_prefs prefs; int i; + ndpi_cfg_error rc; memset(&prefs, 0, sizeof(prefs)); prefs.decode_tunnels = decode_tunnels; @@ -2821,6 +2923,15 @@ static void setupDetection(u_int16_t thread_id, pcap_t * pcap_handle) { ndpi_set_protocol_aggressiveness(ndpi_thread_info[thread_id].workflow->ndpi_struct, i, aggressiveness[i]); } + for(i = 0; i < num_cfgs; i++) { + rc = ndpi_set_config(ndpi_thread_info[thread_id].workflow->ndpi_struct, + cfgs[i].proto, cfgs[i].param, cfgs[i].value); + if (rc != NDPI_CFG_OK) + fprintf(stderr, "Error setting config [%s][%s][%s]: %d\n", + cfgs[i].proto, cfgs[i].param, cfgs[i].value, rc); + } + + ndpi_finalize_initialization(ndpi_thread_info[thread_id].workflow->ndpi_struct); if(enable_doh_dot_detection) @@ -5833,6 +5944,12 @@ int main(int argc, char **argv) { ndpi_free(_debug_protocols); ndpi_free(_disabled_protocols); + for(i = 0; i < num_cfgs; i++) { + ndpi_free(cfgs[i].proto); + ndpi_free(cfgs[i].param); + ndpi_free(cfgs[i].value); + } + #ifdef DEBUG_TRACE if(trace) fclose(trace); #endif |