diff options
-rw-r--r-- | .github/workflows/build.yml | 1 | ||||
-rw-r--r-- | .gitlab-ci.yml | 1 | ||||
-rw-r--r-- | config.h | 21 | ||||
-rw-r--r-- | nDPId-test.c | 4 | ||||
-rw-r--r-- | nDPId.c | 179 | ||||
-rw-r--r-- | nDPIsrvd.c | 164 | ||||
-rw-r--r-- | utils.c | 40 | ||||
-rw-r--r-- | utils.h | 17 |
8 files changed, 261 insertions, 166 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index aebd96f22..c746dc15f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,6 +70,7 @@ jobs: run: | ./build/nDPId-test || test $? -eq 1 ./build/nDPId -h || test $? -eq 1 + ./build/nDPIsrvd -h || test $? -eq 1 - name: Test DIFF if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.ndpid_gcrypt, '-DNDPI_WITH_GCRYPT=OFF') run: | diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c485efe20..4e2e8fc44 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,6 +53,7 @@ build_and_test: - cd .. - ./build/nDPId-test || test $? -eq 1 - ./build/nDPId -h || test $? -eq 1 + - ./build/nDPIsrvd -h || test $? -eq 1 # dameon start/stop test - NUSER=nobody make -C ./build daemon VERBOSE=1 - NUSER=nobody make -C ./build daemon VERBOSE=1 @@ -2,6 +2,7 @@ #define CONFIG_H 1 /* macros shared across multiple executables */ +#define DEFAULT_CHUSER "nobody" #define COLLECTOR_UNIX_SOCKET "/tmp/ndpid-collector.sock" #define DISTRIBUTOR_UNIX_SOCKET "/tmp/ndpid-distributor.sock" #define DISTRIBUTOR_HOST "127.0.0.1" @@ -23,17 +24,17 @@ #define nDPId_MAX_IDLE_FLOWS_PER_THREAD (nDPId_MAX_FLOWS_PER_THREAD / 32u) #define nDPId_MAX_READER_THREADS 32u #define nDPId_ERROR_EVENT_THRESHOLD_N 16u -#define nDPId_ERROR_EVENT_THRESHOLD_TIME TIME_S_TO_US(10u) /* 10 sec */ -#define nDPId_DAEMON_STATUS_INTERVAL TIME_S_TO_US(600u) /* 600 sec */ +#define nDPId_ERROR_EVENT_THRESHOLD_TIME TIME_S_TO_US(10u) /* 10 sec */ +#define nDPId_DAEMON_STATUS_INTERVAL TIME_S_TO_US(600u) /* 600 sec */ #define nDPId_MEMORY_PROFILING_LOG_INTERVAL TIME_S_TO_US(5u) /* 5 sec */ -#define nDPId_COMPRESSION_SCAN_INTERVAL TIME_S_TO_US(20u) /* 20 sec */ -#define nDPId_COMPRESSION_FLOW_INACTIVITY TIME_S_TO_US(30u) /* 30 sec */ -#define nDPId_FLOW_SCAN_INTERVAL TIME_S_TO_US(10u) /* 10 sec */ -#define nDPId_GENERIC_IDLE_TIME TIME_S_TO_US(600u) /* 600 sec */ -#define nDPId_ICMP_IDLE_TIME TIME_S_TO_US(120u) /* 120 sec */ -#define nDPId_TCP_IDLE_TIME TIME_S_TO_US(7440u) /* 7440 sec */ -#define nDPId_UDP_IDLE_TIME TIME_S_TO_US(180u) /* 180 sec */ -#define nDPId_TCP_POST_END_FLOW_TIME TIME_S_TO_US(120u) /* 120 sec */ +#define nDPId_COMPRESSION_SCAN_INTERVAL TIME_S_TO_US(20u) /* 20 sec */ +#define nDPId_COMPRESSION_FLOW_INACTIVITY TIME_S_TO_US(30u) /* 30 sec */ +#define nDPId_FLOW_SCAN_INTERVAL TIME_S_TO_US(10u) /* 10 sec */ +#define nDPId_GENERIC_IDLE_TIME TIME_S_TO_US(600u) /* 600 sec */ +#define nDPId_ICMP_IDLE_TIME TIME_S_TO_US(120u) /* 120 sec */ +#define nDPId_TCP_IDLE_TIME TIME_S_TO_US(7440u) /* 7440 sec */ +#define nDPId_UDP_IDLE_TIME TIME_S_TO_US(180u) /* 180 sec */ +#define nDPId_TCP_POST_END_FLOW_TIME TIME_S_TO_US(120u) /* 120 sec */ #define nDPId_THREAD_DISTRIBUTION_SEED 0x03dd018b #define nDPId_PACKETS_PER_FLOW_TO_SEND 15u #define nDPId_PACKETS_PER_FLOW_TO_PROCESS NDPI_DEFAULT_MAX_NUM_PKTS_PER_FLOW_TO_DISSECT diff --git a/nDPId-test.c b/nDPId-test.c index ae28b2b64..b125d5e99 100644 --- a/nDPId-test.c +++ b/nDPId-test.c @@ -1141,13 +1141,13 @@ int main(int argc, char ** argv) nDPId_options.memory_profiling_log_interval = (unsigned long long int)-1; nDPId_options.reader_thread_count = 1; /* Please do not change this! Generating meaningful pcap diff's relies on a single reader thread! */ - nDPId_options.instance_alias = strdup("nDPId-test"); + set_cmdarg(&nDPId_options.instance_alias, "nDPId-test"); if (access(argv[1], R_OK) != 0) { logger(1, "%s: pcap file `%s' does not exist or is not readable", argv[0], argv[1]); return 1; } - nDPId_options.pcap_file_or_interface = strdup(argv[1]); + set_cmdarg(&nDPId_options.pcap_file_or_interface, argv[1]); if (validate_options() != 0) { return 1; @@ -441,27 +441,27 @@ static MT_VALUE(zlib_compression_bytes, uint64_t) = MT_INIT(0); static struct { /* opts */ - char * pcap_file_or_interface; + struct cmdarg pcap_file_or_interface; + struct cmdarg bpf_str; + struct cmdarg pidfile; + struct cmdarg user; + struct cmdarg group; + struct cmdarg custom_protocols_file; + struct cmdarg custom_categories_file; + struct cmdarg custom_ja3_file; + struct cmdarg custom_sha1_file; + struct cmdarg collector_address; + struct cmdarg instance_alias; union nDPId_ip pcap_dev_ip4, pcap_dev_ip6; union nDPId_ip pcap_dev_netmask4, pcap_dev_netmask6; union nDPId_ip pcap_dev_subnet4, pcap_dev_subnet6; uint8_t process_internal_initial_direction; uint8_t process_external_initial_direction; - char * bpf_str; - char pidfile[UNIX_PATH_MAX]; - char * user; - char * group; - char * custom_protocols_file; - char * custom_categories_file; - char * custom_ja3_file; - char * custom_sha1_file; - char collector_address[UNIX_PATH_MAX]; #ifdef ENABLE_ZLIB uint8_t enable_zlib_compression; #endif uint8_t enable_data_analysis; /* subopts */ - char * instance_alias; unsigned long long int max_flows_per_thread; unsigned long long int max_idle_flows_per_thread; unsigned long long int reader_thread_count; @@ -484,9 +484,17 @@ static struct unsigned long long int max_packets_per_flow_to_analyse; unsigned long long int error_event_threshold_n; unsigned long long int error_event_threshold_time; -} nDPId_options = {.pidfile = nDPId_PIDFILE, - .user = "nobody", - .collector_address = COLLECTOR_UNIX_SOCKET, +} nDPId_options = {.pcap_file_or_interface = CMDARG(NULL), + .bpf_str = CMDARG(NULL), + .pidfile = CMDARG(nDPId_PIDFILE), + .user = CMDARG(DEFAULT_CHUSER), + .group = CMDARG(NULL), + .custom_protocols_file = CMDARG(NULL), + .custom_categories_file = CMDARG(NULL), + .custom_ja3_file = CMDARG(NULL), + .custom_sha1_file = CMDARG(NULL), + .collector_address = CMDARG(COLLECTOR_UNIX_SOCKET), + .instance_alias = CMDARG(NULL), .max_flows_per_thread = nDPId_MAX_FLOWS_PER_THREAD / 2, .max_idle_flows_per_thread = nDPId_MAX_IDLE_FLOWS_PER_THREAD / 2, .reader_thread_count = nDPId_MAX_READER_THREADS / 2, @@ -986,7 +994,7 @@ static int get_ip6_address_and_netmask(char const * const ifa_name, size_t ifnam logger(0, "%s IPv6 address/prefix netmask subnet: %s/%u %s %s", - nDPId_options.pcap_file_or_interface, + get_cmdarg(&nDPId_options.pcap_file_or_interface), addr6, plen, netmask6, @@ -1053,7 +1061,7 @@ static int get_ip4_address_and_netmask(char const * const ifa_name, size_t ifnam void * ssubn = &nDPId_options.pcap_dev_subnet4.v4.ip; logger(0, "%s IPv4 address netmask subnet: %s %s %s", - nDPId_options.pcap_file_or_interface, + get_cmdarg(&nDPId_options.pcap_file_or_interface), inet_ntop(AF_INET, saddr, addr, sizeof(addr)), inet_ntop(AF_INET, snetm, netm, sizeof(netm)), inet_ntop(AF_INET, ssubn, subn, sizeof(subn))); @@ -1236,10 +1244,10 @@ static struct nDPId_workflow * init_workflow(char const * const file_or_device) return NULL; } - if (nDPId_options.bpf_str != NULL) + if (is_cmdarg_set(&nDPId_options.bpf_str) != 0) { struct bpf_program fp; - if (pcap_compile(workflow->pcap_handle, &fp, nDPId_options.bpf_str, 1, PCAP_NETMASK_UNKNOWN) != 0) + if (pcap_compile(workflow->pcap_handle, &fp, get_cmdarg(&nDPId_options.bpf_str), 1, PCAP_NETMASK_UNKNOWN) != 0) { logger_early(1, "pcap_compile: %s", pcap_geterr(workflow->pcap_handle)); free_workflow(&workflow); @@ -1292,21 +1300,21 @@ static struct nDPId_workflow * init_workflow(char const * const file_or_device) NDPI_PROTOCOL_BITMASK protos; NDPI_BITMASK_SET_ALL(protos); ndpi_set_protocol_detection_bitmask2(workflow->ndpi_struct, &protos); - if (nDPId_options.custom_protocols_file != NULL) + if (is_cmdarg_set(&nDPId_options.custom_protocols_file) != 0) { - ndpi_load_protocols_file(workflow->ndpi_struct, nDPId_options.custom_protocols_file); + ndpi_load_protocols_file(workflow->ndpi_struct, get_cmdarg(&nDPId_options.custom_protocols_file)); } - if (nDPId_options.custom_categories_file != NULL) + if (is_cmdarg_set(&nDPId_options.custom_categories_file) != 0) { - ndpi_load_categories_file(workflow->ndpi_struct, nDPId_options.custom_categories_file, NULL); + ndpi_load_categories_file(workflow->ndpi_struct, get_cmdarg(&nDPId_options.custom_categories_file), NULL); } - if (nDPId_options.custom_ja3_file != NULL) + if (is_cmdarg_set(&nDPId_options.custom_ja3_file) != 0) { - ndpi_load_malicious_ja3_file(workflow->ndpi_struct, nDPId_options.custom_ja3_file); + ndpi_load_malicious_ja3_file(workflow->ndpi_struct, get_cmdarg(&nDPId_options.custom_ja3_file)); } - if (nDPId_options.custom_sha1_file != NULL) + if (is_cmdarg_set(&nDPId_options.custom_sha1_file) != 0) { - ndpi_load_malicious_sha1_file(workflow->ndpi_struct, nDPId_options.custom_sha1_file); + ndpi_load_malicious_sha1_file(workflow->ndpi_struct, get_cmdarg(&nDPId_options.custom_sha1_file)); } ndpi_finalize_initialization(workflow->ndpi_struct); @@ -1484,28 +1492,30 @@ static int setup_reader_threads(void) return 1; } - if (nDPId_options.pcap_file_or_interface == NULL) + if (is_cmdarg_set(&nDPId_options.pcap_file_or_interface) == 0) { - nDPId_options.pcap_file_or_interface = get_default_pcapdev(pcap_error_buffer); - if (nDPId_options.pcap_file_or_interface == NULL) + char * const pcapdev = get_default_pcapdev(pcap_error_buffer); + set_cmdarg(&nDPId_options.pcap_file_or_interface, pcapdev); + free(pcapdev); + if (is_cmdarg_set(&nDPId_options.pcap_file_or_interface) == 0) { logger_early(1, "pcap_lookupdev: %.*s", (int)PCAP_ERRBUF_SIZE, pcap_error_buffer); return 1; } - logger_early(0, "Capturing packets from default device: %s", nDPId_options.pcap_file_or_interface); + logger_early(0, "Capturing packets from default device: %s", get_cmdarg(&nDPId_options.pcap_file_or_interface)); } errno = 0; - if (access(nDPId_options.pcap_file_or_interface, R_OK) != 0 && errno == ENOENT) + if (access(get_cmdarg(&nDPId_options.pcap_file_or_interface), R_OK) != 0 && errno == ENOENT) { errno = 0; - if (get_ip_netmask_from_pcap_dev(nDPId_options.pcap_file_or_interface) != 0) + if (get_ip_netmask_from_pcap_dev(get_cmdarg(&nDPId_options.pcap_file_or_interface)) != 0) { if (errno != 0) { logger_early(1, "Could not get netmask for pcap device %s: %s", - nDPId_options.pcap_file_or_interface, + get_cmdarg(&nDPId_options.pcap_file_or_interface), strerror(errno)); } return 1; @@ -1527,7 +1537,7 @@ static int setup_reader_threads(void) for (unsigned long long int i = 0; i < nDPId_options.reader_thread_count; ++i) { - reader_threads[i].workflow = init_workflow(nDPId_options.pcap_file_or_interface); + reader_threads[i].workflow = init_workflow(get_cmdarg(&nDPId_options.pcap_file_or_interface)); if (reader_threads[i].workflow == NULL) { return 1; @@ -1981,8 +1991,10 @@ static void jsonize_basic(struct nDPId_reader_thread * const reader_thread, int ndpi_serialize_string_int32(&workflow->ndpi_serializer, "thread_id", reader_thread->array_index); } ndpi_serialize_string_uint32(&workflow->ndpi_serializer, "packet_id", workflow->packets_captured); - ndpi_serialize_string_string(&workflow->ndpi_serializer, "source", nDPId_options.pcap_file_or_interface); - ndpi_serialize_string_string(&workflow->ndpi_serializer, "alias", nDPId_options.instance_alias); + ndpi_serialize_string_string(&workflow->ndpi_serializer, + "source", + get_cmdarg(&nDPId_options.pcap_file_or_interface)); + ndpi_serialize_string_string(&workflow->ndpi_serializer, "alias", get_cmdarg(&nDPId_options.instance_alias)); } static void jsonize_daemon(struct nDPId_reader_thread * const reader_thread, enum daemon_event event) @@ -2232,7 +2244,7 @@ static void send_to_collector(struct nDPId_reader_thread * const reader_thread, "[%8llu, %zu] Reconnected to nDPIsrvd Collector at %s", workflow->packets_captured, reader_thread->array_index, - nDPId_options.collector_address); + get_cmdarg(&nDPId_options.collector_address)); jsonize_daemon(reader_thread, DAEMON_EVENT_RECONNECT); } } @@ -2244,7 +2256,7 @@ static void send_to_collector(struct nDPId_reader_thread * const reader_thread, "[%8llu, %zu] Could not connect to nDPIsrvd Collector at %s, will try again later. Error: %s", workflow->packets_captured, reader_thread->array_index, - nDPId_options.collector_address, + get_cmdarg(&nDPId_options.collector_address), (reader_thread->collector_sock_last_errno != 0 ? strerror(reader_thread->collector_sock_last_errno) : "Internal Error.")); @@ -2275,7 +2287,7 @@ static void send_to_collector(struct nDPId_reader_thread * const reader_thread, workflow->packets_captured, reader_thread->array_index, (collector_address.raw.sa_family == AF_UNIX ? "Connection" : "Datagram"), - nDPId_options.collector_address); + get_cmdarg(&nDPId_options.collector_address)); } reader_thread->collector_sock_last_errno = saved_errno; } @@ -2302,7 +2314,7 @@ static void send_to_collector(struct nDPId_reader_thread * const reader_thread, "[%8llu, %zu] Send data (blocking I/O) to nDPIsrvd Collector at %s failed: %s", workflow->packets_captured, reader_thread->array_index, - nDPId_options.collector_address, + get_cmdarg(&nDPId_options.collector_address), strerror(saved_errno)); reader_thread->collector_sock_last_errno = saved_errno; break; @@ -4476,7 +4488,7 @@ static void * processing_thread(void * const ndpi_thread_arg) logger(1, "Thread %zu: Could not connect to nDPIsrvd Collector at %s, will try again later. Error: %s", reader_thread->array_index, - nDPId_options.collector_address, + get_cmdarg(&nDPId_options.collector_address), (reader_thread->collector_sock_last_errno != 0 ? strerror(reader_thread->collector_sock_last_errno) : "Internal Error.")); } @@ -4516,30 +4528,33 @@ static int start_reader_threads(void) return 1; } - if (daemonize_with_pidfile(nDPId_options.pidfile) != 0) + if (daemonize_with_pidfile(get_cmdarg(&nDPId_options.pidfile)) != 0) { return 1; } errno = 0; - if (nDPId_options.user != NULL && - change_user_group(nDPId_options.user, nDPId_options.group, nDPId_options.pidfile, NULL, NULL) != 0 && + if (change_user_group(get_cmdarg(&nDPId_options.user), + get_cmdarg(&nDPId_options.group), + get_cmdarg(&nDPId_options.pidfile), + NULL, + NULL) != 0 && errno != EPERM) { if (errno != 0) { logger(1, "Change user/group to %s/%s failed: %s", - (nDPId_options.user != NULL ? nDPId_options.user : "-"), - (nDPId_options.group != NULL ? nDPId_options.group : "-"), + get_cmdarg(&nDPId_options.user), + get_cmdarg(&nDPId_options.group), strerror(errno)); } else { logger(1, "Change user/group to %s/%s failed.", - (nDPId_options.user != NULL ? nDPId_options.user : "-"), - (nDPId_options.group != NULL ? nDPId_options.group : "-")); + get_cmdarg(&nDPId_options.user), + get_cmdarg(&nDPId_options.group)); } return 1; } @@ -4816,10 +4831,8 @@ static void print_subopt_usage(void) } while (1); } -static int nDPId_parse_options(int argc, char ** argv) +static void print_usage(char const * const arg0) { - int opt; - static char const usage[] = "Usage: %s " "[-i pcap-file/interface] [-I] [-E] [-B bpf-filter]\n" @@ -4844,9 +4857,12 @@ static int nDPId_parse_options(int argc, char ** argv) "\t-l\tLog all messages to stderr.\n" "\t-L\tLog all messages to a log file.\n" "\t-c\tPath to a UNIX socket (nDPIsrvd Collector) or a custom UDP endpoint.\n" - "\t-d\tForking into background after initialization.\n" + "\t \tDefault: %s\n" + "\t-d\tFork into background after initialization.\n" "\t-p\tWrite the daemon PID to the given file path.\n" + "\t \tDefault: %s\n" "\t-u\tChange UID to the numeric value of user.\n" + "\t \tDefault: %s\n" "\t-g\tChange GID to the numeric value of group.\n" "\t-P\tLoad a nDPI custom protocols file.\n" "\t-C\tLoad a nDPI custom categories file.\n" @@ -4867,13 +4883,24 @@ static int nDPId_parse_options(int argc, char ** argv) "\t-o\t(Carefully) Tune some daemon options. See subopts below.\n" "\t-v\tversion\n" "\t-h\tthis\n\n"; + fprintf(stderr, + usage, + arg0, + get_cmdarg(&nDPId_options.collector_address), + get_cmdarg(&nDPId_options.pidfile), + get_cmdarg(&nDPId_options.user)); +} + +static int nDPId_parse_options(int argc, char ** argv) +{ + int opt; while ((opt = getopt(argc, argv, "i:IEB:lL:c:dp:u:g:P:C:J:S:a:Azo:vh")) != -1) { switch (opt) { case 'i': - nDPId_options.pcap_file_or_interface = strdup(optarg); + set_cmdarg(&nDPId_options.pcap_file_or_interface, optarg); break; case 'I': nDPId_options.process_internal_initial_direction = 1; @@ -4882,7 +4909,7 @@ static int nDPId_parse_options(int argc, char ** argv) nDPId_options.process_external_initial_direction = 1; break; case 'B': - nDPId_options.bpf_str = strdup(optarg); + set_cmdarg(&nDPId_options.bpf_str, optarg); break; case 'l': enable_console_logger(); @@ -4894,36 +4921,34 @@ static int nDPId_parse_options(int argc, char ** argv) } break; case 'c': - strncpy(nDPId_options.collector_address, optarg, sizeof(nDPId_options.collector_address) - 1); - nDPId_options.collector_address[sizeof(nDPId_options.collector_address) - 1] = '\0'; + set_cmdarg(&nDPId_options.collector_address, optarg); break; case 'd': daemonize_enable(); break; case 'p': - strncpy(nDPId_options.pidfile, optarg, sizeof(nDPId_options.pidfile) - 1); - nDPId_options.pidfile[sizeof(nDPId_options.pidfile) - 1] = '\0'; + set_cmdarg(&nDPId_options.pidfile, optarg); break; case 'u': - nDPId_options.user = strdup(optarg); + set_cmdarg(&nDPId_options.user, optarg); break; case 'g': - nDPId_options.group = strdup(optarg); + set_cmdarg(&nDPId_options.group, optarg); break; case 'P': - nDPId_options.custom_protocols_file = strdup(optarg); + set_cmdarg(&nDPId_options.custom_protocols_file, optarg); break; case 'C': - nDPId_options.custom_categories_file = strdup(optarg); + set_cmdarg(&nDPId_options.custom_categories_file, optarg); break; case 'J': - nDPId_options.custom_ja3_file = strdup(optarg); + set_cmdarg(&nDPId_options.custom_ja3_file, optarg); break; case 'S': - nDPId_options.custom_sha1_file = strdup(optarg); + set_cmdarg(&nDPId_options.custom_sha1_file, optarg); break; case 'a': - nDPId_options.instance_alias = strdup(optarg); + set_cmdarg(&nDPId_options.instance_alias, optarg); break; case 'A': nDPId_options.enable_data_analysis = 1; @@ -4950,7 +4975,7 @@ static int nDPId_parse_options(int argc, char ** argv) { logger_early(1, "Missing value for `%s'", subopt_token[subopt]); fprintf(stderr, "%s", "\n"); - fprintf(stderr, usage, argv[0]); + print_usage(argv[0]); print_subopt_usage(); return 1; } @@ -4958,7 +4983,7 @@ static int nDPId_parse_options(int argc, char ** argv) { logger_early(1, "Invalid subopt: %s", value); fprintf(stderr, "%s", "\n"); - fprintf(stderr, usage, argv[0]); + print_usage(argv[0]); print_subopt_usage(); return 1; } @@ -5045,7 +5070,7 @@ static int nDPId_parse_options(int argc, char ** argv) case 'h': default: fprintf(stderr, "%s\n", get_nDPId_version()); - fprintf(stderr, usage, argv[0]); + print_usage(argv[0]); print_subopt_usage(); return 1; } @@ -5055,7 +5080,7 @@ static int nDPId_parse_options(int argc, char ** argv) { logger_early(1, "%s", "Unexpected argument after options"); fprintf(stderr, "%s", "\n"); - fprintf(stderr, usage, argv[0]); + print_usage(argv[0]); print_subopt_usage(); return 1; } @@ -5090,12 +5115,12 @@ static int validate_options(void) } } #endif - if (nDPIsrvd_setup_address(&collector_address, nDPId_options.collector_address) != 0) + if (nDPIsrvd_setup_address(&collector_address, get_cmdarg(&nDPId_options.collector_address)) != 0) { retval = 1; - logger_early(1, "Collector socket invalid address: %s.", nDPId_options.collector_address); + logger_early(1, "Collector socket invalid address: %s.", get_cmdarg(&nDPId_options.collector_address)); } - if (nDPId_options.instance_alias == NULL) + if (is_cmdarg_set(&nDPId_options.instance_alias) == 0) { char hname[256]; @@ -5107,9 +5132,11 @@ static int validate_options(void) } else { - nDPId_options.instance_alias = strdup(hname); - logger_early(1, "No instance alias given, using your hostname '%s'", nDPId_options.instance_alias); - if (nDPId_options.instance_alias == NULL) + set_cmdarg(&nDPId_options.instance_alias, hname); + logger_early(1, + "No instance alias given, using your hostname '%s'", + get_cmdarg(&nDPId_options.instance_alias)); + if (is_cmdarg_set(&nDPId_options.instance_alias) == 0) { retval = 1; } @@ -5285,7 +5312,7 @@ int main(int argc, char ** argv) } free_reader_threads(); - daemonize_shutdown(nDPId_options.pidfile); + daemonize_shutdown(get_cmdarg(&nDPId_options.pidfile)); logger(0, "%s", "Bye."); shutdown_logging(); diff --git a/nDPIsrvd.c b/nDPIsrvd.c index eab484e7e..e57e2625a 100644 --- a/nDPIsrvd.c +++ b/nDPIsrvd.c @@ -84,19 +84,24 @@ static struct nDPIsrvd_address distributor_in_address = { static struct { - char * pidfile; - char * collector_un_sockpath; - char * distributor_un_sockpath; - char * distributor_in_address; + struct cmdarg pidfile; + struct cmdarg collector_un_sockpath; + struct cmdarg distributor_un_sockpath; + struct cmdarg distributor_in_address; + struct cmdarg user; + struct cmdarg group; nDPIsrvd_ull max_remote_descriptors; - char * user; - char * group; nDPIsrvd_ull max_write_buffers; int bufferbloat_fallback_to_blocking; -} nDPIsrvd_options = {.max_remote_descriptors = nDPIsrvd_MAX_REMOTE_DESCRIPTORS, +} nDPIsrvd_options = {.pidfile = CMDARG(nDPIsrvd_PIDFILE), + .collector_un_sockpath = CMDARG(COLLECTOR_UNIX_SOCKET), + .distributor_un_sockpath = CMDARG(DISTRIBUTOR_UNIX_SOCKET), + .distributor_in_address = CMDARG(NULL), + .user = CMDARG(DEFAULT_CHUSER), + .group = CMDARG(NULL), + .max_remote_descriptors = nDPIsrvd_MAX_REMOTE_DESCRIPTORS, .max_write_buffers = nDPIsrvd_MAX_WRITE_BUFFERS, - .bufferbloat_fallback_to_blocking = 1, - .user = "nobody"}; + .bufferbloat_fallback_to_blocking = 1}; static void logger_nDPIsrvd(struct remote_desc const * const remote, char const * const prefix, @@ -457,7 +462,7 @@ static int create_listen_sockets(void) return 1; } - if (nDPIsrvd_options.distributor_in_address != NULL) + if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0) { distributor_in_sockfd = socket(distributor_in_address.raw.sa_family, SOCK_STREAM, 0); if (distributor_in_sockfd < 0) @@ -487,7 +492,7 @@ static int create_listen_sockets(void) int written = snprintf(collector_addr.sun_path, sizeof(collector_addr.sun_path), "%s", - nDPIsrvd_options.collector_un_sockpath); + get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); if (written < 0) { logger(1, "snprintf failed: %s", strerror(errno)); @@ -497,7 +502,7 @@ static int create_listen_sockets(void) { logger(1, "Collector UNIX socket path too long, current/max: %zu/%zu", - strlen(nDPIsrvd_options.collector_un_sockpath), + strlen(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)), sizeof(collector_addr.sun_path) - 1); return 1; } @@ -506,7 +511,7 @@ static int create_listen_sockets(void) { logger(1, "Error binding Collector UNIX socket to `%s': %s", - nDPIsrvd_options.collector_un_sockpath, + get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), strerror(errno)); return 1; } @@ -518,7 +523,7 @@ static int create_listen_sockets(void) int written = snprintf(distributor_addr.sun_path, sizeof(distributor_addr.sun_path), "%s", - nDPIsrvd_options.distributor_un_sockpath); + get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); if (written < 0) { logger(1, "snprintf failed: %s", strerror(errno)); @@ -528,7 +533,7 @@ static int create_listen_sockets(void) { logger(1, "Distributor UNIX socket path too long, current/max: %zu/%zu", - strlen(nDPIsrvd_options.distributor_un_sockpath), + strlen(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)), sizeof(distributor_addr.sun_path) - 1); return 2; } @@ -537,19 +542,19 @@ static int create_listen_sockets(void) { logger(1, "Error binding Distributor socket to `%s': %s", - nDPIsrvd_options.distributor_un_sockpath, + get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath), strerror(errno)); return 2; } } - if (nDPIsrvd_options.distributor_in_address != NULL) + if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0) { if (bind(distributor_in_sockfd, &distributor_in_address.raw, distributor_in_address.size) < 0) { logger(1, "Error binding Distributor TCP/IP socket to %s: %s", - nDPIsrvd_options.distributor_in_address, + get_cmdarg(&nDPIsrvd_options.distributor_in_address), strerror(errno)); return 3; } @@ -557,7 +562,7 @@ static int create_listen_sockets(void) { logger(1, "Error listening Distributor TCP/IP socket to %s: %s", - nDPIsrvd_options.distributor_in_address, + get_cmdarg(&nDPIsrvd_options.distributor_in_address), strerror(errno)); return 3; } @@ -565,7 +570,7 @@ static int create_listen_sockets(void) { logger(1, "Error setting Distributor TCP/IP socket %s to non-blocking mode: %s", - nDPIsrvd_options.distributor_in_address, + get_cmdarg(&nDPIsrvd_options.distributor_in_address), strerror(errno)); return 3; } @@ -581,7 +586,7 @@ static int create_listen_sockets(void) { logger(1, "Error setting Collector UNIX socket `%s' to non-blocking mode: %s", - nDPIsrvd_options.collector_un_sockpath, + get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), strerror(errno)); return 3; } @@ -590,7 +595,7 @@ static int create_listen_sockets(void) { logger(1, "Error setting Distributor UNIX socket `%s' to non-blocking mode: %s", - nDPIsrvd_options.distributor_un_sockpath, + get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath), strerror(errno)); return 3; } @@ -800,23 +805,19 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) } break; case 'c': - free(nDPIsrvd_options.collector_un_sockpath); - nDPIsrvd_options.collector_un_sockpath = strdup(optarg); + set_cmdarg(&nDPIsrvd_options.collector_un_sockpath, optarg); break; case 'd': daemonize_enable(); break; case 'p': - free(nDPIsrvd_options.pidfile); - nDPIsrvd_options.pidfile = strdup(optarg); + set_cmdarg(&nDPIsrvd_options.pidfile, optarg); break; case 's': - free(nDPIsrvd_options.distributor_un_sockpath); - nDPIsrvd_options.distributor_un_sockpath = strdup(optarg); + set_cmdarg(&nDPIsrvd_options.distributor_un_sockpath, optarg); break; case 'S': - free(nDPIsrvd_options.distributor_in_address); - nDPIsrvd_options.distributor_in_address = strdup(optarg); + set_cmdarg(&nDPIsrvd_options.distributor_in_address, optarg); break; case 'm': if (str_value_to_ull(optarg, &nDPIsrvd_options.max_remote_descriptors) != CONVERSION_OK) @@ -826,11 +827,10 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) } break; case 'u': - nDPIsrvd_options.user = strdup(optarg); + set_cmdarg(&nDPIsrvd_options.user, optarg); break; case 'g': - free(nDPIsrvd_options.group); - nDPIsrvd_options.group = strdup(optarg); + set_cmdarg(&nDPIsrvd_options.group, optarg); break; case 'C': if (str_value_to_ull(optarg, &nDPIsrvd_options.max_write_buffers) != CONVERSION_OK) @@ -853,44 +853,57 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) "\t[-s path-to-distributor-unix-socket] [-S distributor-host:port]\n" "\t[-m max-remote-descriptors] [-u user] [-g group]\n" "\t[-C max-buffered-json-lines] [-D]\n" - "\t[-v] [-h]\n", - argv[0]); + "\t[-v] [-h]\n\n" + "\t-l\tLog all messages to stderr.\n" + "\t-L\tLog all messages to a log file.\n" + "\t-c\tPath to a listening UNIX socket (nDPIsrvd Collector).\n" + "\t \tDefault: %s\n" + "\t-d\tFork into background after initialization.\n" + "\t-p\tWrite the daemon PID to the given file path.\n" + "\t \tDefault: %s\n" + "\t-m\tMax accepted (Collector and Distributor) clients.\n" + "\t-u\tChange UID to the numeric value of user.\n" + "\t \tDefault: %s\n" + "\t-g\tChange GID to the numeric value of group.\n" + "\t-C\tMax buffered JSON lines before nDPIsrvd disconnects/blocking-IO a client.\n" + "\t-D\tDisconnect a slow client instead of falling back to blocking-IO.\n" + "\t-s\tPath to a listening UNIX socket (nDPIsrvd Distributor).\n" + "\t \tDefault: %s\n" + "\t-S\tAddress:Port of the listening TCP/IP socket (nDPIsrvd Distributor).\n" + "\t-v\tversion\n" + "\t-h\tthis\n\n", + argv[0], + get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), + get_cmdarg(&nDPIsrvd_options.pidfile), + get_cmdarg(&nDPIsrvd_options.user), + get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); return 1; } } - if (nDPIsrvd_options.pidfile == NULL) - { - nDPIsrvd_options.pidfile = strdup(nDPIsrvd_PIDFILE); - } - if (is_path_absolute("Pidfile", nDPIsrvd_options.pidfile) != 0) + if (is_path_absolute("Pidfile", get_cmdarg(&nDPIsrvd_options.pidfile)) != 0) { return 1; } - if (nDPIsrvd_options.collector_un_sockpath == NULL) - { - nDPIsrvd_options.collector_un_sockpath = strdup(COLLECTOR_UNIX_SOCKET); - } - if (is_path_absolute("Collector UNIX socket", nDPIsrvd_options.collector_un_sockpath) != 0) + if (is_path_absolute("Collector UNIX socket", get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)) != 0) { return 1; } - if (nDPIsrvd_options.distributor_un_sockpath == NULL) - { - nDPIsrvd_options.distributor_un_sockpath = strdup(DISTRIBUTOR_UNIX_SOCKET); - } - if (is_path_absolute("Distributor UNIX socket", nDPIsrvd_options.distributor_un_sockpath) != 0) + if (is_path_absolute("Distributor UNIX socket", get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)) != 0) { return 1; } - if (nDPIsrvd_options.distributor_in_address != NULL) + if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0) { - if (nDPIsrvd_setup_address(&distributor_in_address, nDPIsrvd_options.distributor_in_address) != 0) + if (nDPIsrvd_setup_address(&distributor_in_address, get_cmdarg(&nDPIsrvd_options.distributor_in_address)) != 0) { - logger_early(1, "%s: Could not parse address %s", argv[0], nDPIsrvd_options.distributor_in_address); + logger_early(1, + "%s: Could not parse address %s", + argv[0], + get_cmdarg(&nDPIsrvd_options.distributor_in_address)); return 1; } if (distributor_in_address.raw.sa_family == AF_UNIX) @@ -898,8 +911,8 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) logger_early(1, "%s: You've requested to setup another UNIX socket `%s', but there is already one at `%s'", argv[0], - nDPIsrvd_options.distributor_in_address, - nDPIsrvd_options.distributor_un_sockpath); + get_cmdarg(&nDPIsrvd_options.distributor_in_address), + get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); return 1; } } @@ -1536,27 +1549,27 @@ int main(int argc, char ** argv) return 1; } - if (access(nDPIsrvd_options.collector_un_sockpath, F_OK) == 0) + if (access(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), F_OK) == 0) { logger_early(1, "UNIX socket `%s' exists; nDPIsrvd already running? " "Please remove the socket manually or change socket path.", - nDPIsrvd_options.collector_un_sockpath); + get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); return 1; } - if (access(nDPIsrvd_options.distributor_un_sockpath, F_OK) == 0) + if (access(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath), F_OK) == 0) { logger_early(1, "UNIX socket `%s' exists; nDPIsrvd already running? " "Please remove the socket manually or change socket path.", - nDPIsrvd_options.distributor_un_sockpath); + get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); return 1; } log_app_info(); - if (daemonize_with_pidfile(nDPIsrvd_options.pidfile) != 0) + if (daemonize_with_pidfile(get_cmdarg(&nDPIsrvd_options.pidfile)) != 0) { goto error; } @@ -1573,7 +1586,7 @@ int main(int argc, char ** argv) case 1: goto error; case 2: - unlink(nDPIsrvd_options.collector_un_sockpath); + unlink(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); goto error; case 3: goto error_unlink_sockets; @@ -1581,8 +1594,8 @@ int main(int argc, char ** argv) goto error; } - logger(0, "collector UNIX socket listen on `%s'", nDPIsrvd_options.collector_un_sockpath); - logger(0, "distributor UNIX listen on `%s'", nDPIsrvd_options.distributor_un_sockpath); + logger(0, "collector UNIX socket listen on `%s'", get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); + logger(0, "distributor UNIX listen on `%s'", get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); switch (distributor_in_address.raw.sa_family) { default: @@ -1599,28 +1612,27 @@ int main(int argc, char ** argv) } errno = 0; - if (nDPIsrvd_options.user != NULL && - change_user_group(nDPIsrvd_options.user, - nDPIsrvd_options.group, - nDPIsrvd_options.pidfile, - nDPIsrvd_options.collector_un_sockpath, - nDPIsrvd_options.distributor_un_sockpath) != 0 && + if (change_user_group(get_cmdarg(&nDPIsrvd_options.user), + get_cmdarg(&nDPIsrvd_options.group), + get_cmdarg(&nDPIsrvd_options.pidfile), + get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), + get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)) != 0 && errno != EPERM) { if (errno != 0) { logger(1, "Change user/group to %s/%s failed: %s", - nDPIsrvd_options.user, - (nDPIsrvd_options.group != NULL ? nDPIsrvd_options.group : "-"), + get_cmdarg(&nDPIsrvd_options.user), + (is_cmdarg_set(&nDPIsrvd_options.group) != 0 ? get_cmdarg(&nDPIsrvd_options.group) : "-"), strerror(errno)); } else { logger(1, "Change user/group to %s/%s failed.", - nDPIsrvd_options.user, - (nDPIsrvd_options.group != NULL ? nDPIsrvd_options.group : "-")); + get_cmdarg(&nDPIsrvd_options.user), + (is_cmdarg_set(&nDPIsrvd_options.group) != 0 ? get_cmdarg(&nDPIsrvd_options.group) : "-")); } goto error_unlink_sockets; } @@ -1640,14 +1652,14 @@ int main(int argc, char ** argv) close_event_queue(epollfd); error_unlink_sockets: - unlink(nDPIsrvd_options.collector_un_sockpath); - unlink(nDPIsrvd_options.distributor_un_sockpath); + unlink(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); + unlink(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); error: close(collector_un_sockfd); close(distributor_un_sockfd); close(distributor_in_sockfd); - daemonize_shutdown(nDPIsrvd_options.pidfile); + daemonize_shutdown(get_cmdarg(&nDPIsrvd_options.pidfile)); logger(0, "Bye."); shutdown_logging(); @@ -6,6 +6,7 @@ #include <pwd.h> #include <stdarg.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #ifndef NO_MAIN #include <syslog.h> @@ -21,6 +22,42 @@ static int daemonize = 0; static int log_to_console = 0; static int log_to_file_fd = -1; +void set_cmdarg(struct cmdarg * const ca, char const * const val) +{ + if (ca == NULL || val == NULL) + { + return; + } + + free(ca->value); + ca->value = strdup(val); +} + +char const * get_cmdarg(struct cmdarg const * const ca) +{ + if (ca == NULL) + { + return NULL; + } + + if (ca->value != NULL) + { + return ca->value; + } + + return ca->default_value; +} + +int is_cmdarg_set(struct cmdarg const * const ca) +{ + if (ca == NULL) + { + return 0; + } + + return ca->value != NULL; +} + void daemonize_enable(void) { daemonize = 1; @@ -182,8 +219,7 @@ int change_user_group(char const * const user, if (uds_collector_path != NULL) { errno = 0; - if (chmod(uds_collector_path, S_IRUSR | S_IWUSR) != 0 || - chown(uds_collector_path, pwd->pw_uid, gid) != 0) + if (chmod(uds_collector_path, S_IRUSR | S_IWUSR) != 0 || chown(uds_collector_path, pwd->pw_uid, gid) != 0) { return -errno; } @@ -3,6 +3,23 @@ #include <stdarg.h> +#define CMDARG(_default_value) \ + { \ + .value = NULL, .default_value = (_default_value) \ + } + +struct cmdarg +{ + char * value; + char const * const default_value; +}; + +void set_cmdarg(struct cmdarg * const ca, char const * const val); + +char const * get_cmdarg(struct cmdarg const * const ca); + +int is_cmdarg_set(struct cmdarg const * const ca); + int is_path_absolute(char const * const prefix, char const * const path); void daemonize_enable(void); |