diff options
-rw-r--r-- | config.c | 11 | ||||
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | main.c | 101 | ||||
-rw-r--r-- | main.h | 4 |
4 files changed, 114 insertions, 4 deletions
@@ -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: @@ -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, @@ -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 { @@ -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; |