+ logger(DEBUG_ALWAYS, LOG_ERR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+
+ return false;
+}
+
+bool get_config_int(const config_t *cfg, int *result) {
+ if(!cfg)
+ return false;
+
+ if(sscanf(cfg->value, "%d", result) == 1)
+ return true;
+
+ logger(DEBUG_ALWAYS, LOG_ERR, "Integer expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+
+ return false;
+}
+
+bool get_config_string(const config_t *cfg, char **result) {
+ if(!cfg)
+ return false;
+
+ *result = xstrdup(cfg->value);
+
+ return true;
+}
+
+bool get_config_address(const config_t *cfg, struct addrinfo **result) {
+ struct addrinfo *ai;
+
+ if(!cfg)
+ return false;
+
+ ai = str2addrinfo(cfg->value, NULL, 0);
+
+ if(ai) {
+ *result = ai;
+ return true;
+ }
+
+ logger(DEBUG_ALWAYS, LOG_ERR, "Hostname or IP address expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+
+ return false;
+}
+
+bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
+ subnet_t subnet = {NULL};
+
+ if(!cfg)
+ return false;
+
+ if(!str2net(&subnet, cfg->value)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Subnet expected for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+ return false;
+ }
+
+ /* Teach newbies what subnets are... */
+
+ if(((subnet.type == SUBNET_IPV4)
+ && !maskcheck(&subnet.net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof subnet.net.ipv4.address))
+ || ((subnet.type == SUBNET_IPV6)
+ && !maskcheck(&subnet.net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof subnet.net.ipv6.address))) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Network address and prefix length do not match for configuration variable %s in %s line %d",
+ cfg->variable, cfg->file, cfg->line);
+ return false;