mirror of
				https://github.com/optim-enterprises-bv/nDPId.git
				synced 2025-10-29 17:32:23 +00:00 
			
		
		
		
	Read and parse configuration files. Fixes #41. * supports nDPId / nDPIsrvd via command line parameter `-f` * nDPId: read general/tuning and libnDPI settings * support for settings risk domains libnDPI option via config file or via `-R` (Fixes #45, thanks to @UnveilTech) * added some documentation in the config file * adjusted Systemd and Debian packaging to make use of config files Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
This commit is contained in:
		| @@ -22,6 +22,11 @@ find_package(PkgConfig REQUIRED) | |||||||
|  |  | ||||||
| set(CPACK_PACKAGE_CONTACT "toni@impl.cc") | set(CPACK_PACKAGE_CONTACT "toni@impl.cc") | ||||||
| set(CPACK_DEBIAN_PACKAGE_NAME "nDPId") | set(CPACK_DEBIAN_PACKAGE_NAME "nDPId") | ||||||
|  | set(CPACK_DEBIAN_PACKAGE_SECTION "network") | ||||||
|  | set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "nDPId is a set of daemons and tools to capture, process and classify network traffic.") | ||||||
|  | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Toni Uhlig") | ||||||
|  | set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/packages/debian/preinst;${CMAKE_SOURCE_DIR}/packages/debian/prerm;${CMAKE_SOURCE_DIR}/packages/debian/postrm") | ||||||
|  | set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE) | ||||||
| set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) | ||||||
| set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON) | set(CPACK_DEBIAN_DEBUGINFO_PACKAGE ON) | ||||||
| set(CPACK_STRIP_FILES ON) | set(CPACK_STRIP_FILES ON) | ||||||
| @@ -516,7 +521,9 @@ if(ENABLE_SYSTEMD) | |||||||
|     configure_file(packages/systemd/ndpisrvd.service.in ndpisrvd.service @ONLY) |     configure_file(packages/systemd/ndpisrvd.service.in ndpisrvd.service @ONLY) | ||||||
|     configure_file(packages/systemd/ndpid@.service.in ndpid@.service @ONLY) |     configure_file(packages/systemd/ndpid@.service.in ndpid@.service @ONLY) | ||||||
|  |  | ||||||
|     install(FILES packages/systemd/default.cfg DESTINATION etc/default RENAME ndpid) |     install(DIRECTORY DESTINATION etc/nDPId) | ||||||
|  |     install(FILES "ndpid.conf.example" DESTINATION share/nDPId) | ||||||
|  |     install(FILES "ndpisrvd.conf.example" DESTINATION share/nDPId) | ||||||
|     install(FILES "${CMAKE_BINARY_DIR}/ndpisrvd.service" DESTINATION lib/systemd/system) |     install(FILES "${CMAKE_BINARY_DIR}/ndpisrvd.service" DESTINATION lib/systemd/system) | ||||||
|     install(FILES "${CMAKE_BINARY_DIR}/ndpid@.service" DESTINATION lib/systemd/system) |     install(FILES "${CMAKE_BINARY_DIR}/ndpid@.service" DESTINATION lib/systemd/system) | ||||||
| endif() | endif() | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								dependencies/nDPIsrvd.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								dependencies/nDPIsrvd.h
									
									
									
									
										vendored
									
									
								
							| @@ -33,8 +33,8 @@ | |||||||
