From d74bcf2dadfa4fc6c432ba0585b6dc4a77e81f0e Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Mon, 22 Jun 2020 12:11:18 +0200 Subject: Rename config to config-parse --- config-parse.c | 492 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ config-parse.h | 59 +++++++ config.c | 492 -------------------------------------------------------- config.h | 59 ------- idle.c | 1 - main.c | 2 +- meson.build | 2 +- server-config.c | 2 +- server.c | 2 +- 9 files changed, 555 insertions(+), 556 deletions(-) create mode 100644 config-parse.c create mode 100644 config-parse.h delete mode 100644 config.c delete mode 100644 config.h diff --git a/config-parse.c b/config-parse.c new file mode 100644 index 0000000..34fbc64 --- /dev/null +++ b/config-parse.c @@ -0,0 +1,492 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "uring.h" +#include "config-parse.h" +#include "server.h" + +static void +eat_whitespace_and_comments(char **pos) +{ + assert_return(pos && *pos); + + while (true) { + while (isspace(**pos)) + (*pos)++; + + if (**pos != '#') + return; + + while (**pos != '\r' && **pos != '\n' && **pos != '\0') + (*pos)++; + } +} + +static char * +get_line(char **pos) +{ + char *begin, *end; + + assert_return(pos && *pos, NULL); + + begin = *pos; + while (isspace(*begin)) + begin++; + + if (*begin == '\0') + return NULL; + + end = begin; + while (*end != '\n' && *end != '\0') + end++; + + if (*end == '\0') + *pos = end; + else + *pos = end + 1; + + while (isspace(*end)) { + *end = '\0'; + end--; + } + + return begin; +} + +static bool +dnslookup(const char *name, uint16_t port, struct cfg_value *rvalue, bool async) +{ + struct sockaddr_in *in4; + struct sockaddr_in6 *in6; + struct dns_async tmp; + struct dns_async *dns; + int mode = async ? GAI_NOWAIT : GAI_WAIT; + struct addrinfo *results = NULL, *ai; + struct saddr *saddr = NULL; + bool rv = false; + int r; + + assert_return(!empty_str(name) && strlen(name) < sizeof(dns->name) && port > 0 && rvalue, false); + + if (async) { + rvalue->type = CFG_VAL_TYPE_ASYNC_ADDRS; + rvalue->dns_async = NULL; + dns = zmalloc(sizeof(*dns)); + if (!dns) { + error("async DNS lookup of %s failed: %m", name); + goto out; + } + debug(DBG_DNS, "doing async DNS lookup of %s: %p", name, dns); + } else { + memset(&tmp, 0, sizeof(tmp)); + dns = &tmp; + debug(DBG_DNS, "doing sync DNS lookup of %s", name); + } + + sprintf(dns->name, "%s", name); + sprintf(dns->port, "%" PRIu16, port); + + dns->req.ai_family = AF_UNSPEC; + dns->req.ai_socktype = SOCK_STREAM; + dns->req.ai_protocol = 0; + dns->req.ai_flags = AI_NUMERICSERV; + + dns->sev.sigev_notify = SIGEV_SIGNAL; + dns->sev.sigev_signo = SIGUSR1; + dns->sev.sigev_value.sival_ptr = dns; + + dns->gcb.ar_name = dns->name; + dns->gcb.ar_service = dns->port; + dns->gcb.ar_request = &dns->req; + + struct gaicb *gcbs[] = { &dns->gcb }; + + r = getaddrinfo_a(mode, gcbs, ARRAY_SIZE(gcbs), &dns->sev); + if (r != 0) { + error("getaddrinfo(%s:%" PRIu16 "): %s", name, port, gai_strerror(r)); + goto out; + } + + if (async) { + rvalue->dns_async = dns; + rv = true; + goto out; + } + + results = dns->gcb.ar_result; + + for (ai = results; ai; ai = ai->ai_next) { + saddr = zmalloc(sizeof(*saddr)); + if (!saddr) { + error("sync DNS lookup of %s failed: %m", name); + goto out; + } + + switch (ai->ai_family) { + case AF_INET: + in4 = (struct sockaddr_in *)ai->ai_addr; + saddr_set_ipv4(saddr, in4->sin_addr.s_addr, in4->sin_port); + error("addrstr: %s", saddr->addrstr); + list_add(&saddr->list, &rvalue->saddrs); + break; + + case AF_INET6: + in6 = (struct sockaddr_in6 *)ai->ai_addr; + saddr_set_ipv6(saddr, &in6->sin6_addr, in6->sin6_port); + error("addrstr: %s", saddr->addrstr); + list_add(&saddr->list, &rvalue->saddrs); + break; + + default: + error("getaddrinfo(%s:%s): unknown address family (%i)", + dns->name, dns->port, ai->ai_family); + xfree(saddr); + break; + } + } + + rv = true; + +out: + freeaddrinfo(results); + return rv; +} + +static bool +strtosockaddrs(const char *str, struct cfg_value *rvalue, bool async) +{ + struct saddr *saddr; + uint16_t port; + char *tmp; + struct list_head *list; + unsigned naddrs = 0; + + assert_return(!empty_str(str) && rvalue, false); + + rvalue->type = CFG_VAL_TYPE_ADDRS; + list = &rvalue->saddrs; + list_init(list); + + if (*str == '[') { + /* IPv6, [a:b:c...h]:p or [*]:p */ + debug(DBG_CFG, "attempting to parse IPv6 addr (%s)", str); + + str++; + tmp = strchr(str, ']'); + if (!tmp) + goto error; + *tmp = '\0'; + + saddr = zmalloc(sizeof(*saddr)); + if (!saddr) + goto error; + + /* early list_add to make sure saddr is free():d on error */ + list_add(&saddr->list, list); + + if (streq(str, "*")) + saddr->in6.sin6_addr = in6addr_any; + else if (inet_pton(AF_INET6, str, &saddr->in6.sin6_addr) <= 0) + goto error; + + tmp++; + if (*tmp != ':') + goto error; + + tmp++; + if (strtou16_strict(tmp, &port) < 0) + goto error; + + saddr_set_ipv6(saddr, NULL, htons(port)); + naddrs++; + + } else if (*str == '*') { + /* IPv4, *:p */ + debug(DBG_CFG, "attempting to parse IPv4 addr (%s)", str); + + str++; + if (*str != ':') + goto error; + + str++; + if (strtou16_strict(str, &port) < 0) + goto error; + + saddr = zmalloc(sizeof(*saddr)); + if (!saddr) + goto error; + + saddr_set_ipv4(saddr, INADDR_ANY, htons(port)); + list_add(&saddr->list, list); + naddrs++; + + } else if ((tmp = strchr(str, ':'))) { + /* IPv4, a.b.c.d:p or IPv4/6 hostname:p */ + debug(DBG_CFG, "attempting to parse IPv4 addr or hostname (%s)", str); + + *tmp = '\0'; + tmp++; + if (strtou16_strict(tmp, &port) < 0) + goto error; + + saddr = zmalloc(sizeof(*saddr)); + if (!saddr) + goto error; + + if (inet_pton(AF_INET, str, &saddr->in4.sin_addr) > 0) { + debug(DBG_CFG, "got an IPv4:port (%s:%" PRIu16 ")", str, port); + saddr_set_ipv4(saddr, saddr->in4.sin_addr.s_addr, htons(port)); + list_add(&saddr->list, list); + naddrs++; + goto success; + } + + xfree(saddr); + debug(DBG_CFG, "maybe got a hostname:port (%s:%" PRIu16 ")", str, port); + if (!dnslookup(str, port, rvalue, async)) + goto error; + + } else if (strtou16_strict(tmp, &port) == 0) { + /* Port */ + debug(DBG_CFG, "attempting to parse a port number (%s)", str); + + saddr = zmalloc(sizeof(*saddr)); + if (!saddr) + goto error; + + saddr_set_ipv6(saddr, &in6addr_any, htons(port)); + list_add(&saddr->list, list); + naddrs++; + + saddr = zmalloc(sizeof(*saddr)); + if (!saddr) + goto error; + + saddr_set_ipv4(saddr, INADDR_ANY, htons(port)); + list_add(&saddr->list, list); + naddrs++; + + } else { + /* Unknown */ + error("unable to parse address: %s", str); + goto error; + } + +success: + switch (rvalue->type) { + case CFG_VAL_TYPE_ADDRS: + if (list_empty(list) || naddrs == 0) { + error("empty address list"); + return false; + } + + debug(DBG_CFG, "parsed to %u addresses", naddrs); + return true; + + case CFG_VAL_TYPE_ASYNC_ADDRS: + debug(DBG_CFG, "looking up address asynchronously"); + return true; + + default: + error("invalid rvalue type"); + rvalue->type = CFG_VAL_TYPE_INVALID; + break; + } + +error: + if (rvalue->type == CFG_VAL_TYPE_ADDRS && !list_empty(list)) { + struct saddr *tmp; + + list_for_each_entry_safe(saddr, tmp, list, list) { + list_del(&saddr->list); + xfree(saddr); + } + } + return false; +} + +/* Returns true if there's data left to parse in buf */ +bool +config_parse_line(const char *filename, char **buf, + struct cfg_key_value_map *kvmap, int *rkey, + const char **rkeyname, struct cfg_value *rvalue) +{ + char *line, *tmp, *key; + int i; + + assert_return(buf && *buf && kvmap && rkey && rkeyname && rvalue, false); + + eat_whitespace_and_comments(buf); + line = get_line(buf); + if (!line) + return false; + + debug(DBG_CFG, "%s: parsing config line: %s", filename, line); + + tmp = line; + while (isspace(*tmp)) + tmp++; + + if (*tmp == '\0') + goto error; + + key = tmp; + while (*tmp != '\0' && !isspace(*tmp)) + tmp++; + + if (*tmp == '\0') + goto error; + + *tmp = '\0'; + tmp++; + + while (isspace(*tmp)) + tmp++; + + if (*tmp != '=') + goto error; + + tmp++; + while (isspace(*tmp)) + tmp++; + + if (*tmp == '\0') + goto error; + + for (i = 0; kvmap[i].key_name; i++) { + if (!streq(kvmap[i].key_name, key)) + continue; + + switch (kvmap[i].value_type) { + + case CFG_VAL_TYPE_STRING: + rvalue->type = CFG_VAL_TYPE_STRING; + rvalue->str = tmp; + break; + + case CFG_VAL_TYPE_UINT16: { + uint16_t v; + + if (strtou16_strict(tmp, &v) < 0) + goto error; + + rvalue->type = CFG_VAL_TYPE_UINT16; + rvalue->uint16 = v; + break; + } + + case CFG_VAL_TYPE_ADDRS: + if (!strtosockaddrs(tmp, rvalue, false)) + goto error; + + if (rvalue->type != CFG_VAL_TYPE_ADDRS) { + error("invalid type returned from strtosockaddrs"); + goto error; + } + + if (list_empty(&rvalue->saddrs)) { + error("empty address list"); + goto error; + } + break; + + case CFG_VAL_TYPE_ASYNC_ADDRS: + if (!strtosockaddrs(tmp, rvalue, true)) + goto error; + + switch (rvalue->type) { + case CFG_VAL_TYPE_ADDRS: + if (list_empty(&rvalue->saddrs)) { + error("empty address list"); + goto error; + } + break; + + case CFG_VAL_TYPE_ASYNC_ADDRS: + if (!rvalue->dns_async) { + error("dns_async not set"); + goto error; + } + break; + + default: + error("invalid type returned from strtosockaddrs"); + goto error; + } + + break; + + case CFG_VAL_TYPE_BOOL: + if (strcaseeq(tmp, "yes") || strcaseeq(tmp, "true")) { + rvalue->type = CFG_VAL_TYPE_BOOL; + rvalue->boolean = true; + } else if (strcaseeq(tmp, "no") || strcaseeq(tmp, "false")) { + rvalue->type = CFG_VAL_TYPE_BOOL; + rvalue->boolean = false; + } else { + error("invalid boolean value (%s)", tmp); + goto error; + } + break; + + case CFG_VAL_TYPE_INVALID: + /* fall through */ + default: + goto error; + } + + /* sanity check */ + if ((rvalue->type != kvmap[i].value_type) && + ((kvmap[i].value_type != CFG_VAL_TYPE_ASYNC_ADDRS) && + (rvalue->type != CFG_VAL_TYPE_ADDRS))) { + error("rvalue->type != kvmap->type"); + goto error; + } + + *rkey = kvmap[i].key_value; + *rkeyname = kvmap[i].key_name; + return true; + } + +error: + /* FIXME: the line is already mangled here, a line number would be nice */ + error("%s: invalid config line: %s", filename, line); + rvalue->type = CFG_VAL_TYPE_INVALID; + *rkey = 0; + *rkeyname = NULL; + return true; +} + +bool +config_parse_header(const char *filename, const char *title, char **buf) +{ + char *line; + + assert_return(!empty_str(filename) && !empty_str(title) && buf && *buf, false); + + eat_whitespace_and_comments(buf); + + line = get_line(buf); + if (!line) { + error("%s: missing header in configuration file", filename); + return false; + } else { + char titlehdr[strlen(title) + 3]; + + sprintf(titlehdr, "[%s]", title); + if (!streq(line, titlehdr)) { + error("%s: incorrect header in configuration file", filename); + return false; + } + } + + return true; +} diff --git a/config-parse.h b/config-parse.h new file mode 100644 index 0000000..c8d10dc --- /dev/null +++ b/config-parse.h @@ -0,0 +1,59 @@ +#ifndef fooconfigparsehfoo +#define fooconfigparsehfoo + +#define _GNU_SOURCE +#include +#include +#include +#include + +enum cfg_value_type { + CFG_VAL_TYPE_INVALID, + CFG_VAL_TYPE_STRING, + CFG_VAL_TYPE_UINT16, + CFG_VAL_TYPE_ADDRS, + CFG_VAL_TYPE_ASYNC_ADDRS, + CFG_VAL_TYPE_BOOL, +}; + +struct dns_async; + +typedef void (dns_cb_t)(struct dns_async *); + +struct dns_async { + char name[FQDN_STR_LEN + 1]; + char port[PORT_STR_LEN + 1]; + struct addrinfo req; + struct gaicb gcb; + struct sigevent sev; + dns_cb_t *cb; + void *priv; + struct list_head list; +}; + +struct cfg_key_value_map { + const char *key_name; + int key_value; + enum cfg_value_type value_type; +}; + +struct cfg_value { + enum cfg_value_type type; + union { + const char *str; + uint16_t uint16; + struct list_head saddrs; + struct dns_async *dns_async; + bool boolean; + }; +}; + +bool config_parse_line(const char *filename, char **buf, + struct cfg_key_value_map *kvmap, + int *rkey, const char **rkeyname, + struct cfg_value *rvalue); + +bool config_parse_header(const char *filename, + const char *title, char **buf); + +#endif diff --git a/config.c b/config.c deleted file mode 100644 index eb980f8..0000000 --- a/config.c +++ /dev/null @@ -1,492 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -#include "main.h" -#include "uring.h" -#include "config.h" -#include "server.h" - -static void -eat_whitespace_and_comments(char **pos) -{ - assert_return(pos && *pos); - - while (true) { - while (isspace(**pos)) - (*pos)++; - - if (**pos != '#') - return; - - while (**pos != '\r' && **pos != '\n' && **pos != '\0') - (*pos)++; - } -} - -static char * -get_line(char **pos) -{ - char *begin, *end; - - assert_return(pos && *pos, NULL); - - begin = *pos; - while (isspace(*begin)) - begin++; - - if (*begin == '\0') - return NULL; - - end = begin; - while (*end != '\n' && *end != '\0') - end++; - - if (*end == '\0') - *pos = end; - else - *pos = end + 1; - - while (isspace(*end)) { - *end = '\0'; - end--; - } - - return begin; -} - -static bool -dnslookup(const char *name, uint16_t port, struct cfg_value *rvalue, bool async) -{ - struct sockaddr_in *in4; - struct sockaddr_in6 *in6; - struct dns_async tmp; - struct dns_async *dns; - int mode = async ? GAI_NOWAIT : GAI_WAIT; - struct addrinfo *results = NULL, *ai; - struct saddr *saddr = NULL; - bool rv = false; - int r; - - assert_return(!empty_str(name) && strlen(name) < sizeof(dns->name) && port > 0 && rvalue, false); - - if (async) { - rvalue->type = CFG_VAL_TYPE_ASYNC_ADDRS; - rvalue->dns_async = NULL; - dns = zmalloc(sizeof(*dns)); - if (!dns) { - error("async DNS lookup of %s failed: %m", name); - goto out; - } - debug(DBG_DNS, "doing async DNS lookup of %s: %p", name, dns); - } else { - memset(&tmp, 0, sizeof(tmp)); - dns = &tmp; - debug(DBG_DNS, "doing sync DNS lookup of %s", name); - } - - sprintf(dns->name, "%s", name); - sprintf(dns->port, "%" PRIu16, port); - - dns->req.ai_family = AF_UNSPEC; - dns->req.ai_socktype = SOCK_STREAM; - dns->req.ai_protocol = 0; - dns->req.ai_flags = AI_NUMERICSERV; - - dns->sev.sigev_notify = SIGEV_SIGNAL; - dns->sev.sigev_signo = SIGUSR1; - dns->sev.sigev_value.sival_ptr = dns; - - dns->gcb.ar_name = dns->name; - dns->gcb.ar_service = dns->port; - dns->gcb.ar_request = &dns->req; - - struct gaicb *gcbs[] = { &dns->gcb }; - - r = getaddrinfo_a(mode, gcbs, ARRAY_SIZE(gcbs), &dns->sev); - if (r != 0) { - error("getaddrinfo(%s:%" PRIu16 "): %s", name, port, gai_strerror(r)); - goto out; - } - - if (async) { - rvalue->dns_async = dns; - rv = true; - goto out; - } - - results = dns->gcb.ar_result; - - for (ai = results; ai; ai = ai->ai_next) { - saddr = zmalloc(sizeof(*saddr)); - if (!saddr) { - error("sync DNS lookup of %s failed: %m", name); - goto out; - } - - switch (ai->ai_family) { - case AF_INET: - in4 = (struct sockaddr_in *)ai->ai_addr; - saddr_set_ipv4(saddr, in4->sin_addr.s_addr, in4->sin_port); - error("addrstr: %s", saddr->addrstr); - list_add(&saddr->list, &rvalue->saddrs); - break; - - case AF_INET6: - in6 = (struct sockaddr_in6 *)ai->ai_addr; - saddr_set_ipv6(saddr, &in6->sin6_addr, in6->sin6_port); - error("addrstr: %s", saddr->addrstr); - list_add(&saddr->list, &rvalue->saddrs); - break; - - default: - error("getaddrinfo(%s:%s): unknown address family (%i)", - dns->name, dns->port, ai->ai_family); - xfree(saddr); - break; - } - } - - rv = true; - -out: - freeaddrinfo(results); - return rv; -} - -static bool -strtosockaddrs(const char *str, struct cfg_value *rvalue, bool async) -{ - struct saddr *saddr; - uint16_t port; - char *tmp; - struct list_head *list; - unsigned naddrs = 0; - - assert_return(!empty_str(str) && rvalue, false); - - rvalue->type = CFG_VAL_TYPE_ADDRS; - list = &rvalue->saddrs; - list_init(list); - - if (*str == '[') { - /* IPv6, [a:b:c...h]:p or [*]:p */ - debug(DBG_CFG, "attempting to parse IPv6 addr (%s)", str); - - str++; - tmp = strchr(str, ']'); - if (!tmp) - goto error; - *tmp = '\0'; - - saddr = zmalloc(sizeof(*saddr)); - if (!saddr) - goto error; - - /* early list_add to make sure saddr is free():d on error */ - list_add(&saddr->list, list); - - if (streq(str, "*")) - saddr->in6.sin6_addr = in6addr_any; - else if (inet_pton(AF_INET6, str, &saddr->in6.sin6_addr) <= 0) - goto error; - - tmp++; - if (*tmp != ':') - goto error; - - tmp++; - if (strtou16_strict(tmp, &port) < 0) - goto error; - - saddr_set_ipv6(saddr, NULL, htons(port)); - naddrs++; - - } else if (*str == '*') { - /* IPv4, *:p */ - debug(DBG_CFG, "attempting to parse IPv4 addr (%s)", str); - - str++; - if (*str != ':') - goto error; - - str++; - if (strtou16_strict(str, &port) < 0) - goto error; - - saddr = zmalloc(sizeof(*saddr)); - if (!saddr) - goto error; - - saddr_set_ipv4(saddr, INADDR_ANY, htons(port)); - list_add(&saddr->list, list); - naddrs++; - - } else if ((tmp = strchr(str, ':'))) { - /* IPv4, a.b.c.d:p or IPv4/6 hostname:p */ - debug(DBG_CFG, "attempting to parse IPv4 addr or hostname (%s)", str); - - *tmp = '\0'; - tmp++; - if (strtou16_strict(tmp, &port) < 0) - goto error; - - saddr = zmalloc(sizeof(*saddr)); - if (!saddr) - goto error; - - if (inet_pton(AF_INET, str, &saddr->in4.sin_addr) > 0) { - debug(DBG_CFG, "got an IPv4:port (%s:%" PRIu16 ")", str, port); - saddr_set_ipv4(saddr, saddr->in4.sin_addr.s_addr, htons(port)); - list_add(&saddr->list, list); - naddrs++; - goto success; - } - - xfree(saddr); - debug(DBG_CFG, "maybe got a hostname:port (%s:%" PRIu16 ")", str, port); - if (!dnslookup(str, port, rvalue, async)) - goto error; - - } else if (strtou16_strict(tmp, &port) == 0) { - /* Port */ - debug(DBG_CFG, "attempting to parse a port number (%s)", str); - - saddr = zmalloc(sizeof(*saddr)); - if (!saddr) - goto error; - - saddr_set_ipv6(saddr, &in6addr_any, htons(port)); - list_add(&saddr->list, list); - naddrs++; - - saddr = zmalloc(sizeof(*saddr)); - if (!saddr) - goto error; - - saddr_set_ipv4(saddr, INADDR_ANY, htons(port)); - list_add(&saddr->list, list); - naddrs++; - - } else { - /* Unknown */ - error("unable to parse address: %s", str); - goto error; - } - -success: - switch (rvalue->type) { - case CFG_VAL_TYPE_ADDRS: - if (list_empty(list) || naddrs == 0) { - error("empty address list"); - return false; - } - - debug(DBG_CFG, "parsed to %u addresses", naddrs); - return true; - - case CFG_VAL_TYPE_ASYNC_ADDRS: - debug(DBG_CFG, "looking up address asynchronously"); - return true; - - default: - error("invalid rvalue type"); - rvalue->type = CFG_VAL_TYPE_INVALID; - break; - } - -error: - if (rvalue->type == CFG_VAL_TYPE_ADDRS && !list_empty(list)) { - struct saddr *tmp; - - list_for_each_entry_safe(saddr, tmp, list, list) { - list_del(&saddr->list); - xfree(saddr); - } - } - return false; -} - -/* Returns true if there's data left to parse in buf */ -bool -config_parse_line(const char *filename, char **buf, - struct cfg_key_value_map *kvmap, int *rkey, - const char **rkeyname, struct cfg_value *rvalue) -{ - char *line, *tmp, *key; - int i; - - assert_return(buf && *buf && kvmap && rkey && rkeyname && rvalue, false); - - eat_whitespace_and_comments(buf); - line = get_line(buf); - if (!line) - return false; - - debug(DBG_CFG, "%s: parsing config line: %s", filename, line); - - tmp = line; - while (isspace(*tmp)) - tmp++; - - if (*tmp == '\0') - goto error; - - key = tmp; - while (*tmp != '\0' && !isspace(*tmp)) - tmp++; - - if (*tmp == '\0') - goto error; - - *tmp = '\0'; - tmp++; - - while (isspace(*tmp)) - tmp++; - - if (*tmp != '=') - goto error; - - tmp++; - while (isspace(*tmp)) - tmp++; - - if (*tmp == '\0') - goto error; - - for (i = 0; kvmap[i].key_name; i++) { - if (!streq(kvmap[i].key_name, key)) - continue; - - switch (kvmap[i].value_type) { - - case CFG_VAL_TYPE_STRING: - rvalue->type = CFG_VAL_TYPE_STRING; - rvalue->str = tmp; - break; - - case CFG_VAL_TYPE_UINT16: { - uint16_t v; - - if (strtou16_strict(tmp, &v) < 0) - goto error; - - rvalue->type = CFG_VAL_TYPE_UINT16; - rvalue->uint16 = v; - break; - } - - case CFG_VAL_TYPE_ADDRS: - if (!strtosockaddrs(tmp, rvalue, false)) - goto error; - - if (rvalue->type != CFG_VAL_TYPE_ADDRS) { - error("invalid type returned from strtosockaddrs"); - goto error; - } - - if (list_empty(&rvalue->saddrs)) { - error("empty address list"); - goto error; - } - break; - - case CFG_VAL_TYPE_ASYNC_ADDRS: - if (!strtosockaddrs(tmp, rvalue, true)) - goto error; - - switch (rvalue->type) { - case CFG_VAL_TYPE_ADDRS: - if (list_empty(&rvalue->saddrs)) { - error("empty address list"); - goto error; - } - break; - - case CFG_VAL_TYPE_ASYNC_ADDRS: - if (!rvalue->dns_async) { - error("dns_async not set"); - goto error; - } - break; - - default: - error("invalid type returned from strtosockaddrs"); - goto error; - } - - break; - - case CFG_VAL_TYPE_BOOL: - if (strcaseeq(tmp, "yes") || strcaseeq(tmp, "true")) { - rvalue->type = CFG_VAL_TYPE_BOOL; - rvalue->boolean = true; - } else if (strcaseeq(tmp, "no") || strcaseeq(tmp, "false")) { - rvalue->type = CFG_VAL_TYPE_BOOL; - rvalue->boolean = false; - } else { - error("invalid boolean value (%s)", tmp); - goto error; - } - break; - - case CFG_VAL_TYPE_INVALID: - /* fall through */ - default: - goto error; - } - - /* sanity check */ - if ((rvalue->type != kvmap[i].value_type) && - ((kvmap[i].value_type != CFG_VAL_TYPE_ASYNC_ADDRS) && - (rvalue->type != CFG_VAL_TYPE_ADDRS))) { - error("rvalue->type != kvmap->type"); - goto error; - } - - *rkey = kvmap[i].key_value; - *rkeyname = kvmap[i].key_name; - return true; - } - -error: - /* FIXME: the line is already mangled here, a line number would be nice */ - error("%s: invalid config line: %s", filename, line); - rvalue->type = CFG_VAL_TYPE_INVALID; - *rkey = 0; - *rkeyname = NULL; - return true; -} - -bool -config_parse_header(const char *filename, const char *title, char **buf) -{ - char *line; - - assert_return(!empty_str(filename) && !empty_str(title) && buf && *buf, false); - - eat_whitespace_and_comments(buf); - - line = get_line(buf); - if (!line) { - error("%s: missing header in configuration file", filename); - return false; - } else { - char titlehdr[strlen(title) + 3]; - - sprintf(titlehdr, "[%s]", title); - if (!streq(line, titlehdr)) { - error("%s: incorrect header in configuration file", filename); - return false; - } - } - - return true; -} diff --git a/config.h b/config.h deleted file mode 100644 index a88be90..0000000 --- a/config.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef fooconfighfoo -#define fooconfighfoo - -#define _GNU_SOURCE -#include -#include -#include -#include - -enum cfg_value_type { - CFG_VAL_TYPE_INVALID, - CFG_VAL_TYPE_STRING, - CFG_VAL_TYPE_UINT16, - CFG_VAL_TYPE_ADDRS, - CFG_VAL_TYPE_ASYNC_ADDRS, - CFG_VAL_TYPE_BOOL, -}; - -struct dns_async; - -typedef void (dns_cb_t)(struct dns_async *); - -struct dns_async { - char name[FQDN_STR_LEN + 1]; - char port[PORT_STR_LEN + 1]; - struct addrinfo req; - struct gaicb gcb; - struct sigevent sev; - dns_cb_t *cb; - void *priv; - struct list_head list; -}; - -struct cfg_key_value_map { - const char *key_name; - int key_value; - enum cfg_value_type value_type; -}; - -struct cfg_value { - enum cfg_value_type type; - union { - const char *str; - uint16_t uint16; - struct list_head saddrs; - struct dns_async *dns_async; - bool boolean; - }; -}; - -bool config_parse_line(const char *filename, char **buf, - struct cfg_key_value_map *kvmap, - int *rkey, const char **rkeyname, - struct cfg_value *rvalue); - -bool config_parse_header(const char *filename, - const char *title, char **buf); - -#endif diff --git a/idle.c b/idle.c index 15abd72..e0eb525 100644 --- a/idle.c +++ b/idle.c @@ -10,7 +10,6 @@ #include "main.h" #include "uring.h" -#include "config.h" #include "server.h" #include "idle.h" diff --git a/main.c b/main.c index 1dbc3c2..c1c9f8f 100644 --- a/main.c +++ b/main.c @@ -19,7 +19,7 @@ #include "main.h" #include "uring.h" -#include "config.h" +#include "config-parse.h" #include "server.h" #include "server-config.h" #include "announce.h" diff --git a/meson.build b/meson.build index a4472cd..9348482 100644 --- a/meson.build +++ b/meson.build @@ -11,7 +11,7 @@ mcproxy_sources = [ 'server-proxy.c', 'server-config.c', 'announce.c', - 'config.c', + 'config-parse.c', 'rcon.c', 'idle.c', 'igmp.c', diff --git a/server-config.c b/server-config.c index d42022b..03259ca 100644 --- a/server-config.c +++ b/server-config.c @@ -12,7 +12,7 @@ #include "main.h" #include "uring.h" -#include "config.h" +#include "config-parse.h" #include "server.h" #include "server-config.h" diff --git a/server.c b/server.c index 55072c0..7c2bf52 100644 --- a/server.c +++ b/server.c @@ -16,7 +16,7 @@ #include "server.h" #include "server-proxy.h" #include "utils.h" -#include "config.h" +#include "config-parse.h" #include "idle.h" #include "rcon.h" #include "systemd.h" -- cgit v1.2.3