From de67a4a721c0fda9a9b5955f235baafba9ba393d Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Fri, 23 Oct 2026 21:48:58 +0200 Subject: Rework config file parser and tidy up mem inits --- opentracker.c | 233 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 159 insertions(+), 74 deletions(-) (limited to 'opentracker.c') diff --git a/opentracker.c b/opentracker.c index f63db72..e24beb2 100644 --- a/opentracker.c +++ b/opentracker.c @@ -438,8 +438,82 @@ static int scan_ip6_net(const char *src, ot_net *net) { return off + s - src; } +typedef enum { + CONFIG_UNKNOWN, + CONFIG_TRACKER_ROOTDIR, + CONFIG_TRACKER_USER, + CONFIG_LISTEN_TCP_UDP, + CONFIG_LISTEN_TCP, + CONFIG_LISTEN_UDP, + CONFIG_LISTEN_UDP_WORKERS, + CONFIG_ACCESS_WHITELIST, + CONFIG_ACCESS_BLACKLIST, + CONFIG_ACCESS_FIFO_ADD, + CONFIG_ACCESS_FIFO_DELETE, + CONFIG_ACCESS_STATS, + CONFIG_ACCESS_STATS_PATH, + CONFIG_ACCESS_PROXY, + CONFIG_TRACKER_REDIRECT_URL, + CONFIG_LIVESYNC_CLUSTER_NODE_IP, + CONFIG_LIVESYNC_CLUSTER_LISTEN, +} config_kind; + +typedef struct { + const char *name; + size_t len; + config_kind kind; +} config_key; + +#define CONFIG_KEY(s, k) { s, sizeof(s) - 1, k } + +static const config_key config_keys[] = { + CONFIG_KEY("tracker.rootdir", CONFIG_TRACKER_ROOTDIR), + CONFIG_KEY("tracker.user", CONFIG_TRACKER_USER), + CONFIG_KEY("listen.tcp_udp", CONFIG_LISTEN_TCP_UDP), + CONFIG_KEY("listen.tcp", CONFIG_LISTEN_TCP), + CONFIG_KEY("listen.udp", CONFIG_LISTEN_UDP), + CONFIG_KEY("listen.udp.workers", CONFIG_LISTEN_UDP_WORKERS), +#ifdef WANT_ACCESSLIST_WHITE + CONFIG_KEY("access.whitelist", CONFIG_ACCESS_WHITELIST), +#elif defined(WANT_ACCESSLIST_BLACK) + CONFIG_KEY("access.blacklist", CONFIG_ACCESS_BLACKLIST), +#endif +#ifdef WANT_DYNAMIC_ACCESSLIST + CONFIG_KEY("access.fifo_add", CONFIG_ACCESS_FIFO_ADD), + CONFIG_KEY("access.fifo_delete", CONFIG_ACCESS_FIFO_DELETE), +#endif +#ifdef WANT_RESTRICT_STATS + CONFIG_KEY("access.stats", CONFIG_ACCESS_STATS), +#endif + CONFIG_KEY("access.stats_path", CONFIG_ACCESS_STATS_PATH), +#ifdef WANT_IP_FROM_PROXY + CONFIG_KEY("access.proxy", CONFIG_ACCESS_PROXY), +#endif + CONFIG_KEY("tracker.redirect_url", CONFIG_TRACKER_REDIRECT_URL), +#ifdef WANT_SYNC_LIVE + CONFIG_KEY("livesync.cluster.node_ip", CONFIG_LIVESYNC_CLUSTER_NODE_IP), + CONFIG_KEY("livesync.cluster.listen", CONFIG_LIVESYNC_CLUSTER_LISTEN), +#endif +}; +static const size_t config_entry_count = sizeof(config_keys) / sizeof(config_keys[0]); + +static config_kind parse_config_key(char **p) { + size_t i; + for (i = 0; i < config_entry_count; ++i) { + const config_key *key = &config_keys[i]; + if (strncmp(*p, key->name, key->len) == 0 && isspace((unsigned char)(*p)[key->len])) { + *p += key->len + 1; + /* Skip white spaces */ + while (isspace((unsigned char)**p)) + ++(*p); + return key->kind; + } + } + return CONFIG_UNKNOWN; +} + int parse_configfile(char *config_filename) { - FILE *accesslist_filehandle; + FILE *config_file_handle; char inbuf[512]; ot_ip6 tmpip; #if defined(WANT_RESTRICT_STATS) || defined(WANT_IP_FROM_PROXY) || defined(WANT_SYNC_LIVE) @@ -447,19 +521,19 @@ int parse_configfile(char *config_filename) { #endif int bound = 0; - accesslist_filehandle = fopen(config_filename, "r"); + config_file_handle = fopen(config_filename, "r"); - if (accesslist_filehandle == NULL) { + if (config_file_handle == NULL) { fprintf(stderr, "Warning: Can't open config file: %s.", config_filename); return 0; } - while (fgets(inbuf, sizeof(inbuf), accesslist_filehandle)) { - char *p = inbuf; - size_t strl; + while (fgets(inbuf, sizeof(inbuf), config_file_handle)) { + char *p = inbuf, *end; + uint16_t tmpport = 6969; /* Skip white spaces */ - while (isspace(*p)) + while (isspace((unsigned char)*p)) ++p; /* Ignore comments and empty lines */ @@ -467,87 +541,98 @@ int parse_configfile(char *config_filename) { continue; /* consume trailing new lines and spaces */ - strl = strlen(p); - while (strl && isspace(p[strl - 1])) - p[--strl] = 0; + end = p + strlen(p); + while (end > p && isspace((unsigned char)end[-1])) + *--end = 0; /* Scan for commands */ - if (!byte_diff(p, 15, "tracker.rootdir") && isspace(p[15])) { - set_config_option(&g_serverdir, p + 16); - } else if (!byte_diff(p, 12, "tracker.user") && isspace(p[12])) { - set_config_option(&g_serveruser, p + 13); - } else if (!byte_diff(p, 14, "listen.tcp_udp") && isspace(p[14])) { - uint16_t tmpport = 6969; - if (!scan_ip6_port(p + 15, tmpip, &tmpport)) - goto parse_error; - ot_try_bind(tmpip, tmpport, FLAG_TCP); - ++bound; - ot_try_bind(tmpip, tmpport, FLAG_UDP); - ++bound; - } else if (!byte_diff(p, 10, "listen.tcp") && isspace(p[10])) { - uint16_t tmpport = 6969; - if (!scan_ip6_port(p + 11, tmpip, &tmpport)) - goto parse_error; - ot_try_bind(tmpip, tmpport, FLAG_TCP); - ++bound; - } else if (!byte_diff(p, 10, "listen.udp") && isspace(p[10])) { - uint16_t tmpport = 6969; - if (!scan_ip6_port(p + 11, tmpip, &tmpport)) - goto parse_error; - ot_try_bind(tmpip, tmpport, FLAG_UDP); - ++bound; - } else if (!byte_diff(p, 18, "listen.udp.workers") && isspace(p[18])) { - char *value = p + 18; - while (isspace(*value)) - ++value; - scan_uint(value, &g_udp_workers); + switch (parse_config_key(&p)) { + case CONFIG_TRACKER_ROOTDIR: + set_config_option(&g_serverdir, p); + break; + case CONFIG_TRACKER_USER: + set_config_option(&g_serveruser, p); + break; + case CONFIG_LISTEN_TCP_UDP: + if (!scan_ip6_port(p, tmpip, &tmpport)) + goto parse_error; + ot_try_bind(tmpip, tmpport, FLAG_TCP); + ++bound; + ot_try_bind(tmpip, tmpport, FLAG_UDP); + ++bound; + break; + case CONFIG_LISTEN_TCP: + if (!scan_ip6_port(p, tmpip, &tmpport)) + goto parse_error; + ot_try_bind(tmpip, tmpport, FLAG_TCP); + ++bound; + break; + case CONFIG_LISTEN_UDP: + if (!scan_ip6_port(p, tmpip, &tmpport)) + goto parse_error; + ot_try_bind(tmpip, tmpport, FLAG_UDP); + ++bound; + case CONFIG_LISTEN_UDP_WORKERS: + scan_uint(p, &g_udp_workers); + break; #ifdef WANT_ACCESSLIST_WHITE - } else if (!byte_diff(p, 16, "access.whitelist") && isspace(p[16])) { - set_config_option(&g_accesslist_filename, p + 17); + case CONFIG_ACCESS_WHITELIST: + set_config_option(&g_accesslist_filename, p); + break; #elif defined(WANT_ACCESSLIST_BLACK) - } else if (!byte_diff(p, 16, "access.blacklist") && isspace(p[16])) { - set_config_option(&g_accesslist_filename, p + 17); + case CONFIG_ACCESS_BLACKLIST: + set_config_option(&g_accesslist_filename, p); + break; #endif #ifdef WANT_DYNAMIC_ACCESSLIST - } else if (!byte_diff(p, 15, "access.fifo_add") && isspace(p[15])) { - set_config_option(&g_accesslist_pipe_add, p + 16); - } else if (!byte_diff(p, 18, "access.fifo_delete") && isspace(p[18])) { - set_config_option(&g_accesslist_pipe_delete, p + 19); + case CONFIG_ACCESS_FIFO_ADD: + set_config_option(&g_accesslist_pipe_add, p); + break; + case CONFIG_ACCESS_FIFO_DELETE: + set_config_option(&g_accesslist_pipe_delete, p); + break; #endif #ifdef WANT_RESTRICT_STATS - } else if (!byte_diff(p, 12, "access.stats") && isspace(p[12])) { - if (!scan_ip6_net(p + 13, &tmpnet)) - goto parse_error; - accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT); + case CONFIG_ACCESS_STATS: + if (!scan_ip6_net(p, &tmpnet)) + goto parse_error; + accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_STAT); + break; #endif - } else if (!byte_diff(p, 17, "access.stats_path") && isspace(p[17])) { - set_config_option(&g_stats_path, p + 18); + case CONFIG_ACCESS_STATS_PATH: + set_config_option(&g_stats_path, p); + break; #ifdef WANT_IP_FROM_PROXY - } else if (!byte_diff(p, 12, "access.proxy") && isspace(p[12])) { - if (!scan_ip6_net(p + 13, &tmpnet)) - goto parse_error; - accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY); + case CONFIG_ACCESS_PROXY: + if (!scan_ip6_net(p, &tmpnet)) + goto parse_error; + accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_PROXY); + break; #endif - } else if (!byte_diff(p, 20, "tracker.redirect_url") && isspace(p[20])) { - set_config_option(&g_redirecturl, p + 21); + case CONFIG_TRACKER_REDIRECT_URL: + set_config_option(&g_redirecturl, p); + break; #ifdef WANT_SYNC_LIVE - } else if (!byte_diff(p, 24, "livesync.cluster.node_ip") && isspace(p[24])) { - if (!scan_ip6_net(p + 25, &tmpnet)) - goto parse_error; - accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC); - } else if (!byte_diff(p, 23, "livesync.cluster.listen") && isspace(p[23])) { - uint16_t tmpport = LIVESYNC_PORT; - if (!scan_ip6_port(p + 24, tmpip, &tmpport)) - goto parse_error; - livesync_bind_mcast(tmpip, tmpport); + case CONFIG_LIVESYNC_CLUSTER_NODE_IP: + if (!scan_ip6_net(p, &tmpnet)) + goto parse_error; + accesslist_bless_net(&tmpnet, OT_PERMISSION_MAY_LIVESYNC); + break; + case CONFIG_LIVESYNC_CLUSTER_LISTEN: + tmpport = LIVESYNC_PORT; + if (!scan_ip6_port(p, tmpip, &tmpport)) + goto parse_error; + livesync_bind_mcast(tmpip, tmpport); + break; #endif - } else - fprintf(stderr, "Unhandled line in config file: %s\n", inbuf); - continue; - parse_error: - fprintf(stderr, "Parse error in config file: %s\n", inbuf); + default: + fprintf(stderr, "Unhandled line in config file: %s\n", inbuf); + break; + parse_error: + fprintf(stderr, "Parse error in config file: %s\n", inbuf); + } } - fclose(accesslist_filehandle); + fclose(config_file_handle); return bound; } -- cgit v1.3