summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2020-06-16 23:22:18 +0200
committerDavid Härdeman <david@hardeman.nu>2020-06-16 23:22:18 +0200
commit66377f809ef1c84672e12b1896f1a39e1957dc96 (patch)
tree492462a89ad9ad69de233d814584ade7ce04befe
parente74dad8526cc72ced4554f9af16464a00b230eec (diff)
Flesh out main config parsing
-rw-r--r--config.c11
-rw-r--r--config.h2
-rw-r--r--main.c101
-rw-r--r--main.h4
4 files changed, 114 insertions, 4 deletions
diff --git a/config.c b/config.c
index c49a7e9..5affeff 100644
--- a/config.c
+++ b/config.c
@@ -337,6 +337,17 @@ config_parse_line(struct cfg *cfg, const char *filename, char **buf,
break;
}
+ case CFG_VAL_TYPE_BOOL:
+ if (!strcasecmp(tmp, "yes"))
+ rvalue->boolean = true;
+ else if (!strcasecmp(tmp, "no"))
+ rvalue->boolean = false;
+ else {
+ error("invalid boolean value (%s)\n", tmp);
+ goto out;
+ }
+ break;
+
case CFG_VAL_TYPE_INVALID:
/* fall through */
default:
diff --git a/config.h b/config.h
index 2ea440a..4c3955f 100644
--- a/config.h
+++ b/config.h
@@ -6,6 +6,7 @@ enum cfg_value_type {
CFG_VAL_TYPE_STRING,
CFG_VAL_TYPE_UINT16,
CFG_VAL_TYPE_ADDRS,
+ CFG_VAL_TYPE_BOOL,
};
struct cfg_key_value_map {
@@ -18,6 +19,7 @@ union cfg_value {
const char *str;
uint16_t uint16;
struct list_head addrs;
+ bool boolean;
};
bool config_parse_line(struct cfg *cfg, const char *filename, char **buf,
diff --git a/main.c b/main.c
index 148b2d2..9915cf2 100644
--- a/main.c
+++ b/main.c
@@ -57,25 +57,118 @@ cfg_free(struct uring_task *task)
debug(DBG_SIG, "called\n");
systemd_delete(cfg);
+ xfree(cfg->igmp_iface);
+ cfg->igmp_iface = NULL;
+ xfree(cfg->cfg_path);
+ cfg->cfg_path = NULL;
exiting = true;
/* The cfg struct is free:d in main() */
}
+#define DEFAULT_MAIN_CONFIG_FILE_PATH "./mcproxy.conf"
+
+enum mcfg_keys {
+ MCFG_KEY_INVALID = 0,
+ MCFG_KEY_IGMP,
+ MCFG_KEY_IGMP_IFACE
+};
+
+struct cfg_key_value_map mcfg_key_map[] = {
+ {
+ .key_name = "igmp",
+ .key_value = MCFG_KEY_IGMP,
+ .value_type = CFG_VAL_TYPE_BOOL,
+ }, {
+ .key_name = "igmp_iface",
+ .key_value = MCFG_KEY_IGMP_IFACE,
+ .value_type = CFG_VAL_TYPE_STRING,
+ }, {
+ .key_name = NULL,
+ .key_value = MCFG_KEY_INVALID,
+ .value_type = CFG_VAL_TYPE_INVALID,
+ }
+};
+
static void
cfg_read(struct cfg *cfg)
{
FILE *cfgfile;
-
- cfgfile = fopen("./mcproxy.conf", "re");
+ const char *path;
+ char buf[4096];
+ char *pos = buf;
+ size_t rd = 0;
+ size_t r;
+
+ if (cfg->cfg_path)
+ path = cfg->cfg_path;
+ else
+ path = DEFAULT_MAIN_CONFIG_FILE_PATH;
+
+ cfgfile = fopen(path, "re");
if (!cfgfile) {
- if (errno == ENOENT)
+ /* ENOENT is only an error with an explicitly set path */
+ if (errno == ENOENT && !cfg->cfg_path)
return;
+ else if (errno == ENOENT)
+ die("main config file (%s) missing\n", path);
else
perrordie("fopen");
}
- debug(DBG_CFG, "opened config file\n");
+ debug(DBG_CFG, "opened main config file (%s)\n", path);
+
+ while (rd < sizeof(buf)) {
+ r = fread(pos, 1, sizeof(buf) - rd - 1, cfgfile);
+ if (r == 0)
+ break;
+ rd += r;
+ pos += r;
+ }
+
+ if (rd == 0)
+ die("main config file (%s) invalid\n", path);
+
+ if (rd >= sizeof(buf))
+ die("main config file (%s) too large\n", path);
+
fclose(cfgfile);
+ *pos = '\0';
+ pos = buf;
+
+ if (!config_parse_header(cfg, path, "mcproxy", &pos))
+ die("main config file (%s) invalid\n", path);
+
+ while (true) {
+ int key;
+ const char *keyname;
+ union cfg_value value;
+
+ if (!config_parse_line(cfg, path, &pos, mcfg_key_map,
+ &key, &keyname, &value))
+ break;
+
+ if (key == MCFG_KEY_INVALID)
+ die("main config file (%s) invalid\n", path);
+
+ debug(DBG_CFG, "main cfg: key %s\n", keyname);
+
+ switch (key) {
+
+ case MCFG_KEY_IGMP:
+ cfg->do_igmp = value.boolean;
+ break;
+
+ case MCFG_KEY_IGMP_IFACE:
+ cfg->igmp_iface = xstrdup(value.str);
+ if (!cfg->igmp_iface)
+ perrordie("xstrdup");
+ break;
+
+ case MCFG_KEY_INVALID:
+ default:
+ die("main config file (%s) invalid\n", path);
+ }
+ }
}
const struct {
diff --git a/main.h b/main.h
index dd93474..0074bd9 100644
--- a/main.h
+++ b/main.h
@@ -89,6 +89,10 @@ struct uring_task {
struct cfg {
const char *homedir;
+ char *cfg_path;
+ bool do_igmp;
+ char *igmp_iface;
+
struct uring_ev *uev;
struct inotify_ev *iev;
struct signalfd_ev *sev;