aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/util/config_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/util/config_file.c')
-rw-r--r--external/unbound/util/config_file.c420
1 files changed, 399 insertions, 21 deletions
diff --git a/external/unbound/util/config_file.c b/external/unbound/util/config_file.c
index cc7d99086..af176929d 100644
--- a/external/unbound/util/config_file.c
+++ b/external/unbound/util/config_file.c
@@ -62,6 +62,9 @@
#ifdef HAVE_GLOB_H
# include <glob.h>
#endif
+#ifdef CLIENT_SUBNET
+#include "edns-subnet/edns-subnet.h"
+#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
@@ -98,13 +101,17 @@ config_create(void)
cfg->do_udp = 1;
cfg->do_tcp = 1;
cfg->tcp_upstream = 0;
+ cfg->tcp_mss = 0;
+ cfg->outgoing_tcp_mss = 0;
cfg->ssl_service_key = NULL;
cfg->ssl_service_pem = NULL;
cfg->ssl_port = 853;
cfg->ssl_upstream = 0;
cfg->use_syslog = 1;
+ cfg->log_identity = NULL; /* changed later with argv[0] */
cfg->log_time_ascii = 0;
cfg->log_queries = 0;
+ cfg->log_replies = 0;
#ifndef USE_WINSOCK
# ifdef USE_MINI_EVENT
/* select max 1024 sockets */
@@ -155,18 +162,28 @@ config_create(void)
cfg->donotqueryaddrs = NULL;
cfg->donotquery_localhost = 1;
cfg->root_hints = NULL;
+ cfg->use_systemd = 0;
cfg->do_daemonize = 1;
cfg->if_automatic = 0;
cfg->so_rcvbuf = 0;
cfg->so_sndbuf = 0;
cfg->so_reuseport = 0;
cfg->ip_transparent = 0;
+ cfg->ip_freebind = 0;
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->num_out_ifs = 0;
cfg->out_ifs = NULL;
cfg->stubs = NULL;
cfg->forwards = NULL;
+#ifdef CLIENT_SUBNET
+ cfg->client_subnet = NULL;
+ cfg->client_subnet_opcode = LDNS_EDNS_CLIENT_SUBNET;
+ cfg->client_subnet_always_forward = 0;
+ cfg->max_client_subnet_ipv4 = 24;
+ cfg->max_client_subnet_ipv6 = 56;
+#endif
+ cfg->views = NULL;
cfg->acls = NULL;
cfg->harden_short_bufsize = 0;
cfg->harden_large_queries = 0;
@@ -182,6 +199,7 @@ config_create(void)
cfg->unwanted_threshold = 0;
cfg->hide_identity = 0;
cfg->hide_version = 0;
+ cfg->hide_trustanchor = 0;
cfg->identity = NULL;
cfg->version = NULL;
cfg->auto_trust_anchor_file_list = NULL;
@@ -199,6 +217,7 @@ config_create(void)
cfg->val_log_squelch = 0;
cfg->val_permissive_mode = 0;
cfg->ignore_cd = 0;
+ cfg->serve_expired = 0;
cfg->add_holddown = 30*24*3600;
cfg->del_holddown = 30*24*3600;
cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */
@@ -209,7 +228,9 @@ config_create(void)
cfg->local_zones = NULL;
cfg->local_zones_nodefault = NULL;
cfg->local_data = NULL;
+ cfg->local_zone_overrides = NULL;
cfg->unblock_lan_zones = 0;
+ cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
cfg->remote_control_enable = 0;
cfg->control_ifs = NULL;
@@ -227,20 +248,37 @@ config_create(void)
if(!(cfg->control_cert_file = strdup(RUN_DIR"/unbound_control.pem")))
goto error_exit;
+#ifdef CLIENT_SUBNET
+ if(!(cfg->module_conf = strdup("subnetcache validator iterator"))) goto error_exit;
+#else
if(!(cfg->module_conf = strdup("validator iterator"))) goto error_exit;
+#endif
if(!(cfg->val_nsec3_key_iterations =
strdup("1024 150 2048 500 4096 2500"))) goto error_exit;
#if defined(DNSTAP_SOCKET_PATH)
if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH)))
goto error_exit;
#endif
+ cfg->disable_dnssec_lame_check = 0;
+ cfg->ip_ratelimit = 0;
cfg->ratelimit = 0;
+ cfg->ip_ratelimit_slabs = 4;
cfg->ratelimit_slabs = 4;
+ cfg->ip_ratelimit_size = 4*1024*1024;
cfg->ratelimit_size = 4*1024*1024;
cfg->ratelimit_for_domain = NULL;
cfg->ratelimit_below_domain = NULL;
+ cfg->ip_ratelimit_factor = 10;
cfg->ratelimit_factor = 10;
cfg->qname_minimisation = 0;
+ cfg->qname_minimisation_strict = 0;
+ cfg->shm_enable = 0;
+ cfg->shm_key = 11777;
+ cfg->dnscrypt = 0;
+ cfg->dnscrypt_port = 0;
+ cfg->dnscrypt_provider = NULL;
+ cfg->dnscrypt_provider_cert = NULL;
+ cfg->dnscrypt_secret_key = NULL;
return cfg;
error_exit:
config_delete(cfg);
@@ -361,18 +399,24 @@ int config_set_option(struct config_file* cfg, const char* opt,
log_set_time_asc(cfg->log_time_ascii); }
else S_SIZET_NONZERO("max-udp-size:", max_udp_size)
else S_YNO("use-syslog:", use_syslog)
+ else S_STR("log-identity:", log_identity)
else S_YNO("extended-statistics:", stat_extended)
else S_YNO("statistics-cumulative:", stat_cumulative)
+ else S_YNO("shm-enable:", shm_enable)
+ else S_NUMBER_OR_ZERO("shm-key:", shm_key)
else S_YNO("do-ip4:", do_ip4)
else S_YNO("do-ip6:", do_ip6)
else S_YNO("do-udp:", do_udp)
else S_YNO("do-tcp:", do_tcp)
else S_YNO("tcp-upstream:", tcp_upstream)
+ else S_NUMBER_NONZERO("tcp-mss:", tcp_mss)
+ else S_NUMBER_NONZERO("outgoing-tcp-mss:", outgoing_tcp_mss)
else S_YNO("ssl-upstream:", ssl_upstream)
else S_STR("ssl-service-key:", ssl_service_key)
else S_STR("ssl-service-pem:", ssl_service_pem)
else S_NUMBER_NONZERO("ssl-port:", ssl_port)
else S_YNO("interface-automatic:", if_automatic)
+ else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
else S_NUMBER_NONZERO("port:", port)
else S_NUMBER_NONZERO("outgoing-range:", outgoing_num_ports)
@@ -388,6 +432,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_MEMSIZE("so-sndbuf:", so_sndbuf)
else S_YNO("so-reuseport:", so_reuseport)
else S_YNO("ip-transparent:", ip_transparent)
+ else S_YNO("ip-freebind:", ip_freebind)
else S_MEMSIZE("rrset-cache-size:", rrset_cache_size)
else S_POW2("rrset-cache-slabs:", rrset_cache_slabs)
else S_YNO("prefetch:", prefetch)
@@ -412,6 +457,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("pidfile:", pidfile)
else S_YNO("hide-identity:", hide_identity)
else S_YNO("hide-version:", hide_version)
+ else S_YNO("hide-trustanchor:", hide_trustanchor)
else S_STR("identity:", identity)
else S_STR("version:", version)
else S_STRLIST("root-hints:", root_hints)
@@ -442,8 +488,10 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_NUMBER_OR_ZERO("val-log-level:", val_log_level)
else S_YNO("val-log-squelch:", val_log_squelch)
else S_YNO("log-queries:", log_queries)
+ else S_YNO("log-replies:", log_replies)
else S_YNO("val-permissive-mode:", val_permissive_mode)
else S_YNO("ignore-cd-flag:", ignore_cd)
+ else S_YNO("serve-expired:", serve_expired)
else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
else S_UNSIGNED_OR_ZERO("add-holddown:", add_holddown)
else S_UNSIGNED_OR_ZERO("del-holddown:", del_holddown)
@@ -458,6 +506,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
else S_STRLIST("local-data:", local_data)
else S_YNO("unblock-lan-zones:", unblock_lan_zones)
+ else S_YNO("insecure-lan-zones:", insecure_lan_zones)
else S_YNO("control-enable:", remote_control_enable)
else S_STRLIST("control-interface:", control_ifs)
else S_NUMBER_NONZERO("control-port:", control_port)
@@ -467,17 +516,34 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("control-cert-file:", control_cert_file)
else S_STR("module-config:", module_conf)
else S_STR("python-script:", python_script)
+ else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
+#ifdef CLIENT_SUBNET
+ /* Can't set max subnet prefix here, since that value is used when
+ * generating the address tree. */
+ /* No client-subnet-always-forward here, module registration depends on
+ * this option. */
+#endif
+ else if(strcmp(opt, "ip-ratelimit:") == 0) {
+ IS_NUMBER_OR_ZERO; cfg->ip_ratelimit = atoi(val);
+ infra_ip_ratelimit=cfg->ip_ratelimit;
+ }
else if(strcmp(opt, "ratelimit:") == 0) {
IS_NUMBER_OR_ZERO; cfg->ratelimit = atoi(val);
infra_dp_ratelimit=cfg->ratelimit;
}
+ else S_MEMSIZE("ip-ratelimit-size:", ip_ratelimit_size)
else S_MEMSIZE("ratelimit-size:", ratelimit_size)
+ else S_POW2("ip-ratelimit-slabs:", ip_ratelimit_slabs)
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
+ else S_NUMBER_OR_ZERO("ip-ratelimit-factor:", ip_ratelimit_factor)
else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
else S_YNO("qname-minimisation:", qname_minimisation)
+ else S_YNO("qname-minimisation-strict:", qname_minimisation_strict)
+ else if(strcmp(opt, "define-tag:") ==0) {
+ return config_add_tag(cfg, val);
/* val_sig_skew_min and max are copied into val_env during init,
* so this does not update val_env with set_option */
- else if(strcmp(opt, "val-sig-skew-min:") == 0)
+ } else if(strcmp(opt, "val-sig-skew-min:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_min = (int32_t)atoi(val); }
else if(strcmp(opt, "val-sig-skew-max:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_max = (int32_t)atoi(val); }
@@ -496,9 +562,13 @@ int config_set_option(struct config_file* cfg, const char* opt,
/* unknown or unsupported (from the set_option interface):
* interface, outgoing-interface, access-control,
* stub-zone, name, stub-addr, stub-host, stub-prime
- * forward-first, stub-first,
- * forward-zone, name, forward-addr, forward-host,
- * ratelimit-for-domain, ratelimit-below-domain */
+ * forward-first, stub-first, forward-ssl-upstream,
+ * stub-ssl-upstream, forward-zone,
+ * name, forward-addr, forward-host,
+ * ratelimit-for-domain, ratelimit-below-domain,
+ * local-zone-tag, access-control-view
+ * send-client-subnet client-subnet-always-forward
+ * max-client-subnet-ipv4 max-client-subnet-ipv6 */
return 0;
}
return 1;
@@ -622,9 +692,31 @@ config_collate_cat(struct config_strlist* list)
/** compare and print list option */
#define O_LS2(opt, name, lst) if(strcmp(opt, name)==0) { \
struct config_str2list* p = cfg->lst; \
- for(p = cfg->lst; p; p = p->next) \
- snprintf(buf, len, "%s %s\n", p->str, p->str2); \
+ for(p = cfg->lst; p; p = p->next) { \
+ snprintf(buf, len, "%s %s", p->str, p->str2); \
+ func(buf, arg); \
+ } \
+ }
+/** compare and print list option */
+#define O_LS3(opt, name, lst) if(strcmp(opt, name)==0) { \
+ struct config_str3list* p = cfg->lst; \
+ for(p = cfg->lst; p; p = p->next) { \
+ snprintf(buf, len, "%s %s %s", p->str, p->str2, p->str3); \
func(buf, arg); \
+ } \
+ }
+/** compare and print taglist option */
+#define O_LTG(opt, name, lst) if(strcmp(opt, name)==0) { \
+ char* tmpstr = NULL; \
+ struct config_strbytelist *p = cfg->lst; \
+ for(p = cfg->lst; p; p = p->next) {\
+ tmpstr = config_taglist2str(cfg, p->str2, p->str2len); \
+ if(tmpstr) {\
+ snprintf(buf, len, "%s %s", p->str, tmpstr); \
+ func(buf, arg); \
+ free(tmpstr); \
+ } \
+ } \
}
int
@@ -638,7 +730,10 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "statistics-interval", stat_interval)
else O_YNO(opt, "statistics-cumulative", stat_cumulative)
else O_YNO(opt, "extended-statistics", stat_extended)
+ else O_YNO(opt, "shm-enable", shm_enable)
+ else O_DEC(opt, "shm-key", shm_key)
else O_YNO(opt, "use-syslog", use_syslog)
+ else O_STR(opt, "log-identity", log_identity)
else O_YNO(opt, "log-time-ascii", log_time_ascii)
else O_DEC(opt, "num-threads", num_threads)
else O_IFC(opt, "interface", num_ifs, ifs)
@@ -658,6 +753,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_MEM(opt, "so-sndbuf", so_sndbuf)
else O_YNO(opt, "so-reuseport", so_reuseport)
else O_YNO(opt, "ip-transparent", ip_transparent)
+ else O_YNO(opt, "ip-freebind", ip_freebind)
else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
else O_YNO(opt, "prefetch-key", prefetch_key)
@@ -675,19 +771,24 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "do-udp", do_udp)
else O_YNO(opt, "do-tcp", do_tcp)
else O_YNO(opt, "tcp-upstream", tcp_upstream)
+ else O_DEC(opt, "tcp-mss", tcp_mss)
+ else O_DEC(opt, "outgoing-tcp-mss", outgoing_tcp_mss)
else O_YNO(opt, "ssl-upstream", ssl_upstream)
else O_STR(opt, "ssl-service-key", ssl_service_key)
else O_STR(opt, "ssl-service-pem", ssl_service_pem)
else O_DEC(opt, "ssl-port", ssl_port)
+ else O_YNO(opt, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)
else O_STR(opt, "username", username)
else O_STR(opt, "directory", directory)
else O_STR(opt, "logfile", logfile)
else O_YNO(opt, "log-queries", log_queries)
+ else O_YNO(opt, "log-replies", log_replies)
else O_STR(opt, "pidfile", pidfile)
else O_YNO(opt, "hide-identity", hide_identity)
else O_YNO(opt, "hide-version", hide_version)
+ else O_YNO(opt, "hide-trustanchor", hide_trustanchor)
else O_STR(opt, "identity", identity)
else O_STR(opt, "version", version)
else O_STR(opt, "target-fetch-policy", target_fetch_policy)
@@ -709,6 +810,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "val-log-level", val_log_level)
else O_YNO(opt, "val-permissive-mode", val_permissive_mode)
else O_YNO(opt, "ignore-cd-flag", ignore_cd)
+ else O_YNO(opt, "serve-expired", serve_expired)
else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
else O_UNS(opt, "add-holddown", add_holddown)
else O_UNS(opt, "del-holddown", del_holddown)
@@ -738,18 +840,40 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_UNS(opt, "val-override-date", val_date_override)
else O_YNO(opt, "minimal-responses", minimal_responses)
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
+#ifdef CLIENT_SUBNET
+ else O_LST(opt, "send-client-subnet", client_subnet)
+ else O_DEC(opt, "max-client-subnet-ipv4", max_client_subnet_ipv4)
+ else O_DEC(opt, "max-client-subnet-ipv6", max_client_subnet_ipv6)
+ else O_YNO(opt, "client-subnet-always-forward:",
+ client_subnet_always_forward)
+#endif
else O_YNO(opt, "unblock-lan-zones", unblock_lan_zones)
+ else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_STR(opt, "python-script", python_script)
+ else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
+ else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
else O_DEC(opt, "ratelimit", ratelimit)
+ else O_MEM(opt, "ip-ratelimit-size", ip_ratelimit_size)
else O_MEM(opt, "ratelimit-size", ratelimit_size)
+ else O_DEC(opt, "ip-ratelimit-slabs", ip_ratelimit_slabs)
else O_DEC(opt, "ratelimit-slabs", ratelimit_slabs)
else O_LS2(opt, "ratelimit-for-domain", ratelimit_for_domain)
else O_LS2(opt, "ratelimit-below-domain", ratelimit_below_domain)
+ else O_DEC(opt, "ip-ratelimit-factor", ip_ratelimit_factor)
else O_DEC(opt, "ratelimit-factor", ratelimit_factor)
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
else O_YNO(opt, "qname-minimisation", qname_minimisation)
+ else O_YNO(opt, "qname-minimisation-strict", qname_minimisation_strict)
+ else O_IFC(opt, "define-tag", num_tags, tagname)
+ else O_LTG(opt, "local-zone-tag", local_zone_tags)
+ else O_LTG(opt, "access-control-tag", acl_tags)
+ else O_LTG(opt, "response-ip-tag", respip_tags)
+ else O_LS3(opt, "local-zone-override", local_zone_overrides)
+ else O_LS3(opt, "access-control-tag-action", acl_tag_actions)
+ else O_LS3(opt, "access-control-tag-data", acl_tag_datas)
+ else O_LS2(opt, "access-control-view", acl_view)
/* not here:
* outgoing-permit, outgoing-avoid - have list of ports
* local-zone - zones and nodefault variables
@@ -854,6 +978,8 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot)
ub_c_parse();
fclose(in);
+ if(!cfg->dnscrypt) cfg->dnscrypt_port = 0;
+
if(cfg_parser->errors != 0) {
fprintf(stderr, "read %s failed: %d errors in configuration file\n",
fname, cfg_parser->errors);
@@ -864,6 +990,18 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot)
return 1;
}
+struct config_stub* cfg_stub_find(struct config_stub*** pp, const char* nm)
+{
+ struct config_stub* p = *(*pp);
+ while(p) {
+ if(strcmp(p->name, nm) == 0)
+ return p;
+ (*pp) = &p->next;
+ p = p->next;
+ }
+ return NULL;
+}
+
void
config_delstrlist(struct config_strlist* p)
{
@@ -890,14 +1028,82 @@ config_deldblstrlist(struct config_str2list* p)
}
void
+config_deltrplstrlist(struct config_str3list* p)
+{
+ struct config_str3list *np;
+ while(p) {
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+}
+
+void
+config_delstub(struct config_stub* p)
+{
+ if(!p) return;
+ free(p->name);
+ config_delstrlist(p->hosts);
+ config_delstrlist(p->addrs);
+ free(p);
+}
+
+void
config_delstubs(struct config_stub* p)
{
struct config_stub* np;
while(p) {
np = p->next;
- free(p->name);
- config_delstrlist(p->hosts);
- config_delstrlist(p->addrs);
+ config_delstub(p);
+ p = np;
+ }
+}
+
+void
+config_delview(struct config_view* p)
+{
+ if(!p) return;
+ free(p->name);
+ config_deldblstrlist(p->local_zones);
+ config_delstrlist(p->local_zones_nodefault);
+ config_delstrlist(p->local_data);
+ free(p);
+}
+
+void
+config_delviews(struct config_view* p)
+{
+ struct config_view* np;
+ while(p) {
+ np = p->next;
+ config_delview(p);
+ p = np;
+ }
+}
+/** delete string array */
+static void
+config_del_strarray(char** array, int num)
+{
+ int i;
+ if(!array)
+ return;
+ for(i=0; i<num; i++) {
+ free(array[i]);
+ }
+ free(array);
+}
+
+void
+config_del_strbytelist(struct config_strbytelist* p)
+{
+ struct config_strbytelist* np;
+ while(p) {
+ np = p->next;
+ free(p->str);
+ free(p->str2);
free(p);
p = np;
}
@@ -915,22 +1121,17 @@ config_delete(struct config_file* cfg)
free(cfg->target_fetch_policy);
free(cfg->ssl_service_key);
free(cfg->ssl_service_pem);
- if(cfg->ifs) {
- int i;
- for(i=0; i<cfg->num_ifs; i++)
- free(cfg->ifs[i]);
- free(cfg->ifs);
- }
- if(cfg->out_ifs) {
- int i;
- for(i=0; i<cfg->num_out_ifs; i++)
- free(cfg->out_ifs[i]);
- free(cfg->out_ifs);
- }
+ free(cfg->log_identity);
+ config_del_strarray(cfg->ifs, cfg->num_ifs);
+ config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards);
+ config_delviews(cfg->views);
config_delstrlist(cfg->donotqueryaddrs);
config_delstrlist(cfg->root_hints);
+#ifdef CLIENT_SUBNET
+ config_delstrlist(cfg->client_subnet);
+#endif
free(cfg->identity);
free(cfg->version);
free(cfg->module_conf);
@@ -950,6 +1151,13 @@ config_delete(struct config_file* cfg)
config_deldblstrlist(cfg->local_zones);
config_delstrlist(cfg->local_zones_nodefault);
config_delstrlist(cfg->local_data);
+ config_deltrplstrlist(cfg->local_zone_overrides);
+ config_del_strarray(cfg->tagname, cfg->num_tags);
+ config_del_strbytelist(cfg->local_zone_tags);
+ config_del_strbytelist(cfg->acl_tags);
+ config_del_strbytelist(cfg->respip_tags);
+ config_deltrplstrlist(cfg->acl_tag_actions);
+ config_deltrplstrlist(cfg->acl_tag_datas);
config_delstrlist(cfg->control_ifs);
free(cfg->server_key_file);
free(cfg->server_cert_file);
@@ -1108,6 +1316,23 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item)
}
int
+cfg_region_strlist_insert(struct regional* region,
+ struct config_strlist** head, char* item)
+{
+ struct config_strlist *s;
+ if(!item || !head)
+ return 0;
+ s = (struct config_strlist*)regional_alloc_zero(region,
+ sizeof(struct config_strlist));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->next = *head;
+ *head = s;
+ return 1;
+}
+
+int
cfg_strlist_insert(struct config_strlist** head, char* item)
{
struct config_strlist *s;
@@ -1138,6 +1363,42 @@ cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
return 1;
}
+int
+cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
+ char* i3)
+{
+ struct config_str3list *s;
+ if(!item || !i2 || !i3 || !head)
+ return 0;
+ s = (struct config_str3list*)calloc(1, sizeof(struct config_str3list));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->str2 = i2;
+ s->str3 = i3;
+ s->next = *head;
+ *head = s;
+ return 1;
+}
+
+int
+cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
+ uint8_t* i2, size_t i2len)
+{
+ struct config_strbytelist* s;
+ if(!item || !i2 || !head)
+ return 0;
+ s = (struct config_strbytelist*)calloc(1, sizeof(*s));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->str2 = i2;
+ s->str2len = i2len;
+ s->next = *head;
+ *head = s;
+ return 1;
+}
+
time_t
cfg_convert_timeval(const char* str)
{
@@ -1242,6 +1503,123 @@ cfg_parse_memsize(const char* str, size_t* res)
return 1;
}
+int
+find_tag_id(struct config_file* cfg, const char* tag)
+{
+ int i;
+ for(i=0; i<cfg->num_tags; i++) {
+ if(strcmp(cfg->tagname[i], tag) == 0)
+ return i;
+ }
+ return -1;
+}
+
+int
+config_add_tag(struct config_file* cfg, const char* tag)
+{
+ char** newarray;
+ char* newtag;
+ if(find_tag_id(cfg, tag) != -1)
+ return 1; /* nothing to do */
+ newarray = (char**)malloc(sizeof(char*)*(cfg->num_tags+1));
+ if(!newarray)
+ return 0;
+ newtag = strdup(tag);
+ if(!newtag) {
+ free(newarray);
+ return 0;
+ }
+ if(cfg->tagname) {
+ memcpy(newarray, cfg->tagname, sizeof(char*)*cfg->num_tags);
+ free(cfg->tagname);
+ }
+ newarray[cfg->num_tags++] = newtag;
+ cfg->tagname = newarray;
+ return 1;
+}
+
+/** set a bit in a bit array */
+static void
+cfg_set_bit(uint8_t* bitlist, size_t len, int id)
+{
+ int pos = id/8;
+ log_assert((size_t)pos < len);
+ (void)len;
+ bitlist[pos] |= 1<<(id%8);
+}
+
+uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
+ size_t* listlen)
+{
+ uint8_t* taglist = NULL;
+ size_t len = 0;
+ char* p, *s;
+
+ /* allocate */
+ if(cfg->num_tags == 0) {
+ log_err("parse taglist, but no tags defined");
+ return 0;
+ }
+ len = (size_t)(cfg->num_tags+7)/8;
+ taglist = calloc(1, len);
+ if(!taglist) {
+ log_err("out of memory");
+ return 0;
+ }
+
+ /* parse */
+ s = str;
+ while((p=strsep(&s, " \t\n")) != NULL) {
+ if(*p) {
+ int id = find_tag_id(cfg, p);
+ /* set this bit in the bitlist */
+ if(id == -1) {
+ log_err("unknown tag: %s", p);
+ free(taglist);
+ return 0;
+ }
+ cfg_set_bit(taglist, len, id);
+ }
+ }
+
+ *listlen = len;
+ return taglist;
+}
+
+char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
+ size_t taglen)
+{
+ char buf[10240];
+ size_t i, j, len = 0;
+ buf[0] = 0;
+ for(i=0; i<taglen; i++) {
+ if(taglist[i] == 0)
+ continue;
+ for(j=0; j<8; j++) {
+ if((taglist[i] & (1<<j)) != 0) {
+ size_t id = i*8 + j;
+ snprintf(buf+len, sizeof(buf)-len, "%s%s",
+ (len==0?"":" "), cfg->tagname[id]);
+ len += strlen(buf+len);
+ }
+ }
+ }
+ return strdup(buf);
+}
+
+int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
+ size_t list2len)
+{
+ size_t i;
+ if(!list1 || !list2)
+ return 0;
+ for(i=0; i<list1len && i<list2len; i++) {
+ if((list1[i] & list2[i]) != 0)
+ return 1;
+ }
+ return 0;
+}
+
void
config_apply(struct config_file* config)
{