summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2023-08-08 01:58:25 +0200
committerAnton Luka Šijanec <anton@sijanec.eu>2023-08-08 01:58:25 +0200
commit9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a (patch)
tree1251c02b8a9d3be7761fbe9a86c014689bbdb52d
parent6 (diff)
downloadr-9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a.tar
r-9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a.tar.gz
r-9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a.tar.bz2
r-9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a.tar.lz
r-9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a.tar.xz
r-9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a.tar.zst
r-9b81bdf6b0404d5813bfb1ca7965fefdc0ea519a.zip
-rw-r--r--prog/6/6d.conf53
-rw-r--r--prog/6/conf.c265
-rw-r--r--prog/6/daemon.c9
3 files changed, 165 insertions, 162 deletions
diff --git a/prog/6/6d.conf b/prog/6/6d.conf
index 3ecc3ff..c6d8756 100644
--- a/prog/6/6d.conf
+++ b/prog/6/6d.conf
@@ -8,22 +8,15 @@
# Reloading the server also schedules a synchronization from masters (if any).
# Masters and slaves must have accurate clocks (at least minute accuracy is expected)
# To specify IPv4 addresses, use the V4MAPPED address format (::ffff:192.0.2.69).
-# Zone transfers are made using a 6d-specific TCP+UDP-based protocol, so if you run 6d being a DNS proxy, such as bind9 zone forward, you must specify the host/port combination where 6d listens, not where bind9 listens. When unsigned, this 6d-specific protocol relies on trusted routing to master servers and no MiTM attacks on the line.
-# DNSSEC and signed zone transfers are available upon request (mailto:anton@šijanec.eu).
+# Config transfers are made using a 6d-specific TCP-based protocol, so if you run 6d being a DNS proxy, such as bind9 zone forward, you must specify the host/port combination where 6d listens, not where bind9 listens. When unencrypted, this 6d-specific protocol relies on trusted routing to master servers and no MiTM attacks on the line.
+# DNSSEC and encrypted zone transfers are available upon request (mailto:anton@šijanec.eu).
#################### SLAVE CONFIGURATION ###################### (You may delete this part on master-only 6d.)
# You can optionally define master servers here, all of their configuration will be periodically retrieved and mirrored to this 6d instance. A host may optionally be followed by /TCPport.
-master_servers = {6master.sijanec.eu, 6d2.example, 2001:db8::1/5353}
+masters = {6master.sijanec.eu, 6d2.example, 2001:db8::1/5353}
-# OBSOLETE NON-FEATURE (NOT WORKING)
-# You can optionally define master networks/zones here, they will be also be mirrored from their master server. The master server will be obtained from their SOA record.
-# Note that 6d is not a general purpose DNS server! Any FQDNs specified here will be treated as 6d suffix generators.
-# Note that if this is used, master must not be behind a DNS proxy, such as bind9 zone forward. Use master_servers instead if that's the case.
-# master_zones = {2001:db8:a::/48, 2001:db8:b::/48, 2001:db8:c::/48, 6ptr.sijanec.eu}
-
-# Master servers will be checked for changes every poll_interval number of seconds. Set to 0 to disable polling.
-# 69 is the default.
+# Master servers will be checked for changes every poll_interval number of seconds. 69 is the default.
poll_interval = 69
# Slaves hold everything they know in memory.
@@ -36,37 +29,32 @@ poll_interval = 69
# /var/cache/6/backup is the default file.
ptr_file = /var/cache/6/backup
-# Instead of polling, slaves can be notified on changes. This is done over a DNS-compatible UDP protocol so slaves can run behind bind9 forward zone-like DNS proxies.
-slaves = {6slave.sijanec.eu/666, ::ffff:192.0.2.69, 2001:db8::2/5353}
-
-# Defines networks to generate PTR records on the fly. The only required option is master.
+# Defines networks to generate PTR records on the fly.
network
{
# List of networks this block defines.
networks = {2001:db8:d::/48, 2001:db8:e::/48}
- # List the following slaves in NS responses.
- slaves = {6slave.sijanec.eu, 6slave.example}
+ # List the following servers in NS responses. The first server will be put into SOA responses.
+ ns = {6d.example, 6slave.sijanec.eu, 6slave.example}
# This will be published in the SOA record.
admin = 6@sijanec.eu
- # This will be published as the authoritative server in the SOA record (point it to this 6d instance).
- master = 6d.example
# PTRs will be generated in form 2001-db8-d--5932.suffix for address 2001:db8:d::5932.
# By default, this suffix is the [...].ip6.arpa domain, so for network 2001:db8::/32, the suffix will be 8.B.D.0.1.0.0.2.IP6.ARPA, and the above mentioned PTR would be 2001-db8-d--5932.8.b.d.0.1.0.0.2.ip6.adpa, which is totaly OK standard-wise. Do not specify [...].ip6.arpa addresses as suffixes yourself, they will be managed automatically.
# The suffix must respond to queries with the correct AAAA records, 6d can serve it for you (see below).
### suffix = "6ptr.sijanec.eu"
# TTL for generated records and negative caching.
- ttl = 420
+ ttl = 513
}
# Another networks definition.
network
{
networks = {2001:db8:f:100::/56, 2001:db8:f:200::/56, 2001:db8:900::/48}
- master = ptrdns1.example
+ ns = {ptrdns1.example}
suffix = suffixgenerator.net.example
}
-
-# Define suffixes that will generate AAAA records on the fly. The only required option is master.
+/*
+# Define suffixes that will generate AAAA records on the fly.
suffix
{
# List of suffixes
@@ -75,11 +63,10 @@ suffix
# By specifying ::/0 here you allow any network on the internet to use your suffix for PTRs.
# ::/0 is the default.
accept = {::/0}
- slaves = {6slave.sijanec.org, 6slave.example}
+ ns = {6ptr.sijanec.eu, 6slave.sijanec.org, 6slave.example}
admin = 6@sijanec.eu
- master = 6ptr.sijanec.eu
# TTL for generated records and negative caching.
- ttl = 420
+ ttl = 513
}
# Another suffixes definition, this time networks are specified, other IPv6 addresses will be NXDOMAIN.
@@ -87,7 +74,15 @@ suffix
{
suffixes = {private-ipv6.net.example, private-ipv6.org.example}
accept = {2001:db8:f:100::/56, 2001:db8:f:200::/56, 2001:db8:900::/48}
- master = locked-ns1.net.example
+ ns = {locked-ns1.net.example}
+}
+*/
+# Another one with large accept clauses.
+suffix
+{
+ suffixes = {almost-public.example}
+ accept = {8000::/1, 4000::/2, ::/2}
+ ns = {weird-ns1.net.example}
}
############################# STATIC NS AND PTR RECORDS ###############################
@@ -96,7 +91,7 @@ suffix
ptr 2001:db8:d::1
{
hostname = mail.example
- ttl = 420
+ ttl = 513
}
# Another PTR definition
@@ -110,7 +105,7 @@ ns
{
networks = {2001:db8:d:1337::/64, 2001:db8:d:1338::/64}
ns = {ns1.sijanec.org, ns2.sijanec.org}
- ttl = 420
+ ttl = 513
}
# Another NS delegation.
diff --git a/prog/6/conf.c b/prog/6/conf.c
index b8ce0be..d22c7c0 100644
--- a/prog/6/conf.c
+++ b/prog/6/conf.c
@@ -1,6 +1,10 @@
+#include <search.h>
#include <stdbool.h>
#include <confuse.h>
#include <arpa/inet.h>
+int compar_pcp (const void * a, const void * b) {
+ return strcmp(*((const char **) a), *((const char **) b));
+}
enum type {
nothing,
network,
@@ -14,14 +18,20 @@ struct trie {
void * data;
};
struct trie * next (struct trie * trie) { // for depth-first walking the trie, pass in the root trie first
- if (trie->dir[0])
+ if (trie->dir[0]) {
+ trie->dir[0]->dir[2] = trie;
return trie->dir[0];
- if (trie->dir[1])
+ }
+ if (trie->dir[1]) {
+ trie->dir[1]->dir[2] = trie;
return trie->dir[1];
+ }
while (trie->dir[2]) {
if (trie->dir[2]->dir[1])
- if (trie->dir[2]->dir[1] != trie)
+ if (trie->dir[2]->dir[1] != trie) {
+ trie->dir[2]->dir[1]->dir[2] = trie->dir[2];
return trie->dir[2]->dir[1];
+ }
trie = trie->dir[2];
}
return NULL;
@@ -32,8 +42,8 @@ struct network {
int mask;
char * email;
char ** ns; // first one is master
- time_t serial; // for soa record
- time_t ttl;
+ int serial; // for soa record
+ int ttl;
struct suffix * suffix; // network does not own a suffix
char * from; // master that sent us this network or NULL if I am the master
};
@@ -53,7 +63,7 @@ struct ns {
struct in6_addr addr;
int mask;
char ** ns;
- time_t ttl;
+ int ttl;
char * from; // master that sent us this ns or NULL if I am the master
};
void free_ns (struct ns * ns) {
@@ -70,7 +80,7 @@ void free_ns (struct ns * ns) {
struct ptr {
struct in6_addr addr;
char * hostname;
- time_t ttl; // time of creation for ptr6c records
+ int ttl; // time of creation for ptr6c records
char * from; // master that sent us this ptr or NULL if I am the master
};
void free_ptr (struct ptr * ptr) {
@@ -95,6 +105,7 @@ void free_trie (struct trie * trie) {
free_ptr((struct ptr *) trie->data);
break;
case nothing:
+ free(trie->data);
break;
}
free_trie(trie->dir[0]);
@@ -114,8 +125,8 @@ struct suffix {
struct trie * accept; // trie structure: http://upload.šijanec.eu./d/suffix.jpg (data is irrelevant)
char ** ns; // first one is master
char * email;
- time_t ttl;
- time_t serial;
+ int ttl;
+ int serial;
char * from; // master that sent us this suffix or NULL if I am the master
};
void free_suffix (struct suffix * suffix) {
@@ -134,21 +145,24 @@ void free_suffix (struct suffix * suffix) {
}
struct config {
struct trie * trie;
- char ** master_servers;
- // char ** master_zones;
- char ** slaves;
+ char ** masters;
int poll_interval;
char * ptr_file;
void * suffixrp; // for tsearch(3)
};
-void add_accept (struct trie * trie, struct in6_addr addr, int mask) {
- int depth = 0;
- while (depth < mask) {
- bool bit = !!(addr.s6_addr[depth/8] & (1 << (7-depth%8)));
+struct netspec {
+ struct in6_addr addr;
+ int mask;
+};
+void add_accept (struct trie * trie, struct netspec netspec) {
+ for (int depth = 0; depth < netspec.mask; depth++) {
+ bool bit = !!(netspec.addr.s6_addr[depth/8] & (1 << (7-depth%8)));
if (!trie->dir[bit])
trie->dir[bit] = calloc(1, sizeof *trie);
trie = trie->dir[bit];
}
+ trie->data = calloc(1, sizeof(struct netspec));
+ memcpy(trie->data, &netspec, sizeof netspec);
}
bool is_acceptable (struct trie * trie, struct in6_addr addr) {
int depth = 0;
@@ -221,55 +235,6 @@ int validate_remote (cfg_t * cfg, cfg_opt_t * opt) {
*cp = '/';
return 0;
}
-int validate_zone (cfg_t * cfg, cfg_opt_t * opt) {
- char * value = cfg_opt_getnstr(opt, cfg_opt_size(opt) - 1);
- char * cp = strchr(value, '/');
- if (cp) {
- char * cp2;
- int mask = strtol(cp+1, &cp2, 10);
- if (*cp2) {
- cfg_error(cfg, "zone %s in %s in section %s has non-numeric characters as part of the netmask", value, opt->name, cfg->name);
- return -1;
- }
- if (mask < 0 || mask > 128) {
- cfg_error(cfg, "specified mask %d of zone %s in %s section %s is not in range 0-128", mask, value, opt->name, cfg->name);
- return -1;
- }
- if (mask % 4) {
- cfg_error(cfg, "specified mask %d of zone %s in %s section %s is not divisible by 4", mask, value, opt->name, cfg->name);
- return -1;
- }
- *cp = '\0';
- struct in6_addr tmp;
- switch (inet_pton(AF_INET6, value, &tmp)) {
- case -1:
- cfg_error(cfg, "error while parsing zone %s in section %s: inet_pton(AF_INET6, \"%s\", &tmp): %s --- your libc must support IPv6", opt->name, cfg->name, value, strerror(errno));
- if (cp)
- *cp = '/';
- return -1;
- case 0:
- cfg_error(cfg, "zone %s in section %s is an invalid ipv6 or v4mapped address (%s). see section AF_INET6 in `man inet_pton` for syntax.", opt->name, cfg->name, value);
- if (cp)
- *cp = '/';
- return -1;
- }
- for (int i = mask; i < 128; i++)
- if (tmp.s6_addr[i/8] & (1 << (7-i%8))) {
- cfg_error(cfg, "zone %s in section %s has host bits set (%s/%d) (debug: %d).", opt->name, cfg->name, value, mask, i);
- if (cp)
- *cp = '/';
- return -1;
- }
- *cp = '/';
- return 0;
- }
- unsigned char tmp[PACKETSZ];
- if (res_mkquery(QUERY, value, C_IN, T_AAAA, NULL, 0, NULL, tmp, PACKETSZ) == -1) {
- cfg_error(cfg, "zone %s in zone specification %s in section %s couldn't be parsed by res_mkquery", value, opt->name, cfg->name);
- return -1;
- }
- return 0;
-}
int validate_fqdn (cfg_t * cfg, cfg_opt_t * opt) {
char * value = cfg_opt_getnstr(opt, cfg_opt_size(opt) - 1);
unsigned char tmp[PACKETSZ];
@@ -303,12 +268,11 @@ int validate_email (cfg_t * cfg, cfg_opt_t * opt) {
int validate_network (cfg_t * cfg, cfg_opt_t * opt) {
cfg_t * sec = cfg_opt_getnsec(opt, cfg_opt_size(opt) - 1);
if (!cfg_size(sec, "networks")) {
- cfg_error(sec, "%s section does not contain any networks", opt->name);
+ cfg_error(cfg, "%s section does not contain any networks", opt->name);
return -1;
}
- char * master = cfg_getstr(sec, "master");
- if (!master) {
- cfg_error(cfg, "%s section does not contain required option master", opt->name);
+ if (!cfg_size(sec, "ns")) {
+ cfg_error(sec, "%s section does not contain any NS records", opt->name);
return -1;
}
return 0;
@@ -330,10 +294,6 @@ int validate_netspec (cfg_t * cfg, cfg_opt_t * opt) {
cfg_error(cfg, "specified mask %d of network specification %s in %s section %s is not in range 0-128", mask, value, opt->name, cfg->name);
return -1;
}
- if (mask % 4) {
- cfg_error(cfg, "specified mask %d of network specification %s in %s section %s is not divisible by 4", mask, value, opt->name, cfg->name);
- return -1;
- }
*cp = '\0';
struct in6_addr tmp;
switch (inet_pton(AF_INET6, value, &tmp)) {
@@ -385,42 +345,50 @@ int validate_ns (cfg_t * cfg, cfg_opt_t * opt) {
}
return 0;
}
+int validate_suffix (cfg_t * cfg, cfg_opt_t * opt) {
+ cfg_t * sec = cfg_opt_getnsec(opt, cfg_opt_size(opt) - 1);
+ if (!cfg_size(sec, "suffixes")) {
+ cfg_error(cfg, "%s section does not contain any suffixes", opt->name);
+ return -1;
+ }
+ if (!cfg_size(sec, "ns")) {
+ cfg_error(sec, "%s section does not contain any NS records", opt->name);
+ return -1;
+ }
+ return 0;
+}
int config (struct config * conf, const char * filename, FILE * output) {
cfg_opt_t network_opts[] = {
- CFG_STR_LIST("networks", NULL, CFGF_NODEFAULT), // REQUIRED at least one
- CFG_STR_LIST("slaves", "{}", CFGF_NONE),
+ CFG_STR_LIST("networks", NULL, CFGF_NODEFAULT),
+ CFG_STR_LIST("ns", NULL, CFGF_NODEFAULT), // REQUIRED at least one.
CFG_STR("admin", "6@sijanec.eu", CFGF_NONE),
- CFG_STR("master", NULL, CFGF_NODEFAULT), // REQUIRED
CFG_STR("suffix", NULL, CFGF_NONE),
CFG_INT("ttl", 420, CFGF_NONE),
CFG_END()
};
cfg_opt_t suffix_opts[] = {
- CFG_STR_LIST("suffixes", NULL, CFGF_NODEFAULT), // REQUIRED at least one
+ CFG_STR_LIST("suffixes", NULL, CFGF_NODEFAULT),
CFG_STR_LIST("accept", "{::/0}", CFGF_NONE),
- CFG_STR_LIST("slaves", "{}", CFGF_NONE),
+ CFG_STR_LIST("ns", NULL, CFGF_NODEFAULT), // REQUIRED at least one.
CFG_STR("admin", "6@sijanec.eu", CFGF_NONE),
- CFG_STR("master", NULL, CFGF_NODEFAULT), // REQUIRED
CFG_INT("ttl", 420, CFGF_NONE),
CFG_END()
};
cfg_opt_t ptr_opts[] = {
- CFG_STR("hostname", NULL, CFGF_NODEFAULT), // REQUIRED
+ CFG_STR("hostname", NULL, CFGF_NODEFAULT),
CFG_INT("ttl", 420, CFGF_NONE),
CFG_END()
};
cfg_opt_t ns_opts[] = {
- CFG_STR_LIST("networks", NULL, CFGF_NODEFAULT), // REQUIRED at least one
- CFG_STR_LIST("ns", NULL, CFGF_NODEFAULT), // REQUIRED
+ CFG_STR_LIST("networks", NULL, CFGF_NODEFAULT),
+ CFG_STR_LIST("ns", NULL, CFGF_NODEFAULT),
CFG_INT("ttl", 420, CFGF_NONE),
CFG_END()
};
cfg_opt_t opts[] = {
- CFG_STR_LIST("master_servers", "{}", CFGF_NONE),
- // CFG_STR_LIST("master_zones", "{}", CFGF_NONE),
+ CFG_STR_LIST("masters", "{}", CFGF_NONE),
CFG_INT("poll_interval", 69, CFGF_NONE),
CFG_STR("ptr_file", "/var/lib/cache/6/backup", CFGF_NONE),
- CFG_STR_LIST("slaves", "{}", CFGF_NONE),
CFG_SEC("network", network_opts, CFGF_MULTI),
CFG_SEC("suffix", suffix_opts, CFGF_MULTI),
CFG_SEC("ptr", ptr_opts, CFGF_TITLE | CFGF_MULTI | CFGF_NO_TITLE_DUPES),
@@ -434,11 +402,9 @@ int config (struct config * conf, const char * filename, FILE * output) {
cfg_set_validate_func(cfg, "suffix|ttl", validate_positive);
cfg_set_validate_func(cfg, "ptr|ttl", validate_positive);
cfg_set_validate_func(cfg, "ns|ttl", validate_positive);
- cfg_set_validate_func(cfg, "master_servers", validate_remote);
- cfg_set_validate_func(cfg, "slaves", validate_remote);
- // cfg_set_validate_func(cfg, "master_zones", validate_zone);
- cfg_set_validate_func(cfg, "network|slaves", validate_fqdn);
- cfg_set_validate_func(cfg, "suffix|slaves", validate_fqdn);
+ cfg_set_validate_func(cfg, "masters", validate_remote);
+ cfg_set_validate_func(cfg, "network|ns", validate_fqdn);
+ cfg_set_validate_func(cfg, "suffix|ns", validate_fqdn);
cfg_set_validate_func(cfg, "ptr|hostname", validate_fqdn);
cfg_set_validate_func(cfg, "ns|ns", validate_fqdn);
cfg_set_validate_func(cfg, "suffix|suffixes", validate_fqdn);
@@ -448,6 +414,7 @@ int config (struct config * conf, const char * filename, FILE * output) {
cfg_set_validate_func(cfg, "suffix|accept", validate_netspec);
cfg_set_validate_func(cfg, "ns|networks", validate_netspec);
cfg_set_validate_func(cfg, "network", validate_network);
+ cfg_set_validate_func(cfg, "suffix", validate_suffix);
cfg_set_validate_func(cfg, "ptr", validate_ptr);
cfg_set_validate_func(cfg, "ns", validate_ns);
switch (cfg_parse(cfg, filename)) {
@@ -459,65 +426,105 @@ int config (struct config * conf, const char * filename, FILE * output) {
fprintf(output, "# configuration file '%s' could not be parsed\n", filename);
return 2;
}
- if (conf->master_servers) {
- char ** pcp = conf->master_servers;
+ if (conf->masters) {
+ char ** pcp = conf->masters;
for (; *pcp; pcp++)
free(*pcp);
- free(conf->master_servers);
+ free(conf->masters);
}
- conf->master_servers = calloc(cfg_size(cfg, "master_servers")+1, sizeof *conf->master_servers);
- for (size_t i = 0; i < cfg_size(cfg, "master_servers"); i++)
- conf->master_servers[i] = strdup(cfg_getnstr(cfg, "master_servers", i));
- /* if (conf->master_zones) {
- char ** pcp = conf->master_zones;
- for (; *pcp; pcp++)
- free(*pcp);
- free(conf->master_zones);
- }
- conf->master_zones = calloc(cfg_size(cfg, "master_zones")+1, sizeof *conf->master_zones);
- for (size_t i = 0; i < cfg_size(cfg, "master_zones"); i++)
- conf->master_zones[i] = strdup(cfg_getnstr(cfg, "master_zones", i)); */
+ conf->masters = calloc(cfg_size(cfg, "masters")+1, sizeof *conf->masters);
+ for (size_t i = 0; i < cfg_size(cfg, "masters"); i++)
+ conf->masters[i] = strdup(cfg_getnstr(cfg, "masters", i));
conf->poll_interval = cfg_getint(cfg, "poll_interval");
free(conf->ptr_file);
conf->ptr_file = strdup(cfg_getstr(cfg, "ptr_file"));
- if (conf->slaves) {
- char ** pcp = conf->slaves;
- for (; *pcp; pcp++)
- free(*pcp);
- free(conf->slaves);
- }
- conf->slaves = calloc(cfg_size(cfg, "slaves")+1, sizeof *conf->slaves);
- for (size_t i = 0; i < cfg_size(cfg, "slaves"); i++)
- conf->slaves[i] = strdup(cfg_getnstr(cfg, "slaves", i));
for (size_t i = 0; i < cfg_size(cfg, "suffix"); i++) {
cfg_t * cfg_suffix = cfg_getnsec(cfg, "suffix", i);
for (size_t j = 0; j < cfg_size(cfg_suffix, "suffixes"); j++) {
-
+ char * suffixstr = strdup(cfg_getnstr(cfg_suffix, "suffixes", j));
+ struct suffix ** found = tfind(&suffixstr, &conf->suffixrp, compar_pcp);
+ if (found) {
+ free_suffix(*found);
+ tdelete(&suffixstr, &conf->suffixrp, compar_pcp);
+ }
+ struct suffix * suffix = calloc(1, sizeof *suffix);
+ suffix->suffix = suffixstr;
+ suffix->accept = calloc(1, sizeof *suffix->accept);
+ if (cfg_getstr(cfg_suffix, "admin"))
+ suffix->email = strdup(cfg_getstr(cfg_suffix, "admin"));
+ suffix->ns = calloc(cfg_size(cfg_suffix, "ns")+1, sizeof *suffix->ns);
+ for (size_t k = 0; k < cfg_size(cfg_suffix, "ns"); k++)
+ suffix->ns[k] = strdup(cfg_getnstr(cfg_suffix, "ns", k));
+ suffix->ttl = cfg_getint(cfg_suffix, "ttl");
+ for (size_t k = 0; k < cfg_size(cfg_suffix, "accept"); k++) {
+ struct netspec netspec;
+ char * cp = strchr(cfg_getnstr(cfg_suffix, "accept", k), '/');
+ cp[0] = '\0';
+ netspec.mask = strtol(cp+1, NULL, 10);
+ inet_pton(AF_INET6, cfg_getnstr(cfg_suffix, "accept", k), netspec.addr.s6_addr);
+ cp[0] = '/';
+ add_accept(suffix->accept, netspec);
+ }
+ suffix->serial = timestamp();
+ tsearch(suffix, &conf->suffixrp, compar_pcp);
}
}
- if (!output)
- return 0;
- fprintf(output, "master_servers = {");
- char ** pcp = conf->master_servers;
- while (*pcp) {
- fprintf(output, "\"%s\"", *pcp);
- if (*++pcp)
+ return 0;
+}
+#ifndef _GNU_SOURCE
+FILE * global_print_suffix_output;
+#endif
+void print_suffix (const void * nodep, VISIT which,
+#ifndef _GNU_SOURCE
+int depth __attribute__((unused))
+#else
+void * closure
+#endif
+) {
+ struct suffix * suffix = *((struct suffix **) nodep);
+ if (!(which == postorder || which == leaf))
+ return;
+#ifndef _GNU_SOURCE
+ FILE * output = global_print_suffix_output;
+#else
+ FILE * output = (FILE *) closure;
+#endif
+ fprintf(output, "suffix\n{\tttl = %d\n\t", suffix->ttl);
+ if (suffix->email)
+ fprintf(output, "admin = \"%s\"\n\t", suffix->email);
+ fprintf(output, "accept = {");
+ unsigned i = 0;
+ for (struct trie * trie = suffix->accept; trie; trie = next(trie)) {
+ if (trie->dir[0] || trie->dir[1])
+ continue;
+ if (i++)
fprintf(output, ", ");
+ char buf[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET6, ((struct netspec *) trie->data)->addr.s6_addr, buf, sizeof buf);
+ fprintf(output, "\"%s/%d\"", buf, ((struct netspec *) trie->data)->mask);
}
- /* fprintf(output, "}\nmaster_zones = {");
- pcp = conf->master_zones;
+ fprintf(output, "}\n\tns = {");
+ char ** pcp = suffix->ns;
while (*pcp) {
fprintf(output, "\"%s\"", *pcp);
if (*++pcp)
fprintf(output, ", ");
- } */
- fprintf(output, "}\npoll_interval = %d\nptr_file = \"%s\"\nslaves = {", conf->poll_interval, conf->ptr_file);
- pcp = conf->slaves;
+ }
+ fprintf(output, "}\n\tsuffixes = {\"%s\"}\n}\n", suffix->suffix);
+}
+void print_config (const struct config * conf, FILE * output) {
+ fprintf(output, "masters = {");
+ char ** pcp = conf->masters;
while (*pcp) {
fprintf(output, "\"%s\"", *pcp);
if (*++pcp)
fprintf(output, ", ");
}
- fprintf(output, "}\n");
- return 0;
+ fprintf(output, "}\npoll_interval = %d\nptr_file = \"%s\"\n", conf->poll_interval, conf->ptr_file);
+#ifndef _GNU_SOURCE
+ global_print_suffix_output = output;
+ twalk(conf->suffixrp, print_suffix);
+#else
+ twalk_r(conf->suffixrp, print_suffix, output);
+#endif
}
diff --git a/prog/6/daemon.c b/prog/6/daemon.c
index a808487..1807933 100644
--- a/prog/6/daemon.c
+++ b/prog/6/daemon.c
@@ -80,14 +80,15 @@ int main (int argc, char ** argv) {
}
struct config conf;
memset(&conf, 0, sizeof conf);
- FILE * conf_output = stderr;
- if (argv[1][0] == 'd')
- conf_output = stdout;
- int ret = config(&conf, argv[2], conf_output);
+ int ret = config(&conf, argv[2], stderr);
if (ret) {
fprintf(stderr, "error %d while parsing the configuration file!\n", ret);
return 9+ret;
}
+ FILE * conf_output = stderr;
+ if (argv[1][0] == 'd')
+ conf_output = stdout;
+ print_config(&conf, conf_output);
if (argv[1][0] == 'd')
return 0;
int sock = socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);