From 769457c165488fb8059ecb843a1c200f69dce95d Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Tue, 30 Jun 2020 08:54:52 +0200 Subject: Centralize scfg validation and use in minecctl to implement a lint command --- shared/config-parser.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) (limited to 'shared/config-parser.c') diff --git a/shared/config-parser.c b/shared/config-parser.c index ee30156..6c2d33d 100644 --- a/shared/config-parser.c +++ b/shared/config-parser.c @@ -221,6 +221,148 @@ static char *systemd_object_path(const char *service) return r; } +/* FIXME: Add a strict argument */ +bool scfg_validate(struct server_config *scfg) +{ + struct saddr *saddr; + uint16_t port; + + if (!scfg) { + error("invalid arguments"); + return false; + } + + if (!scfg->filename) { + error("filename not set"); + return false; + } + + if (!list_empty(&scfg->dnslookups)) { + error("%s: pending DNS requests", + scfg->filename); + return false; + } + + if (scfg->stop_method == SERVER_STOP_METHOD_RCON && + list_empty(&scfg->rcons)) { + error("%s: rcon stop method missing rcon address", + scfg->filename); + return false; + } + + if (scfg->stop_method == SERVER_STOP_METHOD_RCON && + !scfg->rcon_password) { + error("%s: rcon stop method missing rcon password", + scfg->filename); + return false; + } + + if ((scfg->start_method == SERVER_START_METHOD_SYSTEMD || + scfg->stop_method == SERVER_STOP_METHOD_SYSTEMD)) { + if (!scfg->systemd_service || !scfg->systemd_obj) { + error("%s: systemd start/stop method missing " + "systemd service", scfg->filename); + return false; + } else { + if (scfg->systemd_service || scfg->systemd_obj) { + error("%s: systemd service set but not used", + scfg->filename); + return false; + } + } + } + + if (scfg->idle_timeout > 0 && + scfg->stop_method == SERVER_STOP_METHOD_UNDEFINED) { + error("%s: idle_timeout set but missing stop method", + scfg->filename); + return false; + } + + switch (scfg->type) { + case SERVER_TYPE_ANNOUNCE: + if (scfg->announce_port == 0) { + error("%s: missing announce port", scfg->filename); + return false; + } + + if (scfg->start_method != SERVER_START_METHOD_UNDEFINED) { + error("%s: can't set start_method for announce server", + scfg->filename); + return false; + } + + if (scfg->start_exec) { + error("%s: can't set start_exec for announce server", + scfg->filename); + return false; + } + + if (!list_empty(&scfg->locals)) { + error("%s: can't set local addresses for announce server", + scfg->filename); + return false; + } + + if (!list_empty(&scfg->remotes)) { + error("%s: can't set remote addresses for announce server", + scfg->filename); + return false; + } + + break; + + case SERVER_TYPE_PROXY: + if (scfg->announce_port == 0) { + error("%s: can't set announce port for proxy server", + scfg->filename); + return false; + } + + if (list_empty(&scfg->locals)) { + error("%s: missing local addresses for proxy server", + scfg->filename); + return false; + } + + if (list_empty(&scfg->remotes)) { + error("%s: missing remote addresses for proxy server", + scfg->filename); + return false; + } + + list_for_each_entry(saddr, &scfg->locals, list) { + port = saddr_port(saddr); + + if (port == 0) { + error("%s: invalid local port", scfg->filename); + return false; + } + + if (scfg->announce_port == 0) + scfg->announce_port = port; + else if (scfg->announce_port != port) { + error("%s: multiple local ports", scfg->filename); + return false; + } + } + + if (scfg->announce_port == 0) { + error("%s: can't determine which port to announce", + scfg->filename); + return false; + } + + break; + + default: + error("%s: can't determine server type", scfg->filename); + return false; + } + + return true; +} + #define INVALID(fmt, ...) \ do { \ verbose("%s: " fmt, scfg->filename __VA_OPT__(,) __VA_ARGS__); \ -- cgit v1.2.3