mirror of
https://github.com/optim-enterprises-bv/nDPId.git
synced 2025-10-28 17:02:24 +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_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_DEBUGINFO_PACKAGE 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/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}/ndpid@.service" DESTINATION lib/systemd/system)
|
||||
endif()
|
||||
|
||||
4
dependencies/nDPIsrvd.h
vendored
4
dependencies/nDPIsrvd.h
vendored
@@ -33,8 +33,8 @@
|
||||
#define nDPIsrvd_JSON_KEY_STRLEN (32)
|
||||
#define nDPIsrvd_HASHKEY_SEED (0x995fd871u)
|
||||
|
||||
#define nDPIsrvd_ARRAY_LENGTH(s) (sizeof(s) / sizeof(s[0]))
|
||||
#define nDPIsrvd_STRLEN_SZ(s) (sizeof(s) / sizeof(s[0]) - sizeof(s[0]))
|
||||
#define nDPIsrvd_ARRAY_LENGTH(s) ((size_t)(sizeof(s) / 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_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;
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "utarray.h"
|
||||
#include "utils.h"
|
||||
|
||||
//#define VERBOSE
|
||||
// #define VERBOSE
|
||||
#define DEFAULT_DATADIR "/tmp/nDPId-captured"
|
||||
|
||||
struct packet_data
|
||||
@@ -1355,8 +1355,14 @@ int main(int argc, char ** argv)
|
||||
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;
|
||||
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)
|
||||
{
|
||||
@@ -1368,10 +1374,6 @@ int main(int argc, char ** argv)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (datadir != NULL)
|
||||
{
|
||||
chmod(datadir, S_IRWXU);
|
||||
}
|
||||
|
||||
if (nDPIsrvd_set_read_timeout(ndpisrvd_socket, 180, 0) != 0)
|
||||
{
|
||||
|
||||
@@ -1671,7 +1671,7 @@ int main(int argc, char ** argv)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
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_free(size_t free_size);
|
||||
|
||||
//#define VERBOSE_MEMORY_PROFILING 1
|
||||
// #define VERBOSE_MEMORY_PROFILING 1
|
||||
#define NO_MAIN 1
|
||||
#include "utils.c"
|
||||
#include "nio.c"
|
||||
@@ -1315,7 +1315,7 @@ static void * nDPId_mainloop_thread(void * const arg)
|
||||
}
|
||||
run_capture_loop(&reader_threads[0]);
|
||||
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_processed += reader_threads[i].workflow->packets_processed;
|
||||
@@ -1667,27 +1667,30 @@ int main(int argc, char ** argv)
|
||||
return retval;
|
||||
}
|
||||
|
||||
nDPIsrvd_options.max_write_buffers = 32;
|
||||
nDPId_options.enable_data_analysis = 1;
|
||||
nDPId_options.max_packets_per_flow_to_send = 5;
|
||||
set_cmdarg_ull(&nDPIsrvd_options.max_write_buffers, 32);
|
||||
set_cmdarg_boolean(&nDPId_options.enable_data_analysis, 1);
|
||||
set_cmdarg_ull(&nDPId_options.max_packets_per_flow_to_send, 5);
|
||||
#ifdef ENABLE_ZLIB
|
||||
/*
|
||||
* zLib compression is forced enabled for testing.
|
||||
* Remember to compile nDPId with zlib enabled.
|
||||
* 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
|
||||
nDPId_options.memory_profiling_log_interval = (unsigned long long int)-1;
|
||||
nDPId_options.reader_thread_count = 1; /* Please do not change this! Generating meaningful pcap diff's relies on a
|
||||
single reader thread! */
|
||||
set_cmdarg(&nDPId_options.instance_alias, "nDPId-test");
|
||||
set_cmdarg_ull(&nDPId_options.memory_profiling_log_interval, (unsigned long long int)-1);
|
||||
set_cmdarg_ull(&nDPId_options.reader_thread_count, 1); /* Please do not change this! Generating meaningful pcap
|
||||
diff's relies on a single reader thread! */
|
||||
set_cmdarg_string(&nDPId_options.instance_alias, "nDPId-test");
|
||||
if (access(argv[1], R_OK) != 0)
|
||||
{
|
||||
logger(1, "%s: pcap file `%s' does not exist or is not readable", argv[0], argv[1]);
|
||||
return 1;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return 1;
|
||||
@@ -1845,10 +1848,12 @@ int main(int argc, char ** argv)
|
||||
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n",
|
||||
total_alloc_bytes -
|
||||
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 -
|
||||
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_free_count);
|
||||
|
||||
|
||||
372
nDPIsrvd.c
372
nDPIsrvd.c
@@ -90,27 +90,54 @@ static struct nDPIsrvd_address distributor_in_address = {
|
||||
|
||||
static struct
|
||||
{
|
||||
struct cmdarg config_file;
|
||||
struct cmdarg pidfile;
|
||||
struct cmdarg collector_un_sockpath;
|
||||
struct cmdarg distributor_un_sockpath;
|
||||
struct cmdarg distributor_in_address;
|
||||
struct cmdarg user;
|
||||
struct cmdarg group;
|
||||
nDPIsrvd_ull max_remote_descriptors;
|
||||
nDPIsrvd_ull max_write_buffers;
|
||||
uint8_t bufferbloat_fallback_to_blocking;
|
||||
struct cmdarg collector_group;
|
||||
struct cmdarg distributor_group;
|
||||
struct cmdarg max_remote_descriptors;
|
||||
struct cmdarg max_write_buffers;
|
||||
struct cmdarg bufferbloat_fallback_to_blocking;
|
||||
#ifdef ENABLE_EPOLL
|
||||
uint8_t use_poll;
|
||||
struct cmdarg use_poll;
|
||||
#endif
|
||||
} nDPIsrvd_options = {.pidfile = CMDARG(nDPIsrvd_PIDFILE),
|
||||
.collector_un_sockpath = CMDARG(COLLECTOR_UNIX_SOCKET),
|
||||
.distributor_un_sockpath = CMDARG(DISTRIBUTOR_UNIX_SOCKET),
|
||||
.distributor_in_address = CMDARG(NULL),
|
||||
.user = CMDARG(DEFAULT_CHUSER),
|
||||
.group = CMDARG(NULL),
|
||||
.max_remote_descriptors = nDPIsrvd_MAX_REMOTE_DESCRIPTORS,
|
||||
.max_write_buffers = nDPIsrvd_MAX_WRITE_BUFFERS,
|
||||
.bufferbloat_fallback_to_blocking = 1};
|
||||
} nDPIsrvd_options = {.config_file = CMDARG_STR(NULL),
|
||||
.pidfile = CMDARG_STR(nDPIsrvd_PIDFILE),
|
||||
.collector_un_sockpath = CMDARG_STR(COLLECTOR_UNIX_SOCKET),
|
||||
.distributor_un_sockpath = CMDARG_STR(DISTRIBUTOR_UNIX_SOCKET),
|
||||
.distributor_in_address = CMDARG_STR(NULL),
|
||||
.user = CMDARG_STR(DEFAULT_CHUSER),
|
||||
.group = CMDARG_STR(NULL),
|
||||
.collector_group = CMDARG_STR(NULL),
|
||||
.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,
|
||||
char const * const prefix,
|
||||
@@ -239,9 +266,9 @@ static int add_to_additional_write_buffers(struct remote_desc * const remote,
|
||||
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,
|
||||
"Buffer limit for",
|
||||
@@ -498,7 +525,7 @@ static int create_listen_sockets(void)
|
||||
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);
|
||||
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,
|
||||
sizeof(collector_addr.sun_path),
|
||||
"%s",
|
||||
get_cmdarg(&nDPIsrvd_options.collector_un_sockpath));
|
||||
GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath));
|
||||
if (written < 0)
|
||||
{
|
||||
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))
|
||||
{
|
||||
logger(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);
|
||||
logger(1, "Collector UNIX socket path too long, max: %zu characters", sizeof(collector_addr.sun_path) - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -547,7 +571,7 @@ static int create_listen_sockets(void)
|
||||
{
|
||||
logger(1,
|
||||
"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));
|
||||
return 1;
|
||||
}
|
||||
@@ -559,7 +583,7 @@ static int create_listen_sockets(void)
|
||||
int written = snprintf(distributor_addr.sun_path,
|
||||
sizeof(distributor_addr.sun_path),
|
||||
"%s",
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath));
|
||||
GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath));
|
||||
if (written < 0)
|
||||
{
|
||||
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))
|
||||
{
|
||||
logger(1,
|
||||
"Distributor UNIX socket path too long, current/max: %zu/%zu",
|
||||
strlen(get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)),
|
||||
"Distributor UNIX socket path too long, max: %zu characters",
|
||||
sizeof(distributor_addr.sun_path) - 1);
|
||||
return 2;
|
||||
}
|
||||
@@ -578,19 +601,19 @@ static int create_listen_sockets(void)
|
||||
{
|
||||
logger(1,
|
||||
"Error binding Distributor socket to `%s': %s",
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath),
|
||||
GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath),
|
||||
strerror(errno));
|
||||
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)
|
||||
{
|
||||
logger(1,
|
||||
"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));
|
||||
return 3;
|
||||
}
|
||||
@@ -598,7 +621,7 @@ static int create_listen_sockets(void)
|
||||
{
|
||||
logger(1,
|
||||
"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));
|
||||
return 3;
|
||||
}
|
||||
@@ -606,7 +629,7 @@ static int create_listen_sockets(void)
|
||||
{
|
||||
logger(1,
|
||||
"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));
|
||||
return 3;
|
||||
}
|
||||
@@ -622,7 +645,7 @@ static int create_listen_sockets(void)
|
||||
{
|
||||
logger(1,
|
||||
"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));
|
||||
return 3;
|
||||
}
|
||||
@@ -631,7 +654,7 @@ static int create_listen_sockets(void)
|
||||
{
|
||||
logger(1,
|
||||
"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));
|
||||
return 3;
|
||||
}
|
||||
@@ -804,10 +827,13 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
{
|
||||
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)
|
||||
{
|
||||
case 'f':
|
||||
set_cmdarg_string(&nDPIsrvd_options.config_file, optarg);
|
||||
break;
|
||||
case 'l':
|
||||
enable_console_logger();
|
||||
break;
|
||||
@@ -818,11 +844,11 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
set_cmdarg(&nDPIsrvd_options.collector_un_sockpath, optarg);
|
||||
set_cmdarg_string(&nDPIsrvd_options.collector_un_sockpath, optarg);
|
||||
break;
|
||||
case 'e':
|
||||
#ifdef ENABLE_EPOLL
|
||||
nDPIsrvd_options.use_poll = 1;
|
||||
set_cmdarg_boolean(&nDPIsrvd_options.use_poll, 1);
|
||||
#else
|
||||
logger_early(1, "%s", "nDPIsrvd was built w/o epoll() support, poll() is already the default");
|
||||
#endif
|
||||
@@ -831,36 +857,67 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
daemonize_enable();
|
||||
break;
|
||||
case 'p':
|
||||
set_cmdarg(&nDPIsrvd_options.pidfile, optarg);
|
||||
set_cmdarg_string(&nDPIsrvd_options.pidfile, optarg);
|
||||
break;
|
||||
case 's':
|
||||
set_cmdarg(&nDPIsrvd_options.distributor_un_sockpath, optarg);
|
||||
set_cmdarg_string(&nDPIsrvd_options.distributor_un_sockpath, optarg);
|
||||
break;
|
||||
case 'S':
|
||||
set_cmdarg(&nDPIsrvd_options.distributor_in_address, optarg);
|
||||
set_cmdarg_string(&nDPIsrvd_options.distributor_in_address, optarg);
|
||||
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':
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
set_cmdarg_ull(&nDPIsrvd_options.max_remote_descriptors, tmp);
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
set_cmdarg(&nDPIsrvd_options.user, optarg);
|
||||
set_cmdarg_string(&nDPIsrvd_options.user, optarg);
|
||||
break;
|
||||
case 'g':
|
||||
set_cmdarg(&nDPIsrvd_options.group, optarg);
|
||||
set_cmdarg_string(&nDPIsrvd_options.group, optarg);
|
||||
break;
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
set_cmdarg_ull(&nDPIsrvd_options.max_write_buffers, tmp);
|
||||
break;
|
||||
}
|
||||
case 'D':
|
||||
nDPIsrvd_options.bufferbloat_fallback_to_blocking = 0;
|
||||
set_cmdarg_boolean(&nDPIsrvd_options.bufferbloat_fallback_to_blocking, 0);
|
||||
break;
|
||||
case 'v':
|
||||
fprintf(stderr, "%s", get_nDPId_version());
|
||||
@@ -869,11 +926,14 @@ static int nDPIsrvd_parse_options(int argc, char ** argv)
|
||||
default:
|
||||
fprintf(stderr, "%s\n", get_nDPId_version());
|
||||
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[-G collector-unix-socket-group:distributor-unix-socket-group]\n"
|
||||
"\t[-m max-remote-descriptors] [-u user] [-g group]\n"
|
||||
"\t[-C max-buffered-json-lines] [-D]\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 a log file.\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 \tDefault: %s\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-h\tthis\n\n",
|
||||
argv[0],
|
||||
get_cmdarg(&nDPIsrvd_options.collector_un_sockpath),
|
||||
get_cmdarg(&nDPIsrvd_options.pidfile),
|
||||
get_cmdarg(&nDPIsrvd_options.user),
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath));
|
||||
nDPIsrvd_options.collector_un_sockpath.string.default_value,
|
||||
nDPIsrvd_options.pidfile.string.default_value,
|
||||
nDPIsrvd_options.user.string.default_value,
|
||||
nDPIsrvd_options.distributor_un_sockpath.string.default_value);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
"%s: Could not parse address %s",
|
||||
argv[0],
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_in_address));
|
||||
GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address));
|
||||
return 1;
|
||||
}
|
||||
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,
|
||||
"%s: You've requested to setup another UNIX socket `%s', but there is already one at `%s'",
|
||||
argv[0],
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_in_address),
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath));
|
||||
GET_CMDARG_STR(nDPIsrvd_options.distributor_in_address),
|
||||
GET_CMDARG_STR(nDPIsrvd_options.distributor_un_sockpath));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1516,8 +1581,9 @@ static int mainloop(struct nio * const io)
|
||||
static int setup_event_queue(struct nio * const io)
|
||||
{
|
||||
#ifdef ENABLE_EPOLL
|
||||
if ((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))
|
||||
if ((GET_CMDARG_BOOL(nDPIsrvd_options.use_poll) == 0 && nio_use_epoll(io, 32) != NIO_SUCCESS) ||
|
||||
(GET_CMDARG_BOOL(nDPIsrvd_options.use_poll) != 0 &&
|
||||
nio_use_poll(io, nDPIsrvd_MAX_REMOTE_DESCRIPTORS) != NIO_SUCCESS))
|
||||
#else
|
||||
if (nio_use_poll(io, nDPIsrvd_MAX_REMOTE_DESCRIPTORS) != NIO_SUCCESS)
|
||||
#endif
|
||||
@@ -1576,6 +1642,49 @@ static int setup_remote_descriptors(nDPIsrvd_ull max_remote_descriptors)
|
||||
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
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
@@ -1594,6 +1703,32 @@ int main(int argc, char ** argv)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -1604,32 +1739,32 @@ int main(int argc, char ** argv)
|
||||
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,
|
||||
"UNIX socket `%s' exists; nDPIsrvd already running? "
|
||||
"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;
|
||||
}
|
||||
|
||||
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,
|
||||
"UNIX socket `%s' exists; nDPIsrvd already running? "
|
||||
"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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1641,11 +1776,11 @@ int main(int argc, char ** argv)
|
||||
case 1:
|
||||
goto error;
|
||||
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,
|
||||
"Could not unlink `%s': %s",
|
||||
get_cmdarg(&nDPIsrvd_options.collector_un_sockpath),
|
||||
GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath),
|
||||
strerror(errno));
|
||||
}
|
||||
goto error;
|
||||
@@ -1655,8 +1790,8 @@ int main(int argc, char ** argv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
logger(0, "collector UNIX socket listen on `%s'", get_cmdarg(&nDPIsrvd_options.collector_un_sockpath));
|
||||
logger(0, "distributor UNIX listen on `%s'", get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath));
|
||||
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_STR(nDPIsrvd_options.distributor_un_sockpath));
|
||||
switch (distributor_in_address.raw.sa_family)
|
||||
{
|
||||
default:
|
||||
@@ -1672,28 +1807,88 @@ int main(int argc, char ** argv)
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (change_user_group(get_cmdarg(&nDPIsrvd_options.user),
|
||||
get_cmdarg(&nDPIsrvd_options.group),
|
||||
get_cmdarg(&nDPIsrvd_options.pidfile),
|
||||
get_cmdarg(&nDPIsrvd_options.collector_un_sockpath),
|
||||
get_cmdarg(&nDPIsrvd_options.distributor_un_sockpath)) != 0 &&
|
||||
errno != EPERM)
|
||||
int ret = chmod_chown(GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath),
|
||||
S_IRUSR | S_IWUSR | S_IWGRP,
|
||||
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));
|
||||
if (ret != 0)
|
||||
{
|
||||
if (errno != 0)
|
||||
if (IS_CMDARG_SET(nDPIsrvd_options.collector_group) != 0 || IS_CMDARG_SET(nDPIsrvd_options.group) != 0)
|
||||
{
|
||||
logger(1,
|
||||
"Change user/group to %s/%s failed: %s",
|
||||
get_cmdarg(&nDPIsrvd_options.user),
|
||||
(is_cmdarg_set(&nDPIsrvd_options.group) != 0 ? get_cmdarg(&nDPIsrvd_options.group) : "-"),
|
||||
"Could not chmod/chown `%s' to user `%s' and group `%s': %s",
|
||||
GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath),
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
logger(1,
|
||||
"Change user/group to %s/%s failed.",
|
||||
get_cmdarg(&nDPIsrvd_options.user),
|
||||
(is_cmdarg_set(&nDPIsrvd_options.group) != 0 ? get_cmdarg(&nDPIsrvd_options.group) : "-"));
|
||||
"Could not chmod/chown `%s' to user `%s': %s",
|
||||
GET_CMDARG_STR(nDPIsrvd_options.collector_un_sockpath),
|
||||
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;
|
||||
}
|
||||
@@ -1713,20 +1908,23 @@ int main(int argc, char ** argv)
|
||||
retval = mainloop(&io);
|
||||
|
||||
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:
|
||||
close(collector_un_sockfd);
|
||||
close(distributor_un_sockfd);
|
||||
close(distributor_in_sockfd);
|
||||
|
||||
daemonize_shutdown(get_cmdarg(&nDPIsrvd_options.pidfile));
|
||||
daemonize_shutdown(GET_CMDARG_STR(nDPIsrvd_options.pidfile));
|
||||
logger(0, "Bye.");
|
||||
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]
|
||||
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
|
||||
Environment=COLLECTOR_PATH=/var/run/ndpisrvd-collector NDPID_ARGS="-A -z"
|
||||
EnvironmentFile=@CMAKE_INSTALL_PREFIX@/etc/default/ndpid
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -4,11 +4,10 @@ After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=@CMAKE_INSTALL_PREFIX@/bin/nDPIsrvd -c ${COLLECTOR_PATH}
|
||||
ExecStopPost=/bin/rm -f /var/run/ndpisrvd-collector
|
||||
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"'
|
||||
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
|
||||
Environment=COLLECTOR_PATH=/var/run/ndpisrvd-collector
|
||||
EnvironmentFile=@CMAKE_INSTALL_PREFIX@/etc/default/ndpid
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
377
utils.c
377
utils.c
@@ -1,3 +1,4 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
@@ -10,11 +11,19 @@
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.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];
|
||||
|
||||
static char const * app_name = NULL;
|
||||
@@ -22,40 +31,151 @@ static int daemonize = 0;
|
||||
static int log_to_console = 0;
|
||||
static int log_to_file_fd = -1;
|
||||
|
||||
void set_cmdarg(struct cmdarg * const ca, char const * const val)
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
free(ca->value);
|
||||
ca->value = strdup(val);
|
||||
if (ca->type != CMDTYPE_STRING)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
@@ -218,11 +338,7 @@ int daemonize_shutdown(char const * const pidfile)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int change_user_group(char const * const user,
|
||||
char const * const group,
|
||||
char const * const pidfile,
|
||||
char const * const uds_collector_path,
|
||||
char const * const uds_distributor_path)
|
||||
int change_user_group(char const * const user, char const * const group, char const * const pidfile)
|
||||
{
|
||||
struct passwd * pwd;
|
||||
struct group * grp;
|
||||
@@ -237,7 +353,7 @@ int change_user_group(char const * const user,
|
||||
pwd = getpwnam(user);
|
||||
if (pwd == NULL)
|
||||
{
|
||||
return -errno;
|
||||
return (errno != 0 ? -errno : -ENOENT);
|
||||
}
|
||||
|
||||
if (group != NULL)
|
||||
@@ -246,7 +362,7 @@ int change_user_group(char const * const user,
|
||||
grp = getgrnam(group);
|
||||
if (grp == NULL)
|
||||
{
|
||||
return -errno;
|
||||
return (errno != 0 ? -errno : -ENOENT);
|
||||
}
|
||||
gid = grp->gr_gid;
|
||||
}
|
||||
@@ -255,23 +371,6 @@ int change_user_group(char const * const user,
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
app_name = name;
|
||||
@@ -454,6 +603,160 @@ char const * get_nDPId_version(void)
|
||||
"unknown"
|
||||
#endif
|
||||
"\n"
|
||||
"(C) 2020-2023 Toni Uhlig\n"
|
||||
"(C) 2020-2024 Toni Uhlig\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
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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
|
||||
{
|
||||
char * value;
|
||||
char const * const default_value;
|
||||
enum cmdtype type;
|
||||
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
|
||||
char const * get_cmdarg(struct cmdarg const * const ca);
|
||||
int set_config_from(struct confopt * const co, char const * const from);
|
||||
|
||||
WARN_UNUSED
|
||||
int is_cmdarg_set(struct cmdarg const * const ca);
|
||||
void set_cmdarg_string(struct cmdarg * const ca, char const * const val);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
WARN_UNUSED
|
||||
int change_user_group(char const * const user,
|
||||
char const * const group,
|
||||
char const * const pidfile,
|
||||
char const * const uds_collector_path,
|
||||
char const * const uds_distributor_path);
|
||||
int change_user_group(char const * const user, char const * const group, char const * const pidfile);
|
||||
|
||||
WARN_UNUSED
|
||||
int chmod_chown(char const * const path, mode_t mode, char const * const user, char const * const group);
|
||||
|
||||
void init_logging(char const * const daemon_name);
|
||||
|
||||
@@ -73,4 +131,7 @@ int set_fd_cloexec(int fd);
|
||||
WARN_UNUSED
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user