| #define nDPIsrvd_JSON_KEY_STRLEN (32) | #define nDPIsrvd_JSON_KEY_STRLEN (32) | ||||||
| #define nDPIsrvd_HASHKEY_SEED (0x995fd871u) | #define nDPIsrvd_HASHKEY_SEED (0x995fd871u) | ||||||
|  |  | ||||||
| #define nDPIsrvd_ARRAY_LENGTH(s) (sizeof(s) / sizeof(s[0])) | #define nDPIsrvd_ARRAY_LENGTH(s) ((size_t)(sizeof(s) / sizeof(s[0]))) | ||||||
| #define nDPIsrvd_STRLEN_SZ(s) (sizeof(s) / sizeof(s[0]) - sizeof(s[0])) | #define nDPIsrvd_STRLEN_SZ(s) ((size_t)((sizeof(s) / sizeof(s[0])) - sizeof(s[0]))) | ||||||
| #define TOKEN_GET_SZ(sock, ...) nDPIsrvd_get_token(sock, __VA_ARGS__, NULL) | #define TOKEN_GET_SZ(sock, ...) nDPIsrvd_get_token(sock, __VA_ARGS__, NULL) | ||||||
| #define TOKEN_VALUE_EQUALS(sock, token, string_to_check, string_to_check_length)                                       \ | #define TOKEN_VALUE_EQUALS(sock, token, string_to_check, string_to_check_length)                                       \ | ||||||
|     nDPIsrvd_token_value_equals(sock, token, string_to_check, string_to_check_length) |     nDPIsrvd_token_value_equals(sock, token, string_to_check, string_to_check_length) | ||||||
|   | |||||||
| @@ -2059,7 +2059,7 @@ int main(int argc, char ** argv) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     errno = 0; |     errno = 0; | ||||||
|     if (user != NULL && change_user_group(user, group, pidfile, NULL, NULL) != 0) |     if (user != NULL && change_user_group(user, group, pidfile) != 0) | ||||||
|     { |     { | ||||||
|         if (errno != 0) |         if (errno != 0) | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ | |||||||
| #include "utarray.h" | #include "utarray.h" | ||||||
| #include "utils.h" | #include "utils.h" | ||||||
|  |  | ||||||
| //#define VERBOSE | // #define VERBOSE | ||||||
| #define DEFAULT_DATADIR "/tmp/nDPId-captured" | #define DEFAULT_DATADIR "/tmp/nDPId-captured" | ||||||
|  |  | ||||||
| struct packet_data | struct packet_data | ||||||
| @@ -1355,8 +1355,14 @@ int main(int argc, char ** argv) | |||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (capture_mode != 0 && chmod_chown(datadir, S_IRWXU | S_IRGRP | S_IXGRP, user, group) != 0) | ||||||
|  |     { | ||||||
|  |         logger(1, "Could not chmod/chown `%s': %s", datadir, strerror(errno)); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     errno = 0; |     errno = 0; | ||||||
|     if (user != NULL && change_user_group(user, group, pidfile, datadir /* :D */, NULL) != 0) |     if (user != NULL && change_user_group(user, group, pidfile) != 0) | ||||||
|     { |     { | ||||||
|         if (errno != 0) |         if (errno != 0) | ||||||
|         { |         { | ||||||
| @@ -1368,10 +1374,6 @@ int main(int argc, char ** argv) | |||||||
|         } |         } | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     if (datadir != NULL) |  | ||||||
|     { |  | ||||||
|         chmod(datadir, S_IRWXU); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (nDPIsrvd_set_read_timeout(ndpisrvd_socket, 180, 0) != 0) |     if (nDPIsrvd_set_read_timeout(ndpisrvd_socket, 180, 0) != 0) | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -1671,7 +1671,7 @@ int main(int argc, char ** argv) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     errno = 0; |     errno = 0; | ||||||
|     if (user != NULL && change_user_group(user, group, pidfile, NULL, NULL) != 0) |     if (user != NULL && change_user_group(user, group, pidfile) != 0) | ||||||
|     { |     { | ||||||
|         if (errno != 0) |         if (errno != 0) | ||||||
|         { |         { | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								nDPId-test.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								nDPId-test.c
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ extern void nDPIsrvd_memprof_log(char const * const format, ...); | |||||||
| extern void nDPIsrvd_memprof_log_alloc(size_t alloc_size); | extern void nDPIsrvd_memprof_log_alloc(size_t alloc_size); | ||||||
| extern void nDPIsrvd_memprof_log_free(size_t free_size); | extern void nDPIsrvd_memprof_log_free(size_t free_size); | ||||||
|  |  | ||||||
| //#define VERBOSE_MEMORY_PROFILING 1 | // #define VERBOSE_MEMORY_PROFILING 1 | ||||||
| #define NO_MAIN 1 | #define NO_MAIN 1 | ||||||
| #include "utils.c" | #include "utils.c" | ||||||
| #include "nio.c" | #include "nio.c" | ||||||
| @@ -1315,7 +1315,7 @@ static void * nDPId_mainloop_thread(void * const arg) | |||||||
|     } |     } | ||||||
|     run_capture_loop(&reader_threads[0]); |     run_capture_loop(&reader_threads[0]); | ||||||
|     process_remaining_flows(); |     process_remaining_flows(); | ||||||
|     for (size_t i = 0; i < nDPId_options.reader_thread_count; ++i) |     for (size_t i = 0; i < GET_CMDARG_ULL(nDPId_options.reader_thread_count); ++i) | ||||||
|     { |     { | ||||||
|         nrv->packets_captured += reader_threads[i].workflow->packets_captured; |         nrv->packets_captured += reader_threads[i].workflow->packets_captured; | ||||||
|         nrv->packets_processed += reader_threads[i].workflow->packets_processed; |         nrv->packets_processed += reader_threads[i].workflow->packets_processed; | ||||||
| @@ -1667,27 +1667,30 @@ int main(int argc, char ** argv) | |||||||
|         return retval; |         return retval; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     nDPIsrvd_options.max_write_buffers = 32; |     set_cmdarg_ull(&nDPIsrvd_options.max_write_buffers, 32); | ||||||
|     nDPId_options.enable_data_analysis = 1; |     set_cmdarg_boolean(&nDPId_options.enable_data_analysis, 1); | ||||||
|     nDPId_options.max_packets_per_flow_to_send = 5; |     set_cmdarg_ull(&nDPId_options.max_packets_per_flow_to_send, 5); | ||||||
| #ifdef ENABLE_ZLIB | #ifdef ENABLE_ZLIB | ||||||
|     /* |     /* | ||||||
|      * zLib compression is forced enabled for testing. |      * zLib compression is forced enabled for testing. | ||||||
|      * Remember to compile nDPId with zlib enabled. |      * Remember to compile nDPId with zlib enabled. | ||||||
|      * There will be diff's while running `test/run_tests.sh' otherwise. |      * There will be diff's while running `test/run_tests.sh' otherwise. | ||||||
|      */ |      */ | ||||||
|     nDPId_options.enable_zlib_compression = 1; |     set_cmdarg_boolean(&nDPId_options.enable_zlib_compression, 1); | ||||||
| #endif | #endif | ||||||
|     nDPId_options.memory_profiling_log_interval = (unsigned long long int)-1; |     set_cmdarg_ull(&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 |     set_cmdarg_ull(&nDPId_options.reader_thread_count, 1); /* Please do not change this! Generating meaningful pcap | ||||||
|                                               single reader thread! */ |                                               diff's relies on a single reader thread! */ | ||||||
|     set_cmdarg(&nDPId_options.instance_alias, "nDPId-test"); |     set_cmdarg_string(&nDPId_options.instance_alias, "nDPId-test"); | ||||||
|     if (access(argv[1], R_OK) != 0) |     if (access(argv[1], R_OK) != 0) | ||||||
|     { |     { | ||||||
|         logger(1, "%s: pcap file `%s' does not exist or is not readable", argv[0], argv[1]); |         logger(1, "%s: pcap file `%s' does not exist or is not readable", argv[0], argv[1]); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     set_cmdarg(&nDPId_options.pcap_file_or_interface, argv[1]); |     set_cmdarg_string(&nDPId_options.pcap_file_or_interface, argv[1]); | ||||||
|  |     set_config_defaults(&config_map[0], nDPIsrvd_ARRAY_LENGTH(config_map)); | ||||||
|  |     set_config_defaults(&general_config_map[0], nDPIsrvd_ARRAY_LENGTH(general_config_map)); | ||||||
|  |     set_config_defaults(&tuning_config_map[0], nDPIsrvd_ARRAY_LENGTH(tuning_config_map)); | ||||||
|     if (validate_options() != 0) |     if (validate_options() != 0) | ||||||
|     { |     { | ||||||
|         return 1; |         return 1; | ||||||
| @@ -1845,10 +1848,12 @@ int main(int argc, char ** argv) | |||||||
|             "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", |             "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", | ||||||
|             total_alloc_bytes - |             total_alloc_bytes - | ||||||
|                 sizeof(struct nDPId_workflow) * |                 sizeof(struct nDPId_workflow) * | ||||||
|                     nDPId_options.reader_thread_count /* We do not want to take the workflow into account. */, |                     GET_CMDARG_ULL( | ||||||
|  |                         nDPId_options.reader_thread_count) /* We do not want to take the workflow into account. */, | ||||||
|             total_free_bytes - |             total_free_bytes - | ||||||
|                 sizeof(struct nDPId_workflow) * |                 sizeof(struct nDPId_workflow) * | ||||||
|                     nDPId_options.reader_thread_count /* We do not want to take the workflow into account. */, |                     GET_CMDARG_ULL( | ||||||
|  |                         nDPId_options.reader_thread_count) /* We do not want to take the workflow into account. */, | ||||||
|             total_alloc_count, |             total_alloc_count, | ||||||
|             total_free_count); |             total_free_count); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										372
									
								
								nDPIsrvd.c
									
									
									
									
									
								
							
							
						
						
									
										372
									
								
								nDPIsrvd.c
									
									
									
									
									
								
							| @@ -90,27 +90,54 @@ static struct nDPIsrvd_address distributor_in_address = { | |||||||
|  |  | ||||||
| static struct | static struct | ||||||
| { | { | ||||||
|  |     struct cmdarg config_file; | ||||||
|     struct cmdarg pidfile; |     struct cmdarg pidfile; | ||||||
|     struct cmdarg collector_un_sockpath; |     struct cmdarg collector_un_sockpath; | ||||||
|     struct cmdarg distributor_un_sockpath; |     struct cmdarg distributor_un_sockpath; | ||||||
|     struct cmdarg distributor_in_address; |     struct cmdarg distributor_in_address; | ||||||
|     struct cmdarg user; |     struct cmdarg user; | ||||||
|     struct cmdarg group; |     struct cmdarg group; | ||||||
|     nDPIsrvd_ull max_remote_descriptors; |     struct cmdarg collector_group; | ||||||
|     nDPIsrvd_ull max_write_buffers; |     struct cmdarg distributor_group; | ||||||
|     uint8_t bufferbloat_fallback_to_blocking; |     struct cmdarg max_remote_descriptors; | ||||||
|  |     struct cmdarg max_write_buffers; | ||||||
|  |     struct cmdarg bufferbloat_fallback_to_blocking; | ||||||
| #ifdef ENABLE_EPOLL | #ifdef ENABLE_EPOLL | ||||||
|     uint8_t use_poll; |     struct cmdarg use_poll; | ||||||
| #endif | #endif | ||||||
| } nDPIsrvd_options = {.pidfile = CMDARG(nDPIsrvd_PIDFILE), | } nDPIsrvd_options = {.config_file = CMDARG_STR(NULL), | ||||||
|                       .collector_un_sockpath = CMDARG(COLLECTOR_UNIX_SOCKET), |                       .pidfile = CMDARG_STR(nDPIsrvd_PIDFILE), | ||||||
|                       .distributor_un_sockpath = CMDARG(DISTRIBUTOR_UNIX_SOCKET), |                       .collector_un_sockpath = CMDARG_STR(COLLECTOR_UNIX_SOCKET), | ||||||
|                       .distributor_in_address = CMDARG(NULL), |                       .distributor_un_sockpath = CMDARG_STR(DISTRIBUTOR_UNIX_SOCKET), | ||||||
|                       .user = CMDARG(DEFAULT_CHUSER), |                       .distributor_in_address = CMDARG_STR(NULL), | ||||||
|                       .group = CMDARG(NULL), |                       .user = CMDARG_STR(DEFAULT_CHUSER), | ||||||
|                       .max_remote_descriptors = nDPIsrvd_MAX_REMOTE_DESCRIPTORS, |                       .group = CMDARG_STR(NULL), | ||||||
|                       .max_write_buffers = nDPIsrvd_MAX_WRITE_BUFFERS, |                       .collector_group = CMDARG_STR(NULL), | ||||||
|                       .bufferbloat_fallback_to_blocking = 1}; |                       .distributor_group = CMDARG_STR(NULL), | ||||||
|  |                       .max_remote_descriptors = CMDARG_ULL(nDPIsrvd_MAX_REMOTE_DESCRIPTORS), | ||||||
|  |                       .max_write_buffers = CMDARG_ULL(nDPIsrvd_MAX_WRITE_BUFFERS), | ||||||
|  |                       .bufferbloat_fallback_to_blocking = CMDARG_BOOL(1) | ||||||
|  | #ifdef ENABLE_EPOLL | ||||||
|  |                           , | ||||||
|  |                       .use_poll = CMDARG_BOOL(0) | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  | struct confopt config_map[] = {CONFOPT("pidfile", &nDPIsrvd_options.pidfile), | ||||||
|  |                                CONFOPT("collector", &nDPIsrvd_options.collector_un_sockpath), | ||||||
|  |                                CONFOPT("distributor-unix", &nDPIsrvd_options.distributor_un_sockpath), | ||||||
|  |                                CONFOPT("distributor-in", &nDPIsrvd_options.distributor_in_address), | ||||||
|  |                                CONFOPT("user", &nDPIsrvd_options.user), | ||||||
|  |                                CONFOPT("group", &nDPIsrvd_options.group), | ||||||
|  |                                CONFOPT("collector-group", &nDPIsrvd_options.collector_group), | ||||||
|  |                                CONFOPT("distributor-group", &nDPIsrvd_options.distributor_group), | ||||||
|  |                                CONFOPT("max-remote-descriptors", &nDPIsrvd_options.max_remote_descriptors), | ||||||
|  |                                CONFOPT("max-write-buffers", &nDPIsrvd_options.max_write_buffers), | ||||||
|  |                                CONFOPT("blocking-io-fallback", &nDPIsrvd_options.bufferbloat_fallback_to_blocking) | ||||||
|  | #ifdef ENABLE_EPOLL | ||||||
|  |                                    , | ||||||
|  |                                CONFOPT("poll", &nDPIsrvd_options.use_poll) | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
| static void logger_nDPIsrvd(struct remote_desc const * const remote, | static void logger_nDPIsrvd(struct remote_desc const * const remote, | ||||||
|                             char const * const prefix, |                             char const * const prefix, | ||||||
| @@ -239,9 +266,9 @@ static int add_to_additional_write_buffers(struct remote_desc * const remote, | |||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (utarray_len(additional_write_buffers) >= nDPIsrvd_options.max_write_buffers) |     if (utarray_len(additional_write_buffers) >= GET_CMDARG_ULL(nDPIsrvd_options.max_write_buffers)) | ||||||
|     { |     { | ||||||
|         if (nDPIsrvd_options.bufferbloat_fallback_to_blocking == 0) |         if (GET_CMDARG_BOOL(nDPIsrvd_options.bufferbloat_fallback_to_blocking) == 0) | ||||||
|         { |         { | ||||||
|             logger_nDPIsrvd(remote, |             logger_nDPIsrvd(remote, | ||||||
|                             "Buffer limit for", |                             "Buffer limit for", | ||||||
| @@ -498,7 +525,7 @@ static int create_listen_sockets(void) | |||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0) |     if (IS_CMDARG_SET(nDPIsrvd_options.distributor_in_address) != 0) | ||||||
|     { |     { | ||||||
|         distributor_in_sockfd = socket(distributor_in_address.raw.sa_family, SOCK_STREAM, 0); |         distributor_in_sockfd = socket(distributor_in_address.raw.sa_family, SOCK_STREAM, 0); | ||||||
|         if (distributor_in_sockfd < 0 || set_fd_cloexec(distributor_in_sockfd) < 0) |         if (distributor_in_sockfd < 0 || set_fd_cloexec(distributor_in_sockfd) < 0) | ||||||
| @@ -528,7 +555,7 @@ static int create_listen_sockets(void) | |||||||
|         int written = snprintf(collector_addr.sun_path, |         int written = snprintf(collector_addr.sun_path, | ||||||
|                                sizeof(collector_addr.sun_path), |                                sizeof(collector_addr.sun_path), | ||||||
|                                "%s", |                                "%s", | ||||||
|                                get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); |                                GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath)); | ||||||
|         if (written < 0) |         if (written < 0) | ||||||
|         { |         { | ||||||
|             logger(1, "snprintf failed: %s", strerror(errno)); |             logger(1, "snprintf failed: %s", strerror(errno)); | ||||||
| @@ -536,10 +563,7 @@ static int create_listen_sockets(void) | |||||||
|         } |         } | ||||||
|         else if (written == sizeof(collector_addr.sun_path)) |         else if (written == sizeof(collector_addr.sun_path)) | ||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, "Collector UNIX socket path too long, max: %zu characters", sizeof(collector_addr.sun_path) - 1); | ||||||
|                    "Collector UNIX socket path too long, current/max: %zu/%zu", |  | ||||||
|                    strlen(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)), |  | ||||||
|                    sizeof(collector_addr.sun_path) - 1); |  | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -547,7 +571,7 @@ static int create_listen_sockets(void) | |||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Error binding Collector UNIX socket to `%s': %s", |                    "Error binding Collector UNIX socket to `%s': %s", | ||||||
|                    get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), |                    GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), | ||||||
|                    strerror(errno)); |                    strerror(errno)); | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
| @@ -559,7 +583,7 @@ static int create_listen_sockets(void) | |||||||
|         int written = snprintf(distributor_addr.sun_path, |         int written = snprintf(distributor_addr.sun_path, | ||||||
|                                sizeof(distributor_addr.sun_path), |                                sizeof(distributor_addr.sun_path), | ||||||
|                                "%s", |                                "%s", | ||||||
|                                get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); |                                GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath)); | ||||||
|         if (written < 0) |         if (written < 0) | ||||||
|         { |         { | ||||||
|             logger(1, "snprintf failed: %s", strerror(errno)); |             logger(1, "snprintf failed: %s", strerror(errno)); | ||||||
| @@ -568,8 +592,7 @@ static int create_listen_sockets(void) | |||||||
|         else if (written == sizeof(distributor_addr.sun_path)) |         else if (written == sizeof(distributor_addr.sun_path)) | ||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Distributor UNIX socket path too long, current/max: %zu/%zu", |                    "Distributor UNIX socket path too long, max: %zu characters", | ||||||
|                    strlen(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)), |  | ||||||
|                    sizeof(distributor_addr.sun_path) - 1); |                    sizeof(distributor_addr.sun_path) - 1); | ||||||
|             return 2; |             return 2; | ||||||
|         } |         } | ||||||
| @@ -578,19 +601,19 @@ static int create_listen_sockets(void) | |||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Error binding Distributor socket to `%s': %s", |                    "Error binding Distributor socket to `%s': %s", | ||||||
|                    get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath), |                    GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath), | ||||||
|                    strerror(errno)); |                    strerror(errno)); | ||||||
|             return 2; |             return 2; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0) |     if (IS_CMDARG_SET(nDPIsrvd_options.distributor_in_address) != 0) | ||||||
|     { |     { | ||||||
|         if (bind(distributor_in_sockfd, &distributor_in_address.raw, distributor_in_address.size) < 0) |         if (bind(distributor_in_sockfd, &distributor_in_address.raw, distributor_in_address.size) < 0) | ||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Error binding Distributor TCP/IP socket to %s: %s", |                    "Error binding Distributor TCP/IP socket to %s: %s", | ||||||
|                    get_cmdarg(&nDPIsrvd_options.distributor_in_address), |                    GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address), | ||||||
|                    strerror(errno)); |                    strerror(errno)); | ||||||
|             return 3; |             return 3; | ||||||
|         } |         } | ||||||
| @@ -598,7 +621,7 @@ static int create_listen_sockets(void) | |||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Error listening Distributor TCP/IP socket to %s: %s", |                    "Error listening Distributor TCP/IP socket to %s: %s", | ||||||
|                    get_cmdarg(&nDPIsrvd_options.distributor_in_address), |                    GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address), | ||||||
|                    strerror(errno)); |                    strerror(errno)); | ||||||
|             return 3; |             return 3; | ||||||
|         } |         } | ||||||
| @@ -606,7 +629,7 @@ static int create_listen_sockets(void) | |||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Error setting Distributor TCP/IP socket %s to non-blocking mode: %s", |                    "Error setting Distributor TCP/IP socket %s to non-blocking mode: %s", | ||||||
|                    get_cmdarg(&nDPIsrvd_options.distributor_in_address), |                    GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address), | ||||||
|                    strerror(errno)); |                    strerror(errno)); | ||||||
|             return 3; |             return 3; | ||||||
|         } |         } | ||||||
| @@ -622,7 +645,7 @@ static int create_listen_sockets(void) | |||||||
|     { |     { | ||||||
|         logger(1, |         logger(1, | ||||||
|                "Error setting Collector UNIX socket `%s' to non-blocking mode: %s", |                "Error setting Collector UNIX socket `%s' to non-blocking mode: %s", | ||||||
|                get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), |                GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), | ||||||
|                strerror(errno)); |                strerror(errno)); | ||||||
|         return 3; |         return 3; | ||||||
|     } |     } | ||||||
| @@ -631,7 +654,7 @@ static int create_listen_sockets(void) | |||||||
|     { |     { | ||||||
|         logger(1, |         logger(1, | ||||||
|                "Error setting Distributor UNIX socket `%s' to non-blocking mode: %s", |                "Error setting Distributor UNIX socket `%s' to non-blocking mode: %s", | ||||||
|                get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath), |                GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath), | ||||||
|                strerror(errno)); |                strerror(errno)); | ||||||
|         return 3; |         return 3; | ||||||
|     } |     } | ||||||
| @@ -804,10 +827,13 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) | |||||||
| { | { | ||||||
|     int opt; |     int opt; | ||||||
|  |  | ||||||
|     while ((opt = getopt(argc, argv, "lL:c:dp:s:S:m:u:g:C:Dvh")) != -1) |     while ((opt = getopt(argc, argv, "f:lL:c:dp:s:S:G:m:u:g:C:Dvh")) != -1) | ||||||
|     { |     { | ||||||
|         switch (opt) |         switch (opt) | ||||||
|         { |         { | ||||||
|  |             case 'f': | ||||||
|  |                 set_cmdarg_string(&nDPIsrvd_options.config_file, optarg); | ||||||
|  |                 break; | ||||||
|             case 'l': |             case 'l': | ||||||
|                 enable_console_logger(); |                 enable_console_logger(); | ||||||
|                 break; |                 break; | ||||||
| @@ -818,11 +844,11 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) | |||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             case 'c': |             case 'c': | ||||||
|                 set_cmdarg(&nDPIsrvd_options.collector_un_sockpath, optarg); |                 set_cmdarg_string(&nDPIsrvd_options.collector_un_sockpath, optarg); | ||||||
|                 break; |                 break; | ||||||
|             case 'e': |             case 'e': | ||||||
| #ifdef ENABLE_EPOLL | #ifdef ENABLE_EPOLL | ||||||
|                 nDPIsrvd_options.use_poll = 1; |                 set_cmdarg_boolean(&nDPIsrvd_options.use_poll, 1); | ||||||
| #else | #else | ||||||
|                 logger_early(1, "%s", "nDPIsrvd was built w/o epoll() support, poll() is already the default"); |                 logger_early(1, "%s", "nDPIsrvd was built w/o epoll() support, poll() is already the default"); | ||||||
| #endif | #endif | ||||||
| @@ -831,36 +857,67 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) | |||||||
|                 daemonize_enable(); |                 daemonize_enable(); | ||||||
|                 break; |                 break; | ||||||
|             case 'p': |             case 'p': | ||||||
|                 set_cmdarg(&nDPIsrvd_options.pidfile, optarg); |                 set_cmdarg_string(&nDPIsrvd_options.pidfile, optarg); | ||||||
|                 break; |                 break; | ||||||
|             case 's': |             case 's': | ||||||
|                 set_cmdarg(&nDPIsrvd_options.distributor_un_sockpath, optarg); |                 set_cmdarg_string(&nDPIsrvd_options.distributor_un_sockpath, optarg); | ||||||
|                 break; |                 break; | ||||||
|             case 'S': |             case 'S': | ||||||
|                 set_cmdarg(&nDPIsrvd_options.distributor_in_address, optarg); |                 set_cmdarg_string(&nDPIsrvd_options.distributor_in_address, optarg); | ||||||
|                 break; |                 break; | ||||||
|  |             case 'G': | ||||||
|  |             { | ||||||
|  |                 char const * const sep = strchr(optarg, ':'); | ||||||
|  |                 char group[256]; | ||||||
|  |  | ||||||
|  |                 if (sep == NULL) | ||||||
|  |                 { | ||||||
|  |                     fprintf(stderr, "%s: Argument for `-G' is not in the format group:group\n", argv[0]); | ||||||
|  |                     return 1; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (snprintf(group, sizeof(group), "%.*s", (int)(sep - optarg), optarg) > 0) | ||||||
|  |                 { | ||||||
|  |                     set_cmdarg_string(&nDPIsrvd_options.collector_group, group); | ||||||
|  |                 } | ||||||
|  |                 if (snprintf(group, sizeof(group), "%s", sep + 1) > 0) | ||||||
|  |                 { | ||||||
|  |                     set_cmdarg_string(&nDPIsrvd_options.distributor_group, group); | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|             case 'm': |             case 'm': | ||||||
|                 if (str_value_to_ull(optarg, &nDPIsrvd_options.max_remote_descriptors) != CONVERSION_OK) |             { | ||||||
|  |                 nDPIsrvd_ull tmp; | ||||||
|  |  | ||||||
|  |                 if (str_value_to_ull(optarg, &tmp) != CONVERSION_OK) | ||||||
|                 { |                 { | ||||||
|                     fprintf(stderr, "%s: Argument for `-C' is not a number: %s\n", argv[0], optarg); |                     fprintf(stderr, "%s: Argument for `-C' is not a number: %s\n", argv[0], optarg); | ||||||
|                     return 1; |                     return 1; | ||||||
|                 } |                 } | ||||||
|  |                 set_cmdarg_ull(&nDPIsrvd_options.max_remote_descriptors, tmp); | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|             case 'u': |             case 'u': | ||||||
|                 set_cmdarg(&nDPIsrvd_options.user, optarg); |                 set_cmdarg_string(&nDPIsrvd_options.user, optarg); | ||||||
|                 break; |                 break; | ||||||
|             case 'g': |             case 'g': | ||||||
|                 set_cmdarg(&nDPIsrvd_options.group, optarg); |                 set_cmdarg_string(&nDPIsrvd_options.group, optarg); | ||||||
|                 break; |                 break; | ||||||
|             case 'C': |             case 'C': | ||||||
|                 if (str_value_to_ull(optarg, &nDPIsrvd_options.max_write_buffers) != CONVERSION_OK) |             { | ||||||
|  |                 nDPIsrvd_ull tmp; | ||||||
|  |  | ||||||
|  |                 if (str_value_to_ull(optarg, &tmp) != CONVERSION_OK) | ||||||
|                 { |                 { | ||||||
|                     fprintf(stderr, "%s: Argument for `-C' is not a number: %s\n", argv[0], optarg); |                     fprintf(stderr, "%s: Argument for `-C' is not a number: %s\n", argv[0], optarg); | ||||||
|                     return 1; |                     return 1; | ||||||
|                 } |                 } | ||||||
|  |                 set_cmdarg_ull(&nDPIsrvd_options.max_write_buffers, tmp); | ||||||
|                 break; |                 break; | ||||||
|  |             } | ||||||
|             case 'D': |             case 'D': | ||||||
|                 nDPIsrvd_options.bufferbloat_fallback_to_blocking = 0; |                 set_cmdarg_boolean(&nDPIsrvd_options.bufferbloat_fallback_to_blocking, 0); | ||||||
|                 break; |                 break; | ||||||
|             case 'v': |             case 'v': | ||||||
|                 fprintf(stderr, "%s", get_nDPId_version()); |                 fprintf(stderr, "%s", get_nDPId_version()); | ||||||
| @@ -869,11 +926,14 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) | |||||||
|             default: |             default: | ||||||
|                 fprintf(stderr, "%s\n", get_nDPId_version()); |                 fprintf(stderr, "%s\n", get_nDPId_version()); | ||||||
|                 fprintf(stderr, |                 fprintf(stderr, | ||||||
|                         "Usage: %s [-l] [-L logfile] [-c path-to-unix-sock] [-e] [-d] [-p pidfile]\n" |                         "Usage: %s [-f config-file] [-l] [-L logfile]\n" | ||||||
|  |                         "\t[-c path-to-unix-sock] [-e] [-d] [-p pidfile]\n" | ||||||
|                         "\t[-s path-to-distributor-unix-socket] [-S distributor-host:port]\n" |                         "\t[-s path-to-distributor-unix-socket] [-S distributor-host:port]\n" | ||||||
|  |                         "\t[-G collector-unix-socket-group:distributor-unix-socket-group]\n" | ||||||
|                         "\t[-m max-remote-descriptors] [-u user] [-g group]\n" |                         "\t[-m max-remote-descriptors] [-u user] [-g group]\n" | ||||||
|                         "\t[-C max-buffered-json-lines] [-D]\n" |                         "\t[-C max-buffered-json-lines] [-D]\n" | ||||||
|                         "\t[-v] [-h]\n\n" |                         "\t[-v] [-h]\n\n" | ||||||
|  |                         "\t-f\tLoad nDPIsrvd options from a configuration file.\n" | ||||||
|                         "\t-l\tLog all messages to stderr.\n" |                         "\t-l\tLog all messages to stderr.\n" | ||||||
|                         "\t-L\tLog all messages to a log file.\n" |                         "\t-L\tLog all messages to a log file.\n" | ||||||
|                         "\t-c\tPath to a listening UNIX socket (nDPIsrvd Collector).\n" |                         "\t-c\tPath to a listening UNIX socket (nDPIsrvd Collector).\n" | ||||||
| @@ -892,40 +952,45 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) | |||||||
|                         "\t-s\tPath to a listening UNIX socket (nDPIsrvd Distributor).\n" |                         "\t-s\tPath to a listening UNIX socket (nDPIsrvd Distributor).\n" | ||||||
|                         "\t  \tDefault: %s\n" |                         "\t  \tDefault: %s\n" | ||||||
|                         "\t-S\tAddress:Port of the listening TCP/IP socket (nDPIsrvd Distributor).\n" |                         "\t-S\tAddress:Port of the listening TCP/IP socket (nDPIsrvd Distributor).\n" | ||||||
|  |                         "\t-G\tGroup owner of the UNIX collector/distributor socket.\n" | ||||||
|  |                         "\t  \tDefault: Either the group set via `-g', otherwise the primary group of `-u'\n" | ||||||
|                         "\t-v\tversion\n" |                         "\t-v\tversion\n" | ||||||
|                         "\t-h\tthis\n\n", |                         "\t-h\tthis\n\n", | ||||||
|                         argv[0], |                         argv[0], | ||||||
|                         get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), |                         nDPIsrvd_options.collector_un_sockpath.string.default_value, | ||||||
|                         get_cmdarg(&nDPIsrvd_options.pidfile), |                         nDPIsrvd_options.pidfile.string.default_value, | ||||||
|                         get_cmdarg(&nDPIsrvd_options.user), |                         nDPIsrvd_options.user.string.default_value, | ||||||
|                         get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); |                         nDPIsrvd_options.distributor_un_sockpath.string.default_value); | ||||||
|                 return 1; |                 return 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (is_path_absolute("Pidfile", get_cmdarg(&nDPIsrvd_options.pidfile)) != 0) |     set_config_defaults(&config_map[0], nDPIsrvd_ARRAY_LENGTH(config_map)); | ||||||
|  |  | ||||||
|  |     if (is_path_absolute("Pidfile", GET_CMDARG_STR(nDPIsrvd_options.pidfile)) != 0) | ||||||
|     { |     { | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (is_path_absolute("Collector UNIX socket", get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)) != 0) |     if (is_path_absolute("Collector UNIX socket", GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath)) != 0) | ||||||
|     { |     { | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (is_path_absolute("Distributor UNIX socket", get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)) != 0) |     if (is_path_absolute("Distributor UNIX socket", GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath)) != 0) | ||||||
|     { |     { | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (is_cmdarg_set(&nDPIsrvd_options.distributor_in_address) != 0) |     if (IS_CMDARG_SET(nDPIsrvd_options.distributor_in_address) != 0) | ||||||
|     { |     { | ||||||
|         if (nDPIsrvd_setup_address(&distributor_in_address, get_cmdarg(&nDPIsrvd_options.distributor_in_address)) != 0) |         if (nDPIsrvd_setup_address(&distributor_in_address, GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address)) != | ||||||
|  |             0) | ||||||
|         { |         { | ||||||
|             logger_early(1, |             logger_early(1, | ||||||
|                          "%s: Could not parse address %s", |                          "%s: Could not parse address %s", | ||||||
|                          argv[0], |                          argv[0], | ||||||
|                          get_cmdarg(&nDPIsrvd_options.distributor_in_address)); |                          GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address)); | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
|         if (distributor_in_address.raw.sa_family == AF_UNIX) |         if (distributor_in_address.raw.sa_family == AF_UNIX) | ||||||
| @@ -933,8 +998,8 @@ static int nDPIsrvd_parse_options(int argc, char ** argv) | |||||||
|             logger_early(1, |             logger_early(1, | ||||||
|                          "%s: You've requested to setup another UNIX socket `%s', but there is already one at `%s'", |                          "%s: You've requested to setup another UNIX socket `%s', but there is already one at `%s'", | ||||||
|                          argv[0], |                          argv[0], | ||||||
|                          get_cmdarg(&nDPIsrvd_options.distributor_in_address), |                          GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address), | ||||||
|                          get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); |                          GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath)); | ||||||
|             return 1; |             return 1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -1516,8 +1581,9 @@ static int mainloop(struct nio * const io) | |||||||
| static int setup_event_queue(struct nio * const io) | static int setup_event_queue(struct nio * const io) | ||||||
| { | { | ||||||
| #ifdef ENABLE_EPOLL | #ifdef ENABLE_EPOLL | ||||||
|     if ((nDPIsrvd_options.use_poll == 0 && nio_use_epoll(io, 32) != NIO_SUCCESS) || |     if ((GET_CMDARG_BOOL(nDPIsrvd_options.use_poll) == 0 && nio_use_epoll(io, 32) != NIO_SUCCESS) || | ||||||
|         (nDPIsrvd_options.use_poll != 0 && nio_use_poll(io, nDPIsrvd_MAX_REMOTE_DESCRIPTORS) != NIO_SUCCESS)) |         (GET_CMDARG_BOOL(nDPIsrvd_options.use_poll) != 0 && | ||||||
|  |          nio_use_poll(io, nDPIsrvd_MAX_REMOTE_DESCRIPTORS) != NIO_SUCCESS)) | ||||||
| #else | #else | ||||||
|     if (nio_use_poll(io, nDPIsrvd_MAX_REMOTE_DESCRIPTORS) != NIO_SUCCESS) |     if (nio_use_poll(io, nDPIsrvd_MAX_REMOTE_DESCRIPTORS) != NIO_SUCCESS) | ||||||
| #endif | #endif | ||||||
| @@ -1576,6 +1642,49 @@ static int setup_remote_descriptors(nDPIsrvd_ull max_remote_descriptors) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int nDPIsrvd_parsed_config_line( | ||||||
|  |     int lineno, char const * const section, char const * const name, char const * const value, void * const user_data) | ||||||
|  | { | ||||||
|  |     (void)user_data; | ||||||
|  |  | ||||||
|  |     if (strnlen(section, INI_MAX_SECTION) == nDPIsrvd_STRLEN_SZ("general") && | ||||||
|  |         strncmp(section, "general", INI_MAX_SECTION) == 0) | ||||||
|  |     { | ||||||
|  |         size_t i; | ||||||
|  |  | ||||||
|  |         for (i = 0; i < nDPIsrvd_ARRAY_LENGTH(config_map); ++i) | ||||||
|  |         { | ||||||
|  |             if (strnlen(name, INI_MAX_NAME) == strnlen(config_map[i].key, INI_MAX_NAME) && | ||||||
|  |                 strncmp(name, config_map[i].key, INI_MAX_NAME) == 0) | ||||||
|  |             { | ||||||
|  |                 if (IS_CMDARG_SET(*config_map[i].opt) != 0) | ||||||
|  |                 { | ||||||
|  |                     logger_early(1, "General config key `%s' already set, ignoring value `%s'", name, value); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     if (set_config_from(&config_map[i], value) != 0) | ||||||
|  |                     { | ||||||
|  |                         return 0; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (i == nDPIsrvd_ARRAY_LENGTH(config_map)) | ||||||
|  |         { | ||||||
|  |             logger_early(1, "Invalid general config key `%s' at line %d", name, lineno); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         logger_early( | ||||||
|  |             1, "Invalid config section `%s' at line %d with key `%s' and value `%s'", section, lineno, name, value); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
| #ifndef NO_MAIN | #ifndef NO_MAIN | ||||||
| int main(int argc, char ** argv) | int main(int argc, char ** argv) | ||||||
| { | { | ||||||
| @@ -1594,6 +1703,32 @@ int main(int argc, char ** argv) | |||||||
|     { |     { | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |     { | ||||||
|  |         int ret; | ||||||
|  |  | ||||||
|  |         if (IS_CMDARG_SET(nDPIsrvd_options.config_file) != 0 && | ||||||
|  |             (ret = | ||||||
|  |                  parse_config_file(GET_CMDARG_STR(nDPIsrvd_options.config_file), nDPIsrvd_parsed_config_line, NULL)) != | ||||||
|  |                 0) | ||||||
|  |         { | ||||||
|  |             if (ret > 0) | ||||||
|  |             { | ||||||
|  |                 logger_early(1, "Config file `%s' is malformed", GET_CMDARG_STR(nDPIsrvd_options.config_file)); | ||||||
|  |             } | ||||||
|  |             else if (ret == -ENOENT) | ||||||
|  |             { | ||||||
|  |                 logger_early(1, "Path `%s' is not a regular file", GET_CMDARG_STR(nDPIsrvd_options.config_file)); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 logger_early(1, | ||||||
|  |                              "Could not open file `%s' for reading: %s", | ||||||
|  |                              GET_CMDARG_STR(nDPIsrvd_options.config_file), | ||||||
|  |                              strerror(errno)); | ||||||
|  |             } | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (is_daemonize_enabled() != 0 && is_console_logger_enabled() != 0) |     if (is_daemonize_enabled() != 0 && is_console_logger_enabled() != 0) | ||||||
|     { |     { | ||||||
| @@ -1604,32 +1739,32 @@ int main(int argc, char ** argv) | |||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (access(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), F_OK) == 0) |     if (access(GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), F_OK) == 0) | ||||||
|     { |     { | ||||||
|         logger_early(1, |         logger_early(1, | ||||||
|                      "UNIX socket `%s' exists; nDPIsrvd already running? " |                      "UNIX socket `%s' exists; nDPIsrvd already running? " | ||||||
|                      "Please remove the socket manually or change socket path.", |                      "Please remove the socket manually or change socket path.", | ||||||
|                      get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); |                      GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath)); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (access(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath), F_OK) == 0) |     if (access(GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath), F_OK) == 0) | ||||||
|     { |     { | ||||||
|         logger_early(1, |         logger_early(1, | ||||||
|                      "UNIX socket `%s' exists; nDPIsrvd already running? " |                      "UNIX socket `%s' exists; nDPIsrvd already running? " | ||||||
|                      "Please remove the socket manually or change socket path.", |                      "Please remove the socket manually or change socket path.", | ||||||
|                      get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); |                      GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath)); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     log_app_info(); |     log_app_info(); | ||||||
|  |  | ||||||
|     if (daemonize_with_pidfile(get_cmdarg(&nDPIsrvd_options.pidfile)) != 0) |     if (daemonize_with_pidfile(GET_CMDARG_STR(nDPIsrvd_options.pidfile)) != 0) | ||||||
|     { |     { | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (setup_remote_descriptors(nDPIsrvd_options.max_remote_descriptors) != 0) |     if (setup_remote_descriptors(GET_CMDARG_ULL(nDPIsrvd_options.max_remote_descriptors)) != 0) | ||||||
|     { |     { | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
| @@ -1641,11 +1776,11 @@ int main(int argc, char ** argv) | |||||||
|         case 1: |         case 1: | ||||||
|             goto error; |             goto error; | ||||||
|         case 2: |         case 2: | ||||||
|             if (unlink(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)) != 0) |             if (unlink(GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath)) != 0) | ||||||
|             { |             { | ||||||
|                 logger(1, |                 logger(1, | ||||||
|                        "Could not unlink `%s': %s", |                        "Could not unlink `%s': %s", | ||||||
|                        get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), |                        GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), | ||||||
|                        strerror(errno)); |                        strerror(errno)); | ||||||
|             } |             } | ||||||
|             goto error; |             goto error; | ||||||
| @@ -1655,8 +1790,8 @@ int main(int argc, char ** argv) | |||||||
|             goto error; |             goto error; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     logger(0, "collector UNIX socket listen on `%s'", get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)); |     logger(0, "collector UNIX socket listen on `%s'", GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath)); | ||||||
|     logger(0, "distributor UNIX listen on `%s'", get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)); |     logger(0, "distributor UNIX listen on `%s'", GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath)); | ||||||
|     switch (distributor_in_address.raw.sa_family) |     switch (distributor_in_address.raw.sa_family) | ||||||
|     { |     { | ||||||
|         default: |         default: | ||||||
| @@ -1672,28 +1807,88 @@ int main(int argc, char ** argv) | |||||||
|             break; |             break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     errno = 0; |     int ret = chmod_chown(GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), | ||||||
|     if (change_user_group(get_cmdarg(&nDPIsrvd_options.user), |                           S_IRUSR | S_IWUSR | S_IWGRP, | ||||||
|                           get_cmdarg(&nDPIsrvd_options.group), |                           GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|                           get_cmdarg(&nDPIsrvd_options.pidfile), |                           IS_CMDARG_SET(nDPIsrvd_options.collector_group) != 0 | ||||||
|                           get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), |                               ? GET_CMDARG_STR(nDPIsrvd_options.collector_group) | ||||||
|                           get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)) != 0 && |                               : GET_CMDARG_STR(nDPIsrvd_options.group)); | ||||||
|         errno != EPERM) |     if (ret != 0) | ||||||
|     { |     { | ||||||
|         if (errno != 0) |         if (IS_CMDARG_SET(nDPIsrvd_options.collector_group) != 0 || IS_CMDARG_SET(nDPIsrvd_options.group) != 0) | ||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Change user/group to %s/%s failed: %s", |                    "Could not chmod/chown `%s' to user `%s' and group `%s': %s", | ||||||
|                    get_cmdarg(&nDPIsrvd_options.user), |                    GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), | ||||||
|                    (is_cmdarg_set(&nDPIsrvd_options.group) != 0 ? get_cmdarg(&nDPIsrvd_options.group) : "-"), |                    GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|  |                    IS_CMDARG_SET(nDPIsrvd_options.collector_group) != 0 | ||||||
|  |                        ? GET_CMDARG_STR(nDPIsrvd_options.collector_group) | ||||||
|  |                        : GET_CMDARG_STR(nDPIsrvd_options.group), | ||||||
|                    strerror(errno)); |                    strerror(errno)); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             logger(1, |             logger(1, | ||||||
|                    "Change user/group to %s/%s failed.", |                    "Could not chmod/chown `%s' to user `%s': %s", | ||||||
|                    get_cmdarg(&nDPIsrvd_options.user), |                    GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), | ||||||
|                    (is_cmdarg_set(&nDPIsrvd_options.group) != 0 ? get_cmdarg(&nDPIsrvd_options.group) : "-")); |                    GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|  |                    strerror(errno)); | ||||||
|  |         } | ||||||
|  |         if (ret != -EPERM) | ||||||
|  |         { | ||||||
|  |             goto error_unlink_sockets; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ret = chmod_chown(GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath), | ||||||
|  |                       S_IRUSR | S_IWUSR | S_IWGRP, | ||||||
|  |                       GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|  |                       IS_CMDARG_SET(nDPIsrvd_options.distributor_group) != 0 | ||||||
|  |                           ? GET_CMDARG_STR(nDPIsrvd_options.distributor_group) | ||||||
|  |                           : GET_CMDARG_STR(nDPIsrvd_options.group)); | ||||||
|  |     if (ret != 0) | ||||||
|  |     { | ||||||
|  |         if (IS_CMDARG_SET(nDPIsrvd_options.distributor_group) != 0 || IS_CMDARG_SET(nDPIsrvd_options.group) != 0) | ||||||
|  |         { | ||||||
|  |             logger(1, | ||||||
|  |                    "Could not chmod/chown `%s' to user `%s' and group `%s': %s", | ||||||
|  |                    GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath), | ||||||
|  |                    GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|  |                    IS_CMDARG_SET(nDPIsrvd_options.distributor_group) != 0 | ||||||
|  |                        ? GET_CMDARG_STR(nDPIsrvd_options.distributor_group) | ||||||
|  |                        : GET_CMDARG_STR(nDPIsrvd_options.group), | ||||||
|  |                    strerror(errno)); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             logger(1, | ||||||
|  |                    "Could not chmod/chown `%s' to user `%s': %s", | ||||||
|  |                    GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath), | ||||||
|  |                    GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|  |                    strerror(errno)); | ||||||
|  |         } | ||||||
|  |         if (ret != -EPERM) | ||||||
|  |         { | ||||||
|  |             goto error_unlink_sockets; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ret = change_user_group(GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|  |                             GET_CMDARG_STR(nDPIsrvd_options.group), | ||||||
|  |                             GET_CMDARG_STR(nDPIsrvd_options.pidfile)); | ||||||
|  |     if (ret != 0 && ret != -EPERM) | ||||||
|  |     { | ||||||
|  |         if (GET_CMDARG_STR(nDPIsrvd_options.group) != NULL) | ||||||
|  |         { | ||||||
|  |             logger(1, | ||||||
|  |                    "Change user/group to %s/%s failed: %s", | ||||||
|  |                    GET_CMDARG_STR(nDPIsrvd_options.user), | ||||||
|  |                    GET_CMDARG_STR(nDPIsrvd_options.group), | ||||||
|  |                    strerror(-ret)); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             logger(1, "Change user to %s failed: %s", GET_CMDARG_STR(nDPIsrvd_options.user), strerror(-ret)); | ||||||
|         } |         } | ||||||
|         goto error_unlink_sockets; |         goto error_unlink_sockets; | ||||||
|     } |     } | ||||||
| @@ -1713,20 +1908,23 @@ int main(int argc, char ** argv) | |||||||
|     retval = mainloop(&io); |     retval = mainloop(&io); | ||||||
|  |  | ||||||
| error_unlink_sockets: | error_unlink_sockets: | ||||||
|     if (unlink(get_cmdarg(&nDPIsrvd_options.collector_un_sockpath)) != 0) |     if (unlink(GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath)) != 0) | ||||||
|     { |     { | ||||||
|         logger(1, "Could not unlink `%s': %s", get_cmdarg(&nDPIsrvd_options.collector_un_sockpath), strerror(errno)); |         logger(1, "Could not unlink `%s': %s", GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath), strerror(errno)); | ||||||
|     } |     } | ||||||
|     if (unlink(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)) != 0) |     if (unlink(GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath)) != 0) | ||||||
|     { |     { | ||||||
|         logger(1, "Could not unlink `%s': %s", get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath), strerror(errno)); |         logger(1, | ||||||
|  |                "Could not unlink `%s': %s", | ||||||
|  |                GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath), | ||||||
|  |                strerror(errno)); | ||||||
|     } |     } | ||||||
| error: | error: | ||||||
|     close(collector_un_sockfd); |     close(collector_un_sockfd); | ||||||
|     close(distributor_un_sockfd); |     close(distributor_un_sockfd); | ||||||
|     close(distributor_in_sockfd); |     close(distributor_in_sockfd); | ||||||
|  |  | ||||||
|     daemonize_shutdown(get_cmdarg(&nDPIsrvd_options.pidfile)); |     daemonize_shutdown(GET_CMDARG_STR(nDPIsrvd_options.pidfile)); | ||||||
|     logger(0, "Bye."); |     logger(0, "Bye."); | ||||||
|     shutdown_logging(); |     shutdown_logging(); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										86
									
								
								ndpid.conf.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								ndpid.conf.example
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | [general] | ||||||
|  | # Set the network interface from which packets are captured and processed. | ||||||
|  | # Leave it empty to let nDPId choose the default network interface. | ||||||
|  | #netif       = eth0 | ||||||
|  |  | ||||||
|  | # Set a Berkeley Packet Filter. | ||||||
|  | # This will work for libpcap as well as with PF_RING. | ||||||
|  | #bpf         = udp or tcp | ||||||
|  |  | ||||||
|  | #pidfile     = /tmp/ndpid.pid | ||||||
|  | #user        = nobody | ||||||
|  | #group       = daemon | ||||||
|  | #riskdomains = /path/to/libnDPI/example/risky_domains.txt | ||||||
|  | #protocols   = /path/to/libnDPI/example/protos.txt | ||||||
|  | #categories  = /path/to/libnDPI/example/categories.txt | ||||||
|  | #ja3         = /path/to/libnDPI/example/ja3_fingerprints.csv | ||||||
|  | #sha1        = /path/to/libnDPI/example/sha1_fingerprints.csv | ||||||
|  |  | ||||||
|  | # Collector endpoint as UNIX socket (usually nDPIsrvd) | ||||||
|  | #collector   = /run/nDPIsrvd/collector | ||||||
|  | # Collector endpoint as UDP socket (usually a custom application) | ||||||
|  | #collector   = 127.0.0.1:7777 | ||||||
|  |  | ||||||
|  | # Set a name for this nDPId instance | ||||||
|  | #alias       = myhostname | ||||||
|  |  | ||||||
|  | # Process only internal initial connections | ||||||
|  | #internal    = true | ||||||
|  |  | ||||||
|  | # Process only external initial connections | ||||||
|  | #external    = true | ||||||
|  |  | ||||||
|  | # Enable zLib compression of flow memory for long lasting flows | ||||||
|  | compression = true | ||||||
|  |  | ||||||
|  | # Enable "analyse" events, which can be used for machine learning | ||||||
|  | analysis    = true | ||||||
|  |  | ||||||
|  | # Force poll() on systems that support epoll() as well | ||||||
|  | #poll        = false | ||||||
|  |  | ||||||
|  | # Enable PF_RING packet capture instead of libpcap | ||||||
|  | #pfring      = false | ||||||
|  |  | ||||||
|  | [tuning] | ||||||
|  | max-flows-per-thread            = 2048 | ||||||
|  | max-idle-flows-per-thread       = 64 | ||||||
|  | max-reader-threads              = 10 | ||||||
|  | daemon-status-interval          = 600000000 | ||||||
|  | #memory-profiling-log-interval   = 5 | ||||||
|  | compression-scan-interval       = 20000000 | ||||||
|  | compression-flow-inactivity     = 30000000 | ||||||
|  | flow-scan-interval              = 10000000 | ||||||
|  | generic-max-idle-time           = 600000000 | ||||||
|  | icmp-max-idle-time              = 120000000 | ||||||
|  | tcp-max-idle-time               = 180000000 | ||||||
|  | udp-max-idle-time               = 7440000000 | ||||||
|  | tcp-max-post-end-flow-time      = 120000000 | ||||||
|  | max-packets-per-flow-to-send    = 15 | ||||||
|  | max-packets-per-flow-to-process = 32 | ||||||
|  | max-packets-per-flow-to-analyse = 32 | ||||||
|  | error-event-threshold-n         = 16 | ||||||
|  | error-event-threshold-time      = 10000000 | ||||||
|  |  | ||||||
|  | # Please note that the following options are libnDPI related and can only be set via config file, | ||||||
|  | # not as commnand line parameter. | ||||||
|  | # See libnDPI/doc/configuration_parameters.md for detailed information. | ||||||
|  |  | ||||||
|  | [ndpi] | ||||||
|  | packets_limit_per_flow      = 32 | ||||||
|  | flow.direction_detection    = enable | ||||||
|  | flow.track_payload          = disable | ||||||
|  | tcp_ack_payload_heuristic   = disable | ||||||
|  | fully_encrypted_heuristic   = enable | ||||||
|  | libgcrypt.init              = 1 | ||||||
|  | dpi.compute_entropy         = 1 | ||||||
|  | fpc                         = disable | ||||||
|  | dpi.guess_on_giveup         = 0x03 | ||||||
|  | flow_risk_lists.load        = 1 | ||||||
|  | flow_risk.crawler_bot.list.load = 1 | ||||||
|  | log.level                   = 0 | ||||||
|  |  | ||||||
|  | [protos] | ||||||
|  | tls.certificate_expiration_threshold = 7 | ||||||
|  | tls.application_blocks_tracking      = enable | ||||||
|  | stun.max_packets_extra_dissection    = 8 | ||||||
							
								
								
									
										31
									
								
								ndpisrvd.conf.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ndpisrvd.conf.example
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | [general] | ||||||
|  | #pidfile                = /tmp/ndpisrvd.pid | ||||||
|  | #user                   = nobody | ||||||
|  | #group                  = nogroup | ||||||
|  |  | ||||||
|  | # Collector listener as UNIX socket | ||||||
|  | #collector              = /run/nDPIsrvd/collector | ||||||
|  |  | ||||||
|  | # Distributor listener as UNIX socket | ||||||
|  | #distributor-unix       = /run/nDPIsrvd/distributor | ||||||
|  |  | ||||||
|  | # Distributor listener as IP socket | ||||||
|  | #distributor-in         = 127.0.0.1:7000 | ||||||
|  |  | ||||||
|  | # Change group of the collector socket | ||||||
|  | #collector-group        = daemon | ||||||
|  |  | ||||||
|  | # Change group of the distirbutor socket | ||||||
|  | #distirbutor-group      = staff | ||||||
|  |  | ||||||
|  | # Max (distributor) clients allowed to connect to nDPIsrvd | ||||||
|  | max-remote-descriptors = 128 | ||||||
|  |  | ||||||
|  | # Additional output buffers useful if a distributor sink speed unstable | ||||||
|  | max-write-buffers      = 1024 | ||||||
|  |  | ||||||
|  | # Fallback to blocking I/O if output buffers full | ||||||
|  | blocking-io-fallback   = true | ||||||
|  |  | ||||||
|  | # Force poll() on systems that support epoll() as well | ||||||
|  | #poll                   = false | ||||||
							
								
								
									
										6
									
								
								packages/debian/postrm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								packages/debian/postrm
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #!/bin/sh | ||||||
|  |  | ||||||
|  | rm -rf /run/nDPId /run/nDPIsrvd | ||||||
|  | deluser ndpid || true | ||||||
|  | deluser ndpisrvd || true | ||||||
|  | delgroup ndpisrvd-distributor || true | ||||||
							
								
								
									
										16
									
								
								packages/debian/preinst
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								packages/debian/preinst
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | #!/bin/sh | ||||||
|  |  | ||||||
|  | addgroup --system ndpisrvd-distributor | ||||||
|  | adduser --system --no-create-home --shell=/bin/false --group ndpisrvd | ||||||
|  | adduser --system --no-create-home --shell=/bin/false --group ndpid | ||||||
|  |  | ||||||
|  | cat <<EOF | ||||||
|  | ********************************************************************************** | ||||||
|  | * The that may want to access DPI data needs access to /run/nDPIsrvd/distributor * | ||||||
|  | *                                                                                * | ||||||
|  | * To make it accessible to a user, type:                                         * | ||||||
|  | * sudo usermod --append --groups ndpisrvd-distributor [USER]                     * | ||||||
|  | *                                                                                * | ||||||
|  | * Please not that you might need to re-login to make changes take effect.        * | ||||||
|  | ********************************************************************************** | ||||||
|  | EOF | ||||||
							
								
								
									
										3
									
								
								packages/debian/prerm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								packages/debian/prerm
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | #!/bin/sh | ||||||
|  |  | ||||||
|  | systemctl stop ndpisrvd.service | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| COLLECTOR_PATH=/var/run/ndpisrvd-collector |  | ||||||
| NDPID_ARGS="-A -z" |  | ||||||
| @@ -5,10 +5,9 @@ Requires=ndpisrvd.service | |||||||
|  |  | ||||||
| [Service] | [Service] | ||||||
| Type=simple | Type=simple | ||||||
| ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/nDPId $NDPID_ARGS -i %i -c ${COLLECTOR_PATH} | ExecStartPre=/bin/sh -c 'test -r "@CMAKE_INSTALL_PREFIX@/etc/nDPId/%i.conf" || cp -v "@CMAKE_INSTALL_PREFIX@/share/nDPId/ndpid.conf.example" "@CMAKE_INSTALL_PREFIX@/etc/nDPId/%i.conf"' | ||||||
|  | ExecStart=@CMAKE_INSTALL_PREFIX@/sbin/nDPId -f @CMAKE_INSTALL_PREFIX@/etc/nDPId/%i.conf -i %i -u ndpid -c /run/nDPIsrvd/collector | ||||||
| Restart=on-failure | Restart=on-failure | ||||||
| Environment=COLLECTOR_PATH=/var/run/ndpisrvd-collector NDPID_ARGS="-A -z" |  | ||||||
| EnvironmentFile=@CMAKE_INSTALL_PREFIX@/etc/default/ndpid |  | ||||||
|  |  | ||||||
| [Install] | [Install] | ||||||
| WantedBy=multi-user.target | WantedBy=multi-user.target | ||||||
|   | |||||||
| @@ -4,11 +4,10 @@ After=network.target | |||||||
|  |  | ||||||
| [Service] | [Service] | ||||||
| Type=simple | Type=simple | ||||||
| ExecStart=@CMAKE_INSTALL_PREFIX@/bin/nDPIsrvd -c ${COLLECTOR_PATH} | ExecStartPre=/bin/sh -c 'test -r "@CMAKE_INSTALL_PREFIX@/etc/nDPId/nDPIsrvd.conf" || cp -v "@CMAKE_INSTALL_PREFIX@/share/nDPId/ndpisrvd.conf.example" "@CMAKE_INSTALL_PREFIX@/etc/nDPId/nDPIsrvd.conf"' | ||||||
| ExecStopPost=/bin/rm -f /var/run/ndpisrvd-collector | ExecStartPre=/bin/sh -c 'mkdir -p /run/nDPIsrvd && chown root:root /run/nDPIsrvd && chmod 0775 /run/nDPIsrvd' | ||||||
|  | ExecStart=@CMAKE_INSTALL_PREFIX@/bin/nDPIsrvd -f @CMAKE_INSTALL_PREFIX@/etc/nDPId/nDPIsrvd.conf -u ndpisrvd -c /run/nDPIsrvd/collector -s /run/nDPIsrvd/distributor -G ndpid:ndpisrvd-distributor | ||||||
| Restart=on-failure | Restart=on-failure | ||||||
| Environment=COLLECTOR_PATH=/var/run/ndpisrvd-collector |  | ||||||
| EnvironmentFile=@CMAKE_INSTALL_PREFIX@/etc/default/ndpid |  | ||||||
|  |  | ||||||
| [Install] | [Install] | ||||||
| WantedBy=multi-user.target | WantedBy=multi-user.target | ||||||
|   | |||||||
							
								
								
									
										377
									
								
								utils.c
									
									
									
									
									
								
							
							
						
						
									
										377
									
								
								utils.c
									
									
									
									
									
								
							| @@ -1,3 +1,4 @@ | |||||||
|  | #include <ctype.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <grp.h> | #include <grp.h> | ||||||
| @@ -10,11 +11,19 @@ | |||||||
| #include <syslog.h> | #include <syslog.h> | ||||||
| #endif | #endif | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <sys/types.h> |  | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  |  | ||||||
| #include "utils.h" | #include "utils.h" | ||||||
|  |  | ||||||
|  | #define UTILS_STRLEN_SZ(s) ((size_t)((sizeof(s) / sizeof(s[0])) - sizeof(s[0]))) | ||||||
|  |  | ||||||
|  | #ifndef INI_MAX_LINE | ||||||
|  | #define INI_MAX_LINE BUFSIZ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define INI_INLINE_COMMENT_PREFIXES ";" | ||||||
|  | #define INI_START_COMMENT_PREFIXES ";#" | ||||||
|  |  | ||||||
| typedef char pid_str[16]; | typedef char pid_str[16]; | ||||||
|  |  | ||||||
| static char const * app_name = NULL; | static char const * app_name = NULL; | ||||||
| @@ -22,40 +31,151 @@ static int daemonize = 0; | |||||||
| static int log_to_console = 0; | static int log_to_console = 0; | ||||||
| static int log_to_file_fd = -1; | static int log_to_file_fd = -1; | ||||||
|  |  | ||||||
| void set_cmdarg(struct cmdarg * const ca, char const * const val) | void set_config_defaults(struct confopt * const co_array, size_t array_length) | ||||||
|  | { | ||||||
|  |     for (size_t i = 0; i < array_length; ++i) | ||||||
|  |     { | ||||||
|  |         if (co_array[i].opt == NULL) | ||||||
|  |         { | ||||||
|  |             logger_early(1, "%s", "BUG: Config option is NULL"); | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         if (IS_CMDARG_SET(*co_array[i].opt) == 0) | ||||||
|  |         { | ||||||
|  |             switch (co_array[i].opt->type) | ||||||
|  |             { | ||||||
|  |                 case CMDTYPE_INVALID: | ||||||
|  |                     logger_early(1, "BUG: Config option `%s' has CMDTYPE_INVALID!", co_array[i].key); | ||||||
|  |                     break; | ||||||
|  |                 case CMDTYPE_STRING: | ||||||
|  |                     if (co_array[i].opt->string.default_value == NULL) | ||||||
|  |                     { | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     co_array[i].opt->string.value = strdup(co_array[i].opt->string.default_value); | ||||||
|  |                     break; | ||||||
|  |                 case CMDTYPE_BOOLEAN: | ||||||
|  |                     co_array[i].opt->boolean.value = co_array[i].opt->boolean.default_value; | ||||||
|  |                     break; | ||||||
|  |                 case CMDTYPE_ULL: | ||||||
|  |                     co_array[i].opt->ull.value = co_array[i].opt->ull.default_value; | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int set_config_from(struct confopt * const co, char const * const from) | ||||||
|  | { | ||||||
|  |     if (co == NULL || co->opt == NULL || from == NULL) | ||||||
|  |     { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     switch (co->opt->type) | ||||||
|  |     { | ||||||
|  |         case CMDTYPE_INVALID: | ||||||
|  |             break; | ||||||
|  |         case CMDTYPE_STRING: | ||||||
|  |             set_cmdarg_string(co->opt, from); | ||||||
|  |             break; | ||||||
|  |         case CMDTYPE_BOOLEAN: | ||||||
|  |         { | ||||||
|  |             uint8_t enabled; | ||||||
|  |  | ||||||
|  |             if ((strnlen(from, INI_MAX_LINE) == UTILS_STRLEN_SZ("true") && | ||||||
|  |                  strncasecmp(from, "true", INI_MAX_LINE) == 0) || | ||||||
|  |                 (strnlen(from, INI_MAX_LINE) == UTILS_STRLEN_SZ("1") && strncasecmp(from, "1", INI_MAX_LINE) == 0)) | ||||||
|  |             { | ||||||
|  |                 enabled = 1; | ||||||
|  |             } | ||||||
|  |             else if ((strnlen(from, INI_MAX_LINE) == UTILS_STRLEN_SZ("false") && | ||||||
|  |                       strncasecmp(from, "false", INI_MAX_LINE) == 0) || | ||||||
|  |                      (strnlen(from, INI_MAX_LINE) == UTILS_STRLEN_SZ("0") && strncasecmp(from, "0", INI_MAX_LINE) == 0)) | ||||||
|  |             { | ||||||
|  |                 enabled = 0; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 logger_early(1, "Config key `%s' has a value not of type bool: `%s'", co->key, from); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             set_cmdarg_boolean(co->opt, enabled); | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |         case CMDTYPE_ULL: | ||||||
|  |         { | ||||||
|  |             char * endptr; | ||||||
|  |             long int value_llu = strtoull(from, &endptr, 10); | ||||||
|  |  | ||||||
|  |             if (from == endptr) | ||||||
|  |             { | ||||||
|  |                 logger_early(1, "Subopt `%s': Value `%s' is not a valid number.", co->key, from); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             if (errno == ERANGE) | ||||||
|  |             { | ||||||
|  |                 logger_early(1, "Subopt `%s': Number too large.", co->key); | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             set_cmdarg_ull(co->opt, value_llu); | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void set_cmdarg_string(struct cmdarg * const ca, char const * const val) | ||||||
| { | { | ||||||
|     if (ca == NULL || val == NULL) |     if (ca == NULL || val == NULL) | ||||||
|     { |     { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     free(ca->value); |     if (ca->type != CMDTYPE_STRING) | ||||||
|     ca->value = strdup(val); |     { | ||||||
|  |         logger_early(1, "%s", "BUG: Type is not CMDTYPE_STRING!"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ca->is_set = 1; | ||||||
|  |     free(ca->string.value); | ||||||
|  |     ca->string.value = strdup(val); | ||||||
| } | } | ||||||
|  |  | ||||||
| char const * get_cmdarg(struct cmdarg const * const ca) | void set_cmdarg_boolean(struct cmdarg * const ca, uint8_t val) | ||||||
| { | { | ||||||
|     if (ca == NULL) |     if (ca == NULL) | ||||||
|     { |     { | ||||||
|         return NULL; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (ca->value != NULL) |     if (ca->type != CMDTYPE_BOOLEAN) | ||||||
|     { |     { | ||||||
|         return ca->value; |         logger_early(1, "%s", "BUG: Type is not CMDTYPE_BOOLEAN!"); | ||||||
|  |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return ca->default_value; |     ca->is_set = 1; | ||||||
|  |     ca->boolean.value = (val != 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| int is_cmdarg_set(struct cmdarg const * const ca) | void set_cmdarg_ull(struct cmdarg * const ca, unsigned long long int val) | ||||||
| { | { | ||||||
|     if (ca == NULL) |     if (ca == NULL) | ||||||
|     { |     { | ||||||
|         return 0; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return ca->value != NULL; |     if (ca->type != CMDTYPE_ULL) | ||||||
|  |     { | ||||||
|  |         logger_early(1, "%s", "BUG: Type is not CMDTYPE_ULL!"); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ca->is_set = 1; | ||||||
|  |     ca->ull.value = val; | ||||||
| } | } | ||||||
|  |  | ||||||
| void daemonize_enable(void) | void daemonize_enable(void) | ||||||
| @@ -218,11 +338,7 @@ int daemonize_shutdown(char const * const pidfile) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int change_user_group(char const * const user, | int change_user_group(char const * const user, char const * const group, char const * const pidfile) | ||||||
|                       char const * const group, |  | ||||||
|                       char const * const pidfile, |  | ||||||
|                       char const * const uds_collector_path, |  | ||||||
|                       char const * const uds_distributor_path) |  | ||||||
| { | { | ||||||
|     struct passwd * pwd; |     struct passwd * pwd; | ||||||
|     struct group * grp; |     struct group * grp; | ||||||
| @@ -237,7 +353,7 @@ int change_user_group(char const * const user, | |||||||
|     pwd = getpwnam(user); |     pwd = getpwnam(user); | ||||||
|     if (pwd == NULL) |     if (pwd == NULL) | ||||||
|     { |     { | ||||||
|         return -errno; |         return (errno != 0 ? -errno : -ENOENT); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (group != NULL) |     if (group != NULL) | ||||||
| @@ -246,7 +362,7 @@ int change_user_group(char const * const user, | |||||||
|         grp = getgrnam(group); |         grp = getgrnam(group); | ||||||
|         if (grp == NULL) |         if (grp == NULL) | ||||||
|         { |         { | ||||||
|             return -errno; |             return (errno != 0 ? -errno : -ENOENT); | ||||||
|         } |         } | ||||||
|         gid = grp->gr_gid; |         gid = grp->gr_gid; | ||||||
|     } |     } | ||||||
| @@ -255,23 +371,6 @@ int change_user_group(char const * const user, | |||||||
|         gid = pwd->pw_gid; |         gid = pwd->pw_gid; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     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) |  | ||||||
|         { |  | ||||||
|             return -errno; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     if (uds_distributor_path != NULL) |  | ||||||
|     { |  | ||||||
|         errno = 0; |  | ||||||
|         if (chmod(uds_distributor_path, S_IRUSR | S_IWUSR | S_IRGRP) != 0 || |  | ||||||
|             chown(uds_distributor_path, pwd->pw_uid, gid) != 0) |  | ||||||
|         { |  | ||||||
|             return -errno; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     if (daemonize != 0 && pidfile != NULL) |     if (daemonize != 0 && pidfile != NULL) | ||||||
|     { |     { | ||||||
|         errno = 0; |         errno = 0; | ||||||
| @@ -283,6 +382,56 @@ int change_user_group(char const * const user, | |||||||
|     return setregid(gid, gid) != 0 || setreuid(pwd->pw_uid, pwd->pw_uid); |     return setregid(gid, gid) != 0 || setreuid(pwd->pw_uid, pwd->pw_uid); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | WARN_UNUSED | ||||||
|  | int chmod_chown(char const * const path, mode_t mode, char const * const user, char const * const group) | ||||||
|  | { | ||||||
|  |     uid_t path_uid = (uid_t)-1; | ||||||
|  |     gid_t path_gid = (gid_t)-1; | ||||||
|  |  | ||||||
|  |     if (mode != 0) | ||||||
|  |     { | ||||||
|  |         if (chmod(path, mode) != 0) | ||||||
|  |         { | ||||||
|  |             return -errno; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (user != NULL) | ||||||
|  |     { | ||||||
|  |         errno = 0; | ||||||
|  |  | ||||||
|  |         struct passwd * const pwd = getpwnam(user); | ||||||
|  |         if (pwd == NULL) | ||||||
|  |         { | ||||||
|  |             return (errno != 0 ? -errno : -ENOENT); | ||||||
|  |         } | ||||||
|  |         path_uid = pwd->pw_uid; | ||||||
|  |         path_gid = pwd->pw_gid; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (group != NULL) | ||||||
|  |     { | ||||||
|  |         errno = 0; | ||||||
|  |  | ||||||
|  |         struct group * const grp = getgrnam(group); | ||||||
|  |         if (grp == NULL) | ||||||
|  |         { | ||||||
|  |             return (errno != 0 ? -errno : -ENOENT); | ||||||
|  |         } | ||||||
|  |         path_gid = grp->gr_gid; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (path_uid != (uid_t)-1 || path_gid != (gid_t)-1) | ||||||
|  |     { | ||||||
|  |         if (chown(path, path_uid, path_gid) != 0) | ||||||
|  |         { | ||||||
|  |             return -errno; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| void init_logging(char const * const name) | void init_logging(char const * const name) | ||||||
| { | { | ||||||
|     app_name = name; |     app_name = name; | ||||||
| @@ -454,6 +603,160 @@ char const * get_nDPId_version(void) | |||||||
|            "unknown" |            "unknown" | ||||||
| #endif | #endif | ||||||
|            "\n" |            "\n" | ||||||
|            "(C) 2020-2023 Toni Uhlig\n" |            "(C) 2020-2024 Toni Uhlig\n" | ||||||
|            "Please report any BUG to toni@impl.cc\n"; |            "Please report any BUG to toni@impl.cc\n"; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Strip whitespace chars off end of given string, in place. Return s. */ | ||||||
|  | static char * ini_rstrip(char * s) | ||||||
|  | { | ||||||
|  |     char * p = s + strlen(s); | ||||||
|  |     while (p > s && isspace((unsigned char)(*--p))) | ||||||
|  |         *p = '\0'; | ||||||
|  |     return s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Return pointer to first non-whitespace char in given string. */ | ||||||
|  | static char * ini_lskip(const char * s) | ||||||
|  | { | ||||||
|  |     while (*s && isspace((unsigned char)(*s))) | ||||||
|  |         s++; | ||||||
|  |     return (char *)s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Return pointer to first char (of chars) or inline comment in given string, | ||||||
|  |    or pointer to NUL at end of string if neither found. Inline comment must | ||||||
|  |    be prefixed by a whitespace character to register as a comment. */ | ||||||
|  | static char * ini_find_chars_or_comment(const char * s, const char * chars) | ||||||
|  | { | ||||||
|  |     int was_space = 0; | ||||||
|  |     while (*s && (!chars || !strchr(chars, *s)) && !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) | ||||||
|  |     { | ||||||
|  |         was_space = isspace((unsigned char)(*s)); | ||||||
|  |         s++; | ||||||
|  |     } | ||||||
|  |     return (char *)s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* See: https://github.com/benhoyt/inih/blob/master/ini.c#L97C67-L97C74 */ | ||||||
|  | static int parse_config_lines(FILE * const file, config_line_callback cb, void * const user_data) | ||||||
|  | { | ||||||
|  |     char line[INI_MAX_LINE]; | ||||||
|  |     int max_line = INI_MAX_LINE; | ||||||
|  |     char section[INI_MAX_SECTION] = ""; | ||||||
|  |     char prev_name[INI_MAX_NAME] = ""; | ||||||
|  |     char * start; | ||||||
|  |     char * end; | ||||||
|  |     char * name; | ||||||
|  |     char * value; | ||||||
|  |     int lineno = 0; | ||||||
|  |     int error = 0; | ||||||
|  |  | ||||||
|  |     while (fgets(line, max_line, file) != NULL) | ||||||
|  |     { | ||||||
|  |         lineno++; | ||||||
|  |         start = line; | ||||||
|  |         start = ini_lskip(ini_rstrip(start)); | ||||||
|  |  | ||||||
|  |         if (strchr(INI_START_COMMENT_PREFIXES, *start)) | ||||||
|  |         { | ||||||
|  |             /* Start-of-line comment */ | ||||||
|  |         } | ||||||
|  |         else if (*prev_name && *start && start > line) | ||||||
|  |         { | ||||||
|  |             end = ini_find_chars_or_comment(start, NULL); | ||||||
|  |             if (*end) | ||||||
|  |             { | ||||||
|  |                 *end = '\0'; | ||||||
|  |             } | ||||||
|  |             ini_rstrip(start); | ||||||
|  |  | ||||||
|  |             /* Non-blank line with leading whitespace, treat as continuation | ||||||
|  |                of previous name's value (as per Python configparser). */ | ||||||
|  |             if (!cb(lineno, section, prev_name, start, user_data) && !error) | ||||||
|  |             { | ||||||
|  |                 error = lineno; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else if (*start == '[') | ||||||
|  |         { | ||||||
|  |             /* A "[section]" line */ | ||||||
|  |             end = ini_find_chars_or_comment(start + 1, "]"); | ||||||
|  |             if (*end == ']') | ||||||
|  |             { | ||||||
|  |                 *end = '\0'; | ||||||
|  |                 snprintf(section, sizeof(section), "%s", start + 1); | ||||||
|  |                 *prev_name = '\0'; | ||||||
|  |             } | ||||||
|  |             else if (!error) | ||||||
|  |             { | ||||||
|  |                 /* No ']' found on section line */ | ||||||
|  |                 error = lineno; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else if (*start) | ||||||
|  |         { | ||||||
|  |             /* Not a comment, must be a name[=:]value pair */ | ||||||
|  |             end = ini_find_chars_or_comment(start, "=:"); | ||||||
|  |             if (*end == '=' || *end == ':') | ||||||
|  |             { | ||||||
|  |                 *end = '\0'; | ||||||
|  |                 name = ini_rstrip(start); | ||||||
|  |                 value = end + 1; | ||||||
|  |                 end = ini_find_chars_or_comment(value, NULL); | ||||||
|  |                 if (*end) | ||||||
|  |                 { | ||||||
|  |                     *end = '\0'; | ||||||
|  |                 } | ||||||
|  |                 value = ini_lskip(value); | ||||||
|  |                 ini_rstrip(value); | ||||||
|  |  | ||||||
|  |                 /* Valid name[=:]value pair found, call handler */ | ||||||
|  |                 snprintf(prev_name, sizeof(prev_name), "%s", name); | ||||||
|  |                 if (!cb(lineno, section, prev_name, value, user_data) && !error) | ||||||
|  |                 { | ||||||
|  |                     error = lineno; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else if (!error) | ||||||
|  |             { | ||||||
|  |                 /* No '=' or ':' found on name[=:]value line */ | ||||||
|  |                 error = lineno; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return error; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int parse_config_file(char const * const config_file, config_line_callback cb, void * const user_data) | ||||||
|  | { | ||||||
|  |     int file_fd; | ||||||
|  |     FILE * file; | ||||||
|  |     int error; | ||||||
|  |     struct stat sbuf; | ||||||
|  |  | ||||||
|  |     file_fd = open(config_file, O_RDONLY); | ||||||
|  |     if (file_fd < 0) | ||||||
|  |     { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     if (fstat(file_fd, &sbuf) != 0) | ||||||
|  |     { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |     if ((sbuf.st_mode & S_IFMT) != S_IFREG) | ||||||
|  |     { | ||||||
|  |         return -ENOENT; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     file = fdopen(file_fd, "r"); | ||||||
|  |     if (file == NULL) | ||||||
|  |     { | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     error = parse_config_lines(file, cb, user_data); | ||||||
|  |     fclose(file); | ||||||
|  |     return error; | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								utils.h
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								utils.h
									
									
									
									
									
								
							| @@ -2,27 +2,86 @@ | |||||||
| #define UTILS_H 1 | #define UTILS_H 1 | ||||||
|  |  | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  |  | ||||||
| #define WARN_UNUSED __attribute__((__warn_unused_result__)) | #define WARN_UNUSED __attribute__((__warn_unused_result__)) | ||||||
|  |  | ||||||
| #define CMDARG(_default_value)                                                                                         \ | #define INI_MAX_SECTION 50 | ||||||
|  | #define INI_MAX_NAME 50 | ||||||
|  |  | ||||||
|  | #define CMDARG_STR(_default_value)                                                                                     \ | ||||||
|     {                                                                                                                  \ |     {                                                                                                                  \ | ||||||
|         .value = NULL, .default_value = (_default_value)                                                               \ |         .is_set = 0, .type = CMDTYPE_STRING, .string.value = NULL, .string.default_value = (_default_value)            \ | ||||||
|     } |     } | ||||||
|  | #define CMDARG_BOOL(_default_value)                                                                                    \ | ||||||
|  |     {                                                                                                                  \ | ||||||
|  |         .is_set = 0, .type = CMDTYPE_BOOLEAN, .boolean.value = 0, .boolean.default_value = (_default_value)            \ | ||||||
|  |     } | ||||||
|  | #define CMDARG_ULL(_default_value)                                                                                     \ | ||||||
|  |     {                                                                                                                  \ | ||||||
|  |         .is_set = 0, .type = CMDTYPE_ULL, .ull.value = 0ull, .ull.default_value = (_default_value)                     \ | ||||||
|  |     } | ||||||
|  | #define CONFOPT(_key, _opt)                                                                                            \ | ||||||
|  |     {                                                                                                                  \ | ||||||
|  |         .key = _key, .opt = _opt                                                                                       \ | ||||||
|  |     } | ||||||
|  | #define GET_CMDARG_STR(cmdarg) ((cmdarg).string.value) | ||||||
|  | #define GET_CMDARG_BOOL(cmdarg) ((cmdarg).boolean.value) | ||||||
|  | #define GET_CMDARG_ULL(cmdarg) ((cmdarg).ull.value) | ||||||
|  | #define IS_CMDARG_SET(cmdarg) ((cmdarg).is_set) | ||||||
|  |  | ||||||
|  | enum cmdtype | ||||||
|  | { | ||||||
|  |     CMDTYPE_INVALID = 0, | ||||||
|  |     CMDTYPE_STRING, | ||||||
|  |     CMDTYPE_BOOLEAN, | ||||||
|  |     CMDTYPE_ULL | ||||||
|  | }; | ||||||
|  |  | ||||||
| struct cmdarg | struct cmdarg | ||||||
| { | { | ||||||
|     char * value; |     enum cmdtype type; | ||||||
|     char const * const default_value; |     int is_set; | ||||||
|  |     union | ||||||
|  |     { | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             char * value; | ||||||
|  |             char const * const default_value; | ||||||
|  |         } string; | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             uint8_t value; | ||||||
|  |             uint8_t const default_value; | ||||||
|  |         } boolean; | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             unsigned long long int value; | ||||||
|  |             unsigned long long int const default_value; | ||||||
|  |         } ull; | ||||||
|  |     }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| void set_cmdarg(struct cmdarg * const ca, char const * const val); | struct confopt | ||||||
|  | { | ||||||
|  |     char const * const key; | ||||||
|  |     struct cmdarg * const opt; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef int (*config_line_callback)( | ||||||
|  |     int lineno, char const * const section, char const * const key, char const * const value, void * const user_data); | ||||||
|  |  | ||||||
|  | void set_config_defaults(struct confopt * const co_array, size_t array_length); | ||||||
|  |  | ||||||
| WARN_UNUSED | WARN_UNUSED | ||||||
| char const * get_cmdarg(struct cmdarg const * const ca); | int set_config_from(struct confopt * const co, char const * const from); | ||||||
|  |  | ||||||
| WARN_UNUSED | void set_cmdarg_string(struct cmdarg * const ca, char const * const val); | ||||||
| int is_cmdarg_set(struct cmdarg const * const ca); |  | ||||||
|  | void set_cmdarg_boolean(struct cmdarg * const ca, uint8_t val); | ||||||
|  |  | ||||||
|  | void set_cmdarg_ull(struct cmdarg * const ca, unsigned long long int val); | ||||||
|  |  | ||||||
| WARN_UNUSED | WARN_UNUSED | ||||||
| int is_path_absolute(char const * const prefix, char const * const path); | int is_path_absolute(char const * const prefix, char const * const path); | ||||||
| @@ -38,11 +97,10 @@ int daemonize_with_pidfile(char const * const pidfile); | |||||||
| int daemonize_shutdown(char const * const pidfile); | int daemonize_shutdown(char const * const pidfile); | ||||||
|  |  | ||||||
| WARN_UNUSED | WARN_UNUSED | ||||||
| int change_user_group(char const * const user, | int change_user_group(char const * const user, char const * const group, char const * const pidfile); | ||||||
|                       char const * const group, |  | ||||||
|                       char const * const pidfile, | WARN_UNUSED | ||||||
|                       char const * const uds_collector_path, | int chmod_chown(char const * const path, mode_t mode, char const * const user, char const * const group); | ||||||
|                       char const * const uds_distributor_path); |  | ||||||
|  |  | ||||||
| void init_logging(char const * const daemon_name); | void init_logging(char const * const daemon_name); | ||||||
|  |  | ||||||
| @@ -73,4 +131,7 @@ int set_fd_cloexec(int fd); | |||||||
| WARN_UNUSED | WARN_UNUSED | ||||||
| char const * get_nDPId_version(void); | char const * get_nDPId_version(void); | ||||||
|  |  | ||||||
|  | WARN_UNUSED | ||||||
|  | int parse_config_file(char const * const config_file, config_line_callback cb, void * const user_data); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Toni
					Toni