mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- Work on local root zone code.
git-svn-id: file:///svn/unbound/trunk@4376 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
c5c2cb13d4
commit
b37bc47eaa
14 changed files with 4134 additions and 2991 deletions
12
Makefile.in
12
Makefile.in
|
|
@ -823,9 +823,11 @@ shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/ut
|
||||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
|
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
|
||||||
authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/services/authzone.h \
|
authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/services/authzone.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
|
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
|
||||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||||
$(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h \
|
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
|
||||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
|
$(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||||
|
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/config_file.h \
|
||||||
|
$(srcdir)/util/module.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
|
||||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h $(srcdir)/validator/val_nsec3.h \
|
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h $(srcdir)/validator/val_nsec3.h \
|
||||||
$(srcdir)/validator/val_secalgo.h
|
$(srcdir)/validator/val_secalgo.h
|
||||||
fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \
|
fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \
|
||||||
|
|
@ -1313,8 +1315,8 @@ unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c
|
||||||
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
|
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
|
||||||
$(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \
|
$(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \
|
||||||
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \
|
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \
|
||||||
$(srcdir)/services/view.h $(srcdir)/respip/respip.h $(srcdir)/sldns/sbuffer.h $(PYTHONMOD_HEADER) \
|
$(srcdir)/services/view.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h $(srcdir)/sldns/sbuffer.h \
|
||||||
$(srcdir)/edns-subnet/subnet-whitelist.h
|
$(PYTHONMOD_HEADER) $(srcdir)/edns-subnet/subnet-whitelist.h
|
||||||
worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/libunbound/context.h \
|
worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/libunbound/context.h \
|
||||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||||
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
The `dnscrypt-provider-cert-rotated` allow to instruct unbound to not
|
The `dnscrypt-provider-cert-rotated` allow to instruct unbound to not
|
||||||
publish the cert as part of the DNS's provider_name's TXT answer.
|
publish the cert as part of the DNS's provider_name's TXT answer.
|
||||||
- Better documentation for cache-max-negative-ttl.
|
- Better documentation for cache-max-negative-ttl.
|
||||||
|
- Work on local root zone code.
|
||||||
|
|
||||||
10 October 2017: Wouter
|
10 October 2017: Wouter
|
||||||
- tag 1.6.7
|
- tag 1.6.7
|
||||||
|
|
|
||||||
|
|
@ -808,6 +808,30 @@ remote-control:
|
||||||
# name: "example.org"
|
# name: "example.org"
|
||||||
# forward-host: fwd.example.com
|
# forward-host: fwd.example.com
|
||||||
|
|
||||||
|
# Authority zones
|
||||||
|
# The data for these zones is kept locally, from a file or downloaded.
|
||||||
|
# The data can be served to downstream clients, or used instead of the
|
||||||
|
# upstream (which saves a lookup to the upstream). The first example
|
||||||
|
# has a copy of the root for local usage. The second serves example.org
|
||||||
|
# authoritatively. zonefile: reads from file (and writes to it if you also
|
||||||
|
# download it), master: fetches with AXFR, url: fetches zonefile over http.
|
||||||
|
# auth-zone:
|
||||||
|
# name: "."
|
||||||
|
# for-downstream: no
|
||||||
|
# for-upstream: yes
|
||||||
|
# master: b.root-servers.net
|
||||||
|
# master: c.root-servers.net
|
||||||
|
# master: e.root-servers.net
|
||||||
|
# master: f.root-servers.net
|
||||||
|
# master: g.root-servers.net
|
||||||
|
# master: k.root-servers.net
|
||||||
|
# auth-zone:
|
||||||
|
# name: "example.org"
|
||||||
|
# for-downstream: yes
|
||||||
|
# for-upstream: yes
|
||||||
|
# zonefile: "example.org.zone"
|
||||||
|
# url: "http://www.example.com/example.org.zone"
|
||||||
|
|
||||||
# Views
|
# Views
|
||||||
# Create named views. Name must be unique. Map views to requests using
|
# Create named views. Name must be unique. Map views to requests using
|
||||||
# the access-control-view option. Views can contain zero or more local-zone
|
# the access-control-view option. Views can contain zero or more local-zone
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,16 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
#include "util/data/dname.h"
|
#include "util/data/dname.h"
|
||||||
|
#include "util/data/msgparse.h"
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
|
#include "util/data/msgencode.h"
|
||||||
#include "util/data/packed_rrset.h"
|
#include "util/data/packed_rrset.h"
|
||||||
#include "util/regional.h"
|
#include "util/regional.h"
|
||||||
#include "util/net_help.h"
|
#include "util/net_help.h"
|
||||||
|
#include "util/netevent.h"
|
||||||
#include "util/config_file.h"
|
#include "util/config_file.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
#include "util/module.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "sldns/rrdef.h"
|
#include "sldns/rrdef.h"
|
||||||
#include "sldns/pkthdr.h"
|
#include "sldns/pkthdr.h"
|
||||||
|
|
@ -252,9 +256,11 @@ struct auth_zones* auth_zones_create(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
rbtree_init(&az->ztree, &auth_zone_cmp);
|
rbtree_init(&az->ztree, &auth_zone_cmp);
|
||||||
|
rbtree_init(&az->xtree, &auth_xfer_cmp);
|
||||||
lock_rw_init(&az->lock);
|
lock_rw_init(&az->lock);
|
||||||
lock_protect(&az->lock, &az->ztree, sizeof(az->ztree));
|
lock_protect(&az->lock, &az->ztree, sizeof(az->ztree));
|
||||||
/* also lock protects the rbnode's in struct auth_zone */
|
lock_protect(&az->lock, &az->xtree, sizeof(az->xtree));
|
||||||
|
/* also lock protects the rbnode's in struct auth_zone, auth_xfer */
|
||||||
return az;
|
return az;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,6 +291,23 @@ int auth_data_cmp(const void* z1, const void* z2)
|
||||||
b->namelabs, &m);
|
b->namelabs, &m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int auth_xfer_cmp(const void* z1, const void* z2)
|
||||||
|
{
|
||||||
|
/* first sort on class, so that hierarchy can be maintained within
|
||||||
|
* a class */
|
||||||
|
struct auth_xfer* a = (struct auth_xfer*)z1;
|
||||||
|
struct auth_xfer* b = (struct auth_xfer*)z2;
|
||||||
|
int m;
|
||||||
|
if(a->dclass != b->dclass) {
|
||||||
|
if(a->dclass < b->dclass)
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* sorted such that higher zones sort before lower zones (their
|
||||||
|
* contents) */
|
||||||
|
return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m);
|
||||||
|
}
|
||||||
|
|
||||||
/** delete auth rrset node */
|
/** delete auth rrset node */
|
||||||
static void
|
static void
|
||||||
auth_rrset_delete(struct auth_rrset* rrset)
|
auth_rrset_delete(struct auth_rrset* rrset)
|
||||||
|
|
@ -374,6 +397,19 @@ auth_zone_find(struct auth_zones* az, uint8_t* nm, size_t nmlen,
|
||||||
return (struct auth_zone*)rbtree_search(&az->ztree, &key);
|
return (struct auth_zone*)rbtree_search(&az->ztree, &key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct auth_xfer*
|
||||||
|
auth_xfer_find(struct auth_zones* az, uint8_t* nm, size_t nmlen,
|
||||||
|
uint16_t dclass)
|
||||||
|
{
|
||||||
|
struct auth_xfer key;
|
||||||
|
key.node.key = &key;
|
||||||
|
key.dclass = dclass;
|
||||||
|
key.name = nm;
|
||||||
|
key.namelen = nmlen;
|
||||||
|
key.namelabs = dname_count_labels(nm);
|
||||||
|
return (struct auth_xfer*)rbtree_search(&az->xtree, &key);
|
||||||
|
}
|
||||||
|
|
||||||
/** find an auth zone or sorted less-or-equal, return true if exact */
|
/** find an auth zone or sorted less-or-equal, return true if exact */
|
||||||
static int
|
static int
|
||||||
auth_zone_find_less_equal(struct auth_zones* az, uint8_t* nm, size_t nmlen,
|
auth_zone_find_less_equal(struct auth_zones* az, uint8_t* nm, size_t nmlen,
|
||||||
|
|
@ -437,6 +473,23 @@ auth_zones_find_or_add_zone(struct auth_zones* az, char* name)
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** find or create xfer zone with name str. caller must have lock on az.
|
||||||
|
* returns a locked xfer */
|
||||||
|
static struct auth_xfer*
|
||||||
|
auth_zones_find_or_add_xfer(struct auth_zones* az, struct auth_zone* z)
|
||||||
|
{
|
||||||
|
struct auth_xfer* x;
|
||||||
|
x = auth_xfer_find(az, z->name, z->namelen, z->dclass);
|
||||||
|
if(!x) {
|
||||||
|
/* not found, create the zone */
|
||||||
|
x = auth_xfer_create(az, z);
|
||||||
|
lock_basic_lock(&x->lock);
|
||||||
|
} else {
|
||||||
|
lock_basic_lock(&x->lock);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
auth_zone_set_zonefile(struct auth_zone* z, char* zonefile)
|
auth_zone_set_zonefile(struct auth_zone* z, char* zonefile)
|
||||||
{
|
{
|
||||||
|
|
@ -1052,6 +1105,13 @@ auth_zone_read_zonefile(struct auth_zone* z)
|
||||||
in = fopen(z->zonefile, "r");
|
in = fopen(z->zonefile, "r");
|
||||||
if(!in) {
|
if(!in) {
|
||||||
char* n = sldns_wire2str_dname(z->name, z->namelen);
|
char* n = sldns_wire2str_dname(z->name, z->namelen);
|
||||||
|
if(z->zone_is_slave && errno == ENOENT) {
|
||||||
|
/* we fetch the zone contents later, no file yet */
|
||||||
|
verbose(VERB_ALGO, "no zonefile %s for %s",
|
||||||
|
z->zonefile, n?n:"error");
|
||||||
|
free(n);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
log_err("cannot open zonefile %s for %s: %s",
|
log_err("cannot open zonefile %s for %s: %s",
|
||||||
z->zonefile, n?n:"error", strerror(errno));
|
z->zonefile, n?n:"error", strerror(errno));
|
||||||
free(n);
|
free(n);
|
||||||
|
|
@ -1185,68 +1245,177 @@ auth_zones_read_zones(struct auth_zones* az)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** set str2list with (zonename, zonefile) config items and create zones */
|
/** setup all auth zones */
|
||||||
static int
|
int
|
||||||
auth_zones_cfg_zonefile(struct auth_zones* az, struct config_str2list* zlist)
|
auth_zones_setup_zones(struct auth_zones* az, struct module_env* env)
|
||||||
{
|
{
|
||||||
struct auth_zone* z;
|
struct auth_zone* z;
|
||||||
while(zlist) {
|
struct auth_xfer* x;
|
||||||
lock_rw_wrlock(&az->lock);
|
lock_rw_wrlock(&az->lock);
|
||||||
if(!(z=auth_zones_find_or_add_zone(az, zlist->str))) {
|
RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
|
||||||
|
lock_rw_wrlock(&z->lock);
|
||||||
|
x = auth_xfer_find(az, z->name, z->namelen, z->dclass);
|
||||||
|
if(x) {
|
||||||
|
lock_basic_lock(&x->lock);
|
||||||
|
}
|
||||||
|
if(!auth_xfer_setup(z, x, env)) {
|
||||||
|
if(x) {
|
||||||
|
lock_basic_unlock(&x->lock);
|
||||||
|
}
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
lock_rw_unlock(&az->lock);
|
lock_rw_unlock(&az->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(x) {
|
||||||
|
lock_basic_unlock(&x->lock);
|
||||||
|
}
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
|
}
|
||||||
lock_rw_unlock(&az->lock);
|
lock_rw_unlock(&az->lock);
|
||||||
if(!auth_zone_set_zonefile(z, zlist->str2)) {
|
|
||||||
lock_rw_unlock(&z->lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
lock_rw_unlock(&z->lock);
|
|
||||||
zlist = zlist->next;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** set str2list with (zonename, fallback) config items and create zones */
|
/** set config items and create zones */
|
||||||
static int
|
static int
|
||||||
auth_zones_cfg_fallback(struct auth_zones* az, struct config_str2list* zlist)
|
auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
|
||||||
{
|
{
|
||||||
struct auth_zone* z;
|
struct auth_zone* z;
|
||||||
while(zlist) {
|
struct auth_xfer* x = NULL;
|
||||||
|
|
||||||
|
/* create zone */
|
||||||
lock_rw_wrlock(&az->lock);
|
lock_rw_wrlock(&az->lock);
|
||||||
if(!(z=auth_zones_find_or_add_zone(az, zlist->str))) {
|
if(!(z=auth_zones_find_or_add_zone(az, c->name))) {
|
||||||
lock_rw_unlock(&az->lock);
|
lock_rw_unlock(&az->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(c->masters || c->urls) {
|
||||||
|
if(!(x=auth_zones_find_or_add_xfer(az, z))) {
|
||||||
lock_rw_unlock(&az->lock);
|
lock_rw_unlock(&az->lock);
|
||||||
if(!auth_zone_set_fallback(z, zlist->str2)) {
|
|
||||||
lock_rw_unlock(&z->lock);
|
lock_rw_unlock(&z->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lock_rw_unlock(&z->lock);
|
|
||||||
zlist = zlist->next;
|
|
||||||
}
|
}
|
||||||
|
if(c->for_downstream)
|
||||||
|
az->have_downstream = 1;
|
||||||
|
lock_rw_unlock(&az->lock);
|
||||||
|
|
||||||
|
/* set options */
|
||||||
|
if(!auth_zone_set_zonefile(z, c->zonefile)) {
|
||||||
|
if(x) {
|
||||||
|
lock_basic_unlock(&x->lock);
|
||||||
|
}
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
z->for_downstream = c->for_downstream;
|
||||||
|
z->for_upstream = c->for_upstream;
|
||||||
|
/* TODO fallback option */
|
||||||
|
//if(!auth_zone_set_fallback(z, zlist->str2)) {
|
||||||
|
/* TODO other options */
|
||||||
|
|
||||||
|
/* xfer zone */
|
||||||
|
if(x) {
|
||||||
|
z->zone_is_slave = 1;
|
||||||
|
/* set options on xfer zone */
|
||||||
|
if(!xfer_set_masters(&x->task_probe->masters, c)) {
|
||||||
|
lock_basic_unlock(&x->lock);
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!xfer_set_masters(&x->task_transfer->masters, c)) {
|
||||||
|
lock_basic_unlock(&x->lock);
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lock_basic_unlock(&x->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int auth_zones_apply_config(struct auth_zones* az, struct config_file* cfg)
|
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg)
|
||||||
{
|
{
|
||||||
(void)cfg;
|
struct config_auth* p;
|
||||||
/* TODO cfg str2lists */
|
for(p = cfg->auths; p; p = p->next) {
|
||||||
/* create config items for
|
if(!p->name || p->name[0] == 0) {
|
||||||
* auth-zone: name: "example.com"
|
log_warn("auth-zone without a name, skipped");
|
||||||
* zonefile: "zones/example.com"
|
continue;
|
||||||
* fallback: yes
|
}
|
||||||
*/
|
if(!auth_zones_cfg(az, p)) {
|
||||||
if(!auth_zones_cfg_zonefile(az, NULL /*cfg->auth_zones*/))
|
log_err("cannot config auth zone %s", p->name);
|
||||||
return 0;
|
|
||||||
if(!auth_zones_cfg_fallback(az, NULL /*cfg->auth_zones*/))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(!auth_zones_read_zones(az))
|
if(!auth_zones_read_zones(az))
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** delete chunks
|
||||||
|
* @param at: transfer structure with chunks list. The chunks and their
|
||||||
|
* data are freed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
auth_chunks_delete(struct auth_transfer* at)
|
||||||
|
{
|
||||||
|
if(at->chunks_first) {
|
||||||
|
struct auth_chunk* c, *cn;
|
||||||
|
c = at->chunks_first;
|
||||||
|
while(c) {
|
||||||
|
cn = c->next;
|
||||||
|
free(c->data);
|
||||||
|
free(c);
|
||||||
|
c = cn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
at->chunks_first = NULL;
|
||||||
|
at->chunks_last = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** free the masters list */
|
||||||
|
static void
|
||||||
|
auth_free_masters(struct auth_master* list)
|
||||||
|
{
|
||||||
|
struct auth_master* n;
|
||||||
|
while(list) {
|
||||||
|
n = list->next;
|
||||||
|
free(list->host);
|
||||||
|
free(list->file);
|
||||||
|
free(list);
|
||||||
|
list = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** delete auth xfer structure
|
||||||
|
* @param xfr: delete this xfer and its tasks.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
auth_xfer_delete(struct auth_xfer* xfr)
|
||||||
|
{
|
||||||
|
if(!xfr) return;
|
||||||
|
lock_basic_destroy(&xfr->lock);
|
||||||
|
free(xfr->name);
|
||||||
|
if(xfr->task_nextprobe) {
|
||||||
|
comm_timer_delete(xfr->task_nextprobe->timer);
|
||||||
|
free(xfr->task_nextprobe);
|
||||||
|
}
|
||||||
|
if(xfr->task_probe) {
|
||||||
|
auth_free_masters(xfr->task_probe->masters);
|
||||||
|
comm_point_delete(xfr->task_probe->cp);
|
||||||
|
free(xfr->task_probe);
|
||||||
|
}
|
||||||
|
if(xfr->task_transfer) {
|
||||||
|
auth_free_masters(xfr->task_transfer->masters);
|
||||||
|
comm_point_delete(xfr->task_transfer->cp);
|
||||||
|
if(xfr->task_transfer->chunks_first) {
|
||||||
|
auth_chunks_delete(xfr->task_transfer);
|
||||||
|
}
|
||||||
|
free(xfr->task_transfer);
|
||||||
|
}
|
||||||
|
free(xfr);
|
||||||
|
}
|
||||||
|
|
||||||
/** helper traverse to delete zones */
|
/** helper traverse to delete zones */
|
||||||
static void
|
static void
|
||||||
auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||||
|
|
@ -1255,11 +1424,20 @@ auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||||
auth_zone_delete(z);
|
auth_zone_delete(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** helper traverse to delete xfer zones */
|
||||||
|
static void
|
||||||
|
auth_xfer_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||||
|
{
|
||||||
|
struct auth_xfer* z = (struct auth_xfer*)n->key;
|
||||||
|
auth_xfer_delete(z);
|
||||||
|
}
|
||||||
|
|
||||||
void auth_zones_delete(struct auth_zones* az)
|
void auth_zones_delete(struct auth_zones* az)
|
||||||
{
|
{
|
||||||
if(!az) return;
|
if(!az) return;
|
||||||
lock_rw_destroy(&az->lock);
|
lock_rw_destroy(&az->lock);
|
||||||
traverse_postorder(&az->ztree, auth_zone_del, NULL);
|
traverse_postorder(&az->ztree, auth_zone_del, NULL);
|
||||||
|
traverse_postorder(&az->xtree, auth_xfer_del, NULL);
|
||||||
free(az);
|
free(az);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2367,3 +2545,301 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
||||||
lock_rw_unlock(&z->lock);
|
lock_rw_unlock(&z->lock);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** encode auth answer */
|
||||||
|
static void
|
||||||
|
auth_answer_encode(struct query_info* qinfo, struct module_env* env,
|
||||||
|
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||||
|
struct dns_msg* msg)
|
||||||
|
{
|
||||||
|
uint16_t udpsize;
|
||||||
|
udpsize = edns->udp_size;
|
||||||
|
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||||
|
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||||
|
edns->ext_rcode = 0;
|
||||||
|
edns->bits &= EDNS_DO;
|
||||||
|
|
||||||
|
if(!inplace_cb_reply_local_call(env, qinfo, NULL, msg->rep,
|
||||||
|
FLAGS_GET_RCODE(msg->rep->flags), edns, temp)
|
||||||
|
|| !reply_info_answer_encode(qinfo, msg->rep,
|
||||||
|
*(uint16_t*)sldns_buffer_begin(buf),
|
||||||
|
sldns_buffer_read_u16_at(buf, 2),
|
||||||
|
buf, 0, 0, temp, udpsize, edns,
|
||||||
|
(int)(edns->bits&EDNS_DO), 0)) {
|
||||||
|
error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
|
||||||
|
*(uint16_t*)sldns_buffer_begin(buf),
|
||||||
|
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** encode auth error answer */
|
||||||
|
static void
|
||||||
|
auth_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||||
|
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||||
|
int rcode)
|
||||||
|
{
|
||||||
|
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||||
|
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||||
|
edns->ext_rcode = 0;
|
||||||
|
edns->bits &= EDNS_DO;
|
||||||
|
|
||||||
|
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
|
||||||
|
rcode, edns, temp))
|
||||||
|
edns->opt_list = NULL;
|
||||||
|
error_encode(buf, rcode|BIT_AA, qinfo,
|
||||||
|
*(uint16_t*)sldns_buffer_begin(buf),
|
||||||
|
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||||
|
}
|
||||||
|
|
||||||
|
int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||||
|
struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
|
||||||
|
struct regional* temp)
|
||||||
|
{
|
||||||
|
struct dns_msg* msg = NULL;
|
||||||
|
struct auth_zone* z;
|
||||||
|
int r;
|
||||||
|
int fallback = 0;
|
||||||
|
|
||||||
|
lock_rw_rdlock(&az->lock);
|
||||||
|
if(!az->have_downstream) {
|
||||||
|
/* no downstream auth zones */
|
||||||
|
lock_rw_unlock(&az->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
z = auth_zones_find_zone(az, qinfo);
|
||||||
|
if(!z) {
|
||||||
|
/* no zone above it */
|
||||||
|
lock_rw_unlock(&az->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lock_rw_unlock(&az->lock);
|
||||||
|
if(!z->for_downstream) {
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* answer it from zone z */
|
||||||
|
r = auth_zone_generate_answer(z, qinfo, temp, &msg, &fallback);
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
|
if(fallback) {
|
||||||
|
/* fallback to regular answering (recursive) */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encode answer */
|
||||||
|
if(!r)
|
||||||
|
auth_error_encode(qinfo, env, edns, buf, temp,
|
||||||
|
LDNS_RCODE_SERVFAIL);
|
||||||
|
else auth_answer_encode(qinfo, env, edns, buf, temp, msg);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** the current transfer has finished, apply the results.
|
||||||
|
* set timer for future probe. See if zone is expired now. */
|
||||||
|
void
|
||||||
|
xfr_master_transferresult(struct auth_xfer* xfr)
|
||||||
|
{
|
||||||
|
(void)xfr;
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
/** the current probe has finished, inspect the results.
|
||||||
|
* move on to the next master or start a transfer, or at last master,
|
||||||
|
* set timer for future probe. See if zone is expired now. */
|
||||||
|
void
|
||||||
|
xfr_master_proberesult(struct auth_xfer* xfr)
|
||||||
|
{
|
||||||
|
(void)xfr;
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
/** with current master selected, start the probe, or transfer */
|
||||||
|
int
|
||||||
|
xfr_master_start(struct auth_xfer* xfr)
|
||||||
|
{
|
||||||
|
(void)xfr;
|
||||||
|
/* TODO */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Find auth_zone SOA and populate the values in xfr(soa values). */
|
||||||
|
static int
|
||||||
|
xfr_find_soa(struct auth_zone* z, struct auth_xfer* xfr)
|
||||||
|
{
|
||||||
|
struct auth_data* apex;
|
||||||
|
struct auth_rrset* soa;
|
||||||
|
struct packed_rrset_data* d;
|
||||||
|
apex = az_find_name(z, z->name, z->namelen);
|
||||||
|
if(!apex) return 0;
|
||||||
|
soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
|
||||||
|
if(!soa || soa->data->count==0)
|
||||||
|
return 0; /* no RRset or no RRs in rrset */
|
||||||
|
if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */
|
||||||
|
/* SOA record ends with serial, refresh, retry, expiry, minimum,
|
||||||
|
* as 4 byte fields */
|
||||||
|
d = soa->data;
|
||||||
|
xfr->have_zone = 1;
|
||||||
|
xfr->serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20));
|
||||||
|
xfr->retry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-16));
|
||||||
|
xfr->refresh = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-12));
|
||||||
|
xfr->expiry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-8));
|
||||||
|
/* soa minimum at d->rr_len[0]-4 */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** determine next timeout for auth_xfer. Also (re)sets timer. */
|
||||||
|
void
|
||||||
|
xfr_set_timeout(struct auth_xfer* xfr)
|
||||||
|
{
|
||||||
|
(void)xfr;
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* malloc the xfer and tasks
|
||||||
|
* @param z: auth_zone with name of zone.
|
||||||
|
*/
|
||||||
|
static struct auth_xfer*
|
||||||
|
auth_xfer_new(struct auth_zone* z)
|
||||||
|
{
|
||||||
|
struct auth_xfer* xfr;
|
||||||
|
xfr = (struct auth_xfer*)calloc(1, sizeof(*xfr));
|
||||||
|
if(!xfr) return NULL;
|
||||||
|
xfr->name = memdup(z->name, z->namelen);
|
||||||
|
if(!xfr->name) {
|
||||||
|
free(xfr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
xfr->node.key = xfr;
|
||||||
|
xfr->namelen = z->namelen;
|
||||||
|
xfr->namelabs = z->namelabs;
|
||||||
|
xfr->dclass = z->dclass;
|
||||||
|
|
||||||
|
xfr->task_nextprobe = (struct auth_nextprobe*)calloc(1,
|
||||||
|
sizeof(struct auth_nextprobe));
|
||||||
|
if(!xfr->task_nextprobe) {
|
||||||
|
free(xfr->name);
|
||||||
|
free(xfr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
xfr->task_nextprobe->workernum = -1;
|
||||||
|
xfr->task_probe = (struct auth_probe*)calloc(1,
|
||||||
|
sizeof(struct auth_probe));
|
||||||
|
if(!xfr->task_probe) {
|
||||||
|
free(xfr->task_nextprobe);
|
||||||
|
free(xfr->name);
|
||||||
|
free(xfr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
xfr->task_probe->workernum = -1;
|
||||||
|
xfr->task_transfer = (struct auth_transfer*)calloc(1,
|
||||||
|
sizeof(struct auth_transfer));
|
||||||
|
if(!xfr->task_transfer) {
|
||||||
|
free(xfr->task_probe);
|
||||||
|
free(xfr->task_nextprobe);
|
||||||
|
free(xfr->name);
|
||||||
|
free(xfr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
xfr->task_transfer->workernum = -1;
|
||||||
|
|
||||||
|
lock_basic_init(&xfr->lock);
|
||||||
|
lock_protect(&xfr->lock, xfr, sizeof(*xfr));
|
||||||
|
lock_protect(&xfr->lock, &xfr->task_nextprobe->workernum,
|
||||||
|
sizeof(xfr->task_nextprobe->workernum));
|
||||||
|
lock_protect(&xfr->lock, &xfr->task_probe->workernum,
|
||||||
|
sizeof(xfr->task_probe->workernum));
|
||||||
|
lock_protect(&xfr->lock, &xfr->task_transfer->workernum,
|
||||||
|
sizeof(xfr->task_transfer->workernum));
|
||||||
|
return xfr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup auth_xfer zone
|
||||||
|
* This populates the have_zone, soa values, next_probe and so on times.
|
||||||
|
* Doesn't do network traffic yet, sets the timeout.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
auth_xfer_setup(struct auth_zone* z, struct auth_xfer* x, struct module_env* env)
|
||||||
|
{
|
||||||
|
if(!z || !x) return 1;
|
||||||
|
if(!xfr_find_soa(z, x)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* nextprobe setup */
|
||||||
|
x->task_nextprobe->next_probe = 0;
|
||||||
|
if(x->have_zone)
|
||||||
|
x->task_nextprobe->lease_time = *env->now;
|
||||||
|
/* nothing for probe and transfer tasks */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create auth_xfer structure.
|
||||||
|
* This populates the have_zone, soa values, next_probe and so on times.
|
||||||
|
* and sets the timeout, if a zone transfer is needed a short timeout is set.
|
||||||
|
* For that the auth_zone itself must exist (and read in zonefile)
|
||||||
|
* returns false on alloc failure. */
|
||||||
|
struct auth_xfer*
|
||||||
|
auth_xfer_create(struct auth_zones* az, struct auth_zone* z)
|
||||||
|
{
|
||||||
|
struct auth_xfer* xfr;
|
||||||
|
|
||||||
|
/* malloc it */
|
||||||
|
xfr = auth_xfer_new(z);
|
||||||
|
if(!xfr) {
|
||||||
|
log_err("malloc failure");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* insert in tree */
|
||||||
|
(void)rbtree_insert(&az->xtree, &xfr->node);
|
||||||
|
return xfr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** create new auth_master structure */
|
||||||
|
static struct auth_master*
|
||||||
|
auth_master_new(struct auth_master*** list)
|
||||||
|
{
|
||||||
|
struct auth_master *m;
|
||||||
|
m = (struct auth_master*)calloc(1, sizeof(*m));
|
||||||
|
if(!m) {
|
||||||
|
log_err("malloc failure");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* set first pointer to m, or next pointer of previous element to m */
|
||||||
|
(**list) = m;
|
||||||
|
/* store m's next pointer as future point to store at */
|
||||||
|
(*list) = &(m->next);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xfer_set_masters(struct auth_master** list, struct config_auth* c)
|
||||||
|
{
|
||||||
|
struct auth_master* m;
|
||||||
|
struct config_strlist* p;
|
||||||
|
/* list points to the first, or next pointer for the new element */
|
||||||
|
while(*list) {
|
||||||
|
list = &( (*list)->next );
|
||||||
|
}
|
||||||
|
for(p = c->masters; p; p = p->next) {
|
||||||
|
m = auth_master_new(&list);
|
||||||
|
m->ixfr = 1;
|
||||||
|
m->host = strdup(p->str);
|
||||||
|
if(!m->host) {
|
||||||
|
log_err("malloc failure");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(p = c->urls; p; p = p->next) {
|
||||||
|
m = auth_master_new(&list);
|
||||||
|
m->http = 1;
|
||||||
|
/* TODO parse url, get host, file */
|
||||||
|
m->host = strdup(p->str);
|
||||||
|
if(!m->host) {
|
||||||
|
log_err("malloc failure");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,17 +48,33 @@
|
||||||
struct ub_packed_rrset_key;
|
struct ub_packed_rrset_key;
|
||||||
struct regional;
|
struct regional;
|
||||||
struct config_file;
|
struct config_file;
|
||||||
|
struct config_auth;
|
||||||
struct query_info;
|
struct query_info;
|
||||||
struct dns_msg;
|
struct dns_msg;
|
||||||
|
struct edns_data;
|
||||||
|
struct module_env;
|
||||||
|
struct worker;
|
||||||
|
struct comm_point;
|
||||||
|
struct comm_timer;
|
||||||
|
struct auth_rrset;
|
||||||
|
struct auth_nextprobe;
|
||||||
|
struct auth_probe;
|
||||||
|
struct auth_transfer;
|
||||||
|
struct auth_master;
|
||||||
|
struct auth_chunk;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authoritative zones, shared.
|
* Authoritative zones, shared.
|
||||||
*/
|
*/
|
||||||
struct auth_zones {
|
struct auth_zones {
|
||||||
/** lock on the authzone tree */
|
/** lock on the authzone trees */
|
||||||
lock_rw_type lock;
|
lock_rw_type lock;
|
||||||
/** rbtree of struct auth_zone */
|
/** rbtree of struct auth_zone */
|
||||||
rbtree_type ztree;
|
rbtree_type ztree;
|
||||||
|
/** rbtree of struct auth_xfer */
|
||||||
|
rbtree_type xtree;
|
||||||
|
/** do we have downstream enabled */
|
||||||
|
int have_downstream;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -89,10 +105,21 @@ struct auth_zone {
|
||||||
* rbtree of struct auth_data */
|
* rbtree of struct auth_data */
|
||||||
rbtree_type data;
|
rbtree_type data;
|
||||||
|
|
||||||
/* zonefile name (or NULL for no zonefile) */
|
/** zonefile name (or NULL for no zonefile) */
|
||||||
char* zonefile;
|
char* zonefile;
|
||||||
/* fallback to the internet on failure or ttl-expiry of auth zone */
|
/** fallback to the internet on failure or ttl-expiry of auth zone */
|
||||||
int fallback_enabled;
|
int fallback_enabled;
|
||||||
|
/** the zone has expired (enabled by the xfer worker), fallback
|
||||||
|
* happens if that option is enabled. */
|
||||||
|
int zone_expired;
|
||||||
|
/** zone is a slave zone (it has masters) */
|
||||||
|
int zone_is_slave;
|
||||||
|
/** for downstream: this zone answers queries towards the downstream
|
||||||
|
* clients */
|
||||||
|
int for_downstream;
|
||||||
|
/** for upstream: this zone answers queries that unbound intends to
|
||||||
|
* send upstream. */
|
||||||
|
int for_upstream;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -127,6 +154,217 @@ struct auth_rrset {
|
||||||
struct packed_rrset_data* data;
|
struct packed_rrset_data* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authoritative zone transfer structure.
|
||||||
|
* Create and destroy needs the auth_zones* biglock.
|
||||||
|
* The structure consists of different tasks. Each can be unowned (-1) or
|
||||||
|
* owner by a worker (worker-num). A worker can pick up a task and then do
|
||||||
|
* it. This means the events (timeouts, sockets) are for that worker.
|
||||||
|
*
|
||||||
|
* (move this to tasks).
|
||||||
|
* They don't have locks themselves, the worker (that owns it) uses it,
|
||||||
|
* also as part of callbacks, hence it has separate zonename pointers for
|
||||||
|
* lookup in the main zonetree. If the zone has no transfers, this
|
||||||
|
* structure is not created.
|
||||||
|
*/
|
||||||
|
struct auth_xfer {
|
||||||
|
/** rbtree node, key is name and class */
|
||||||
|
rbnode_type node;
|
||||||
|
|
||||||
|
/** lock on this structure, and on the workernum elements of the
|
||||||
|
* tasks. First hold the tree-lock in auth_zones, find the auth_xfer,
|
||||||
|
* lock this lock. Then a worker can reassign itself to fill up
|
||||||
|
* one of the tasks.
|
||||||
|
* Once it has the task assigned to it, the worker can access the
|
||||||
|
* other elements of the task structure without a lock, because that
|
||||||
|
* is necessary for the eventloop and callbacks from that. */
|
||||||
|
lock_basic_type lock;
|
||||||
|
|
||||||
|
/** zone name, in uncompressed wireformat */
|
||||||
|
uint8_t* name;
|
||||||
|
/** length of zone name */
|
||||||
|
size_t namelen;
|
||||||
|
/** number of labels in zone name */
|
||||||
|
int namelabs;
|
||||||
|
/** the class of this zone, in host byteorder.
|
||||||
|
* uses 'dclass' to not conflict with c++ keyword class. */
|
||||||
|
uint16_t dclass;
|
||||||
|
|
||||||
|
/** task to wait for next-probe-timeout,
|
||||||
|
* once timeouted, see if a SOA probe is needed, or already
|
||||||
|
* in progress */
|
||||||
|
struct auth_nextprobe* task_nextprobe;
|
||||||
|
|
||||||
|
/** task for SOA probe. Check if the zone can be updated */
|
||||||
|
struct auth_probe* task_probe;
|
||||||
|
|
||||||
|
/** Task for transfer. Transferring and updating the zone. This
|
||||||
|
* includes trying (potentially) several upstream masters. Downloading
|
||||||
|
* and storing the zone */
|
||||||
|
struct auth_transfer* task_transfer;
|
||||||
|
|
||||||
|
/** a notify was received, but a zone transfer or probe was already
|
||||||
|
* acted on.
|
||||||
|
* However, the zone transfer could signal a newer serial number.
|
||||||
|
* The serial number of that notify is saved below. The transfer and
|
||||||
|
* probe tasks should check this once done to see if they need to
|
||||||
|
* restart the transfer task for the newer notify serial.
|
||||||
|
* Hold the lock to access this member (and the serial).
|
||||||
|
*/
|
||||||
|
int notify_received;
|
||||||
|
/** serial number of the notify */
|
||||||
|
uint32_t notify_serial;
|
||||||
|
|
||||||
|
/* protected by the lock on the structure, information about
|
||||||
|
* the loaded authority zone. */
|
||||||
|
/** is the zone currently considered expired? after expiry also older
|
||||||
|
* serial numbers are allowed (not just newer) */
|
||||||
|
int zone_expired;
|
||||||
|
/** do we have a zone (if 0, no zone data at all) */
|
||||||
|
int have_zone;
|
||||||
|
|
||||||
|
/** current serial (from SOA), if we have no zone, 0 */
|
||||||
|
uint32_t serial;
|
||||||
|
/** retry time (from SOA), time to wait with next_probe
|
||||||
|
* if no master responds */
|
||||||
|
time_t retry;
|
||||||
|
/** refresh time (from SOA), time to wait with next_probe
|
||||||
|
* if everything is fine */
|
||||||
|
time_t refresh;
|
||||||
|
/** expiry time (from SOA), time until zone data is not considered
|
||||||
|
* valid any more, if no master responds within this time, either
|
||||||
|
* with the current zone or a new zone. */
|
||||||
|
time_t expiry;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The next probe task.
|
||||||
|
* This task consists of waiting for the probetimeout. It is a task because
|
||||||
|
* it needs an event in the eventtable. Once the timeout has passed, that
|
||||||
|
* worker can (potentially) become the auth_probe worker, or if another worker
|
||||||
|
* is already doing that, do nothing. Tasks becomes unowned.
|
||||||
|
* The probe worker, if it detects nothing has to be done picks up this task,
|
||||||
|
* if unowned.
|
||||||
|
*/
|
||||||
|
struct auth_nextprobe {
|
||||||
|
/** worker num (or -1 unowned) that is performing this task */
|
||||||
|
int workernum;
|
||||||
|
/* Worker pointer. Used by the worker during callbacks. */
|
||||||
|
struct worker* worker;
|
||||||
|
|
||||||
|
/** Timeout for next probe (for SOA) */
|
||||||
|
time_t next_probe;
|
||||||
|
/** zone lease start time (start+expiry is expiration time).
|
||||||
|
* this is renewed every SOA probe and transfer. On zone load
|
||||||
|
* from zonefile it is also set (with probe set soon to check) */
|
||||||
|
time_t lease_time;
|
||||||
|
/** timeout callback for next_probe or expiry(if that is sooner).
|
||||||
|
* it is on the worker's event_base */
|
||||||
|
struct comm_timer* timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The probe task.
|
||||||
|
* Send a SOA UDP query to see if the zone needs to be updated (or similar,
|
||||||
|
* potential, HTTP probe query) and check serial number.
|
||||||
|
* If yes, start the auth_transfer task. If no, make sure auth_nextprobe
|
||||||
|
* timeout wait task is running.
|
||||||
|
* Needs to be a task, because the UDP query needs an event entry.
|
||||||
|
* This task could also be started by eg. a NOTIFY being received, even though
|
||||||
|
* another worker is performing the nextprobe task (and that worker keeps
|
||||||
|
* waiting uninterrupted).
|
||||||
|
*/
|
||||||
|
struct auth_probe {
|
||||||
|
/** worker num (or -1 unowned) that is performing this task */
|
||||||
|
int workernum;
|
||||||
|
/* Worker pointer. Used by the worker during callbacks. */
|
||||||
|
struct worker* worker;
|
||||||
|
|
||||||
|
/** list of upstream masters for this zone, from config */
|
||||||
|
struct auth_master* masters;
|
||||||
|
|
||||||
|
/** once notified, or the timeout has been reached. a scan starts. */
|
||||||
|
/** the scan specific target (notify source), or NULL if none */
|
||||||
|
struct auth_master* scan_specific;
|
||||||
|
/** scan tries all the upstream masters. the scan current target.
|
||||||
|
* or NULL if not working on sequential scan */
|
||||||
|
struct auth_master* scan_target;
|
||||||
|
|
||||||
|
/** the SOA probe udp event.
|
||||||
|
* on the workers event base. */
|
||||||
|
struct comm_point* cp;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transfer task.
|
||||||
|
* Once done, make sure the nextprobe waiting task is running, whether done
|
||||||
|
* with failure or success. If failure, use shorter timeout for wait time.
|
||||||
|
*/
|
||||||
|
struct auth_transfer {
|
||||||
|
/** worker num (or -1 unowned) that is performing this task */
|
||||||
|
int workernum;
|
||||||
|
/* Worker pointer. Used by the worker during callbacks. */
|
||||||
|
struct worker* worker;
|
||||||
|
|
||||||
|
/** xfer data that has been transferred, the data is applied
|
||||||
|
* once the transfer has completed correctly */
|
||||||
|
struct auth_chunk* chunks_first;
|
||||||
|
/** last element in chunks list (to append new data at the end) */
|
||||||
|
struct auth_chunk* chunks_last;
|
||||||
|
|
||||||
|
/** list of upstream masters for this zone, from config */
|
||||||
|
struct auth_master* masters;
|
||||||
|
|
||||||
|
/** once notified, or the timeout has been reached. a scan starts. */
|
||||||
|
/** the scan specific target (notify source), or NULL if none */
|
||||||
|
struct auth_master* scan_specific;
|
||||||
|
/** scan tries all the upstream masters. the scan current target.
|
||||||
|
* or NULL if not working on sequential scan */
|
||||||
|
struct auth_master* scan_target;
|
||||||
|
/** the zone transfer in progress (or NULL if in scan). It is
|
||||||
|
* from this master */
|
||||||
|
struct auth_master* master;
|
||||||
|
|
||||||
|
/** failed ixfr transfer, retry with axfr (to the current master),
|
||||||
|
* the IXFR was 'REFUSED', 'SERVFAIL', 'NOTIMPL' or the contents of
|
||||||
|
* the IXFR did not apply cleanly (out of sync, delete of nonexistent
|
||||||
|
* data or add of duplicate data). Flag is cleared once the retry
|
||||||
|
* with axfr is done. */
|
||||||
|
int ixfr_fail;
|
||||||
|
|
||||||
|
/** the transfer (TCP) to the master.
|
||||||
|
* on the workers event base. */
|
||||||
|
struct comm_point* cp;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** auth zone master upstream, and the config settings for it */
|
||||||
|
struct auth_master {
|
||||||
|
/** next master in list */
|
||||||
|
struct auth_master* next;
|
||||||
|
/** master IP address (and port), or hostname, string */
|
||||||
|
char* host;
|
||||||
|
/** for http, filename */
|
||||||
|
char* file;
|
||||||
|
/** use HTTP for this master */
|
||||||
|
int http;
|
||||||
|
/** use IXFR for this master */
|
||||||
|
int ixfr;
|
||||||
|
/** use ssl for channel */
|
||||||
|
int ssl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** auth zone master zone transfer data chunk */
|
||||||
|
struct auth_chunk {
|
||||||
|
/** next chunk in list */
|
||||||
|
struct auth_chunk* next;
|
||||||
|
/** the data from this chunk, this is what was received.
|
||||||
|
* for an IXFR that means results from comm_net tcp actions,
|
||||||
|
* packets. also for an AXFR. For HTTP a zonefile chunk. */
|
||||||
|
uint8_t* data;
|
||||||
|
/** length of allocated data */
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create auth zones structure
|
* Create auth zones structure
|
||||||
*/
|
*/
|
||||||
|
|
@ -135,7 +373,7 @@ struct auth_zones* auth_zones_create(void);
|
||||||
/**
|
/**
|
||||||
* Apply configuration to auth zones. Reads zonefiles.
|
* Apply configuration to auth zones. Reads zonefiles.
|
||||||
*/
|
*/
|
||||||
int auth_zones_apply_config(struct auth_zones* az, struct config_file* cfg);
|
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete auth zones structure
|
* Delete auth zones structure
|
||||||
|
|
@ -170,6 +408,20 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
||||||
struct regional* region, struct dns_msg** msg, int* fallback,
|
struct regional* region, struct dns_msg** msg, int* fallback,
|
||||||
uint8_t* dp_nm, size_t dp_nmlen);
|
uint8_t* dp_nm, size_t dp_nmlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer query from auth zone. Create authoritative answer.
|
||||||
|
* @param az: auth zones structure.
|
||||||
|
* @param env: the module environment.
|
||||||
|
* @param qinfo: query info (parsed).
|
||||||
|
* @param edns: edns info (parsed).
|
||||||
|
* @param buf: buffer with query ID and flags, also for reply.
|
||||||
|
* @param temp: temporary storage region.
|
||||||
|
* @return false if not answered
|
||||||
|
*/
|
||||||
|
int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||||
|
struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
|
||||||
|
struct regional* temp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the auth zone that is above the given qname.
|
* Find the auth zone that is above the given qname.
|
||||||
* Return NULL when there is no auth_zone above the give name, otherwise
|
* Return NULL when there is no auth_zone above the give name, otherwise
|
||||||
|
|
@ -185,6 +437,11 @@ struct auth_zone* auth_zones_find_zone(struct auth_zones* az,
|
||||||
struct auth_zone* auth_zone_find(struct auth_zones* az, uint8_t* nm,
|
struct auth_zone* auth_zone_find(struct auth_zones* az, uint8_t* nm,
|
||||||
size_t nmlen, uint16_t dclass);
|
size_t nmlen, uint16_t dclass);
|
||||||
|
|
||||||
|
/** find an xfer zone by name (exact match by name or NULL returned) */
|
||||||
|
struct auth_xfer* auth_xfer_find(struct auth_zones* az, uint8_t* nm,
|
||||||
|
size_t nmlen, uint16_t dclass);
|
||||||
|
|
||||||
|
|
||||||
/** create an auth zone. returns wrlocked zone. caller must have wrlock
|
/** create an auth zone. returns wrlocked zone. caller must have wrlock
|
||||||
* on az. returns NULL on malloc failure */
|
* on az. returns NULL on malloc failure */
|
||||||
struct auth_zone* auth_zone_create(struct auth_zones* az, uint8_t* nm,
|
struct auth_zone* auth_zone_create(struct auth_zones* az, uint8_t* nm,
|
||||||
|
|
@ -206,4 +463,41 @@ int auth_zone_cmp(const void* z1, const void* z2);
|
||||||
/** compare auth_data for sorted rbtree */
|
/** compare auth_data for sorted rbtree */
|
||||||
int auth_data_cmp(const void* z1, const void* z2);
|
int auth_data_cmp(const void* z1, const void* z2);
|
||||||
|
|
||||||
|
/** compare auth_xfer for sorted rbtree */
|
||||||
|
int auth_xfer_cmp(const void* z1, const void* z2);
|
||||||
|
|
||||||
|
/** Create auth_xfer structure.
|
||||||
|
* Caller must have wrlock on az. Returns locked xfer zone.
|
||||||
|
* @param az: zones structure.
|
||||||
|
* @param z: zone with name and class
|
||||||
|
* @return xfer zone or NULL
|
||||||
|
*/
|
||||||
|
struct auth_xfer* auth_xfer_create(struct auth_zones* az, struct auth_zone* z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set masters in auth xfer structure from config.
|
||||||
|
* @param list: pointer to start of list. The malloced list is returned here.
|
||||||
|
* @param c: the config items to copy over.
|
||||||
|
* @return false on failure.
|
||||||
|
*/
|
||||||
|
int xfer_set_masters(struct auth_master** list, struct config_auth* c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup auth_xfer zone. Populates timeouts.
|
||||||
|
* @param z: locked by caller, and modified for setup
|
||||||
|
* @param x: locked by caller, and modified, timers and timeouts.
|
||||||
|
* @param env: module env with time.
|
||||||
|
* @return false on failure.
|
||||||
|
*/
|
||||||
|
int auth_xfer_setup(struct auth_zone* z, struct auth_xfer* xfr,
|
||||||
|
struct module_env* env);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup all zones
|
||||||
|
* @param az: auth zones structure
|
||||||
|
* @param env: module env with time.
|
||||||
|
* @return false on failure.
|
||||||
|
*/
|
||||||
|
int auth_zones_setup_zones(struct auth_zones* az, struct module_env* env);
|
||||||
|
|
||||||
#endif /* SERVICES_AUTHZONE_H */
|
#endif /* SERVICES_AUTHZONE_H */
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@
|
||||||
#include "validator/validator.h"
|
#include "validator/validator.h"
|
||||||
#include "services/localzone.h"
|
#include "services/localzone.h"
|
||||||
#include "services/view.h"
|
#include "services/view.h"
|
||||||
|
#include "services/authzone.h"
|
||||||
#include "respip/respip.h"
|
#include "respip/respip.h"
|
||||||
#include "sldns/sbuffer.h"
|
#include "sldns/sbuffer.h"
|
||||||
#ifdef HAVE_GETOPT_H
|
#ifdef HAVE_GETOPT_H
|
||||||
|
|
@ -573,6 +574,17 @@ check_hints(struct config_file* cfg)
|
||||||
hints_delete(hints);
|
hints_delete(hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** check auth zones */
|
||||||
|
static void
|
||||||
|
check_auth(struct config_file* cfg)
|
||||||
|
{
|
||||||
|
struct auth_zones* az = auth_zones_create();
|
||||||
|
if(!az || !auth_zones_apply_cfg(az, cfg)) {
|
||||||
|
fatal_exit("Could not setup authority zones");
|
||||||
|
}
|
||||||
|
auth_zones_delete(az);
|
||||||
|
}
|
||||||
|
|
||||||
/** check config file */
|
/** check config file */
|
||||||
static void
|
static void
|
||||||
checkconf(const char* cfgfile, const char* opt, int final)
|
checkconf(const char* cfgfile, const char* opt, int final)
|
||||||
|
|
@ -607,6 +619,7 @@ checkconf(const char* cfgfile, const char* opt, int final)
|
||||||
#endif
|
#endif
|
||||||
check_fwd(cfg);
|
check_fwd(cfg);
|
||||||
check_hints(cfg);
|
check_hints(cfg);
|
||||||
|
check_auth(cfg);
|
||||||
printf("unbound-checkconf: no errors in %s\n", cfgfile);
|
printf("unbound-checkconf: no errors in %s\n", cfgfile);
|
||||||
config_delete(cfg);
|
config_delete(cfg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,7 @@ config_create(void)
|
||||||
cfg->out_ifs = NULL;
|
cfg->out_ifs = NULL;
|
||||||
cfg->stubs = NULL;
|
cfg->stubs = NULL;
|
||||||
cfg->forwards = NULL;
|
cfg->forwards = NULL;
|
||||||
|
cfg->auths = NULL;
|
||||||
#ifdef CLIENT_SUBNET
|
#ifdef CLIENT_SUBNET
|
||||||
cfg->client_subnet = NULL;
|
cfg->client_subnet = NULL;
|
||||||
cfg->client_subnet_zone = NULL;
|
cfg->client_subnet_zone = NULL;
|
||||||
|
|
@ -634,7 +635,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||||
* interface, outgoing-interface, access-control,
|
* interface, outgoing-interface, access-control,
|
||||||
* stub-zone, name, stub-addr, stub-host, stub-prime
|
* stub-zone, name, stub-addr, stub-host, stub-prime
|
||||||
* forward-first, stub-first, forward-ssl-upstream,
|
* forward-first, stub-first, forward-ssl-upstream,
|
||||||
* stub-ssl-upstream, forward-zone,
|
* stub-ssl-upstream, forward-zone, auth-zone
|
||||||
* name, forward-addr, forward-host,
|
* name, forward-addr, forward-host,
|
||||||
* ratelimit-for-domain, ratelimit-below-domain,
|
* ratelimit-for-domain, ratelimit-below-domain,
|
||||||
* local-zone-tag, access-control-view,
|
* local-zone-tag, access-control-view,
|
||||||
|
|
@ -1164,6 +1165,28 @@ config_deltrplstrlist(struct config_str3list* p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
config_delauth(struct config_auth* p)
|
||||||
|
{
|
||||||
|
if(!p) return;
|
||||||
|
free(p->name);
|
||||||
|
config_delstrlist(p->masters);
|
||||||
|
config_delstrlist(p->urls);
|
||||||
|
free(p->zonefile);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
config_delauths(struct config_auth* p)
|
||||||
|
{
|
||||||
|
struct config_auth* np;
|
||||||
|
while(p) {
|
||||||
|
np = p->next;
|
||||||
|
config_delauth(p);
|
||||||
|
p = np;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
config_delstub(struct config_stub* p)
|
config_delstub(struct config_stub* p)
|
||||||
{
|
{
|
||||||
|
|
@ -1249,6 +1272,7 @@ config_delete(struct config_file* cfg)
|
||||||
config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
|
config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
|
||||||
config_delstubs(cfg->stubs);
|
config_delstubs(cfg->stubs);
|
||||||
config_delstubs(cfg->forwards);
|
config_delstubs(cfg->forwards);
|
||||||
|
config_delauths(cfg->auths);
|
||||||
config_delviews(cfg->views);
|
config_delviews(cfg->views);
|
||||||
config_delstrlist(cfg->donotqueryaddrs);
|
config_delstrlist(cfg->donotqueryaddrs);
|
||||||
config_delstrlist(cfg->root_hints);
|
config_delstrlist(cfg->root_hints);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
#ifndef UTIL_CONFIG_FILE_H
|
#ifndef UTIL_CONFIG_FILE_H
|
||||||
#define UTIL_CONFIG_FILE_H
|
#define UTIL_CONFIG_FILE_H
|
||||||
struct config_stub;
|
struct config_stub;
|
||||||
|
struct config_auth;
|
||||||
struct config_view;
|
struct config_view;
|
||||||
struct config_strlist;
|
struct config_strlist;
|
||||||
struct config_str2list;
|
struct config_str2list;
|
||||||
|
|
@ -170,6 +171,8 @@ struct config_file {
|
||||||
struct config_stub* stubs;
|
struct config_stub* stubs;
|
||||||
/** the forward zone definitions, linked list */
|
/** the forward zone definitions, linked list */
|
||||||
struct config_stub* forwards;
|
struct config_stub* forwards;
|
||||||
|
/** the auth zone definitions, linked list */
|
||||||
|
struct config_auth* auths;
|
||||||
/** the views definitions, linked list */
|
/** the views definitions, linked list */
|
||||||
struct config_view* views;
|
struct config_view* views;
|
||||||
/** list of donotquery addresses, linked list */
|
/** list of donotquery addresses, linked list */
|
||||||
|
|
@ -530,6 +533,26 @@ struct config_stub {
|
||||||
int ssl_upstream;
|
int ssl_upstream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auth config options
|
||||||
|
*/
|
||||||
|
struct config_auth {
|
||||||
|
/** next in list */
|
||||||
|
struct config_auth* next;
|
||||||
|
/** domain name (in text) of the auth apex domain */
|
||||||
|
char* name;
|
||||||
|
/** list of masters */
|
||||||
|
struct config_strlist* masters;
|
||||||
|
/** list of urls */
|
||||||
|
struct config_strlist* urls;
|
||||||
|
/** zonefile (or NULL) */
|
||||||
|
char* zonefile;
|
||||||
|
/** provide downstream answers */
|
||||||
|
int for_downstream;
|
||||||
|
/** provide upstream answers */
|
||||||
|
int for_upstream;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View config options
|
* View config options
|
||||||
*/
|
*/
|
||||||
|
|
@ -820,6 +843,18 @@ void config_delstub(struct config_stub* p);
|
||||||
*/
|
*/
|
||||||
void config_delstubs(struct config_stub* list);
|
void config_delstubs(struct config_stub* list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an auth item
|
||||||
|
* @param p: auth item
|
||||||
|
*/
|
||||||
|
void config_delauth(struct config_auth* p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete items in config auth list.
|
||||||
|
* @param list: list.
|
||||||
|
*/
|
||||||
|
void config_delauths(struct config_auth* list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a view item
|
* Delete a view item
|
||||||
* @param p: view item
|
* @param p: view item
|
||||||
|
|
|
||||||
3772
util/configlexer.c
3772
util/configlexer.c
File diff suppressed because it is too large
Load diff
|
|
@ -295,6 +295,12 @@ forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) }
|
||||||
forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) }
|
forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) }
|
||||||
forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) }
|
forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) }
|
||||||
forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
|
forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
|
||||||
|
auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) }
|
||||||
|
zonefile{COLON} { YDVAR(1, VAR_ZONEFILE) }
|
||||||
|
master{COLON} { YDVAR(1, VAR_MASTER) }
|
||||||
|
url{COLON} { YDVAR(1, VAR_URL) }
|
||||||
|
for-downstream{COLON} { YDVAR(1, VAR_FOR_DOWNSTREAM) }
|
||||||
|
for-upstream{COLON} { YDVAR(1, VAR_FOR_UPSTREAM) }
|
||||||
view{COLON} { YDVAR(0, VAR_VIEW) }
|
view{COLON} { YDVAR(0, VAR_VIEW) }
|
||||||
view-first{COLON} { YDVAR(1, VAR_VIEW_FIRST) }
|
view-first{COLON} { YDVAR(1, VAR_VIEW_FIRST) }
|
||||||
do-not-query-address{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) }
|
do-not-query-address{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) }
|
||||||
|
|
|
||||||
2288
util/configparser.c
2288
util/configparser.c
File diff suppressed because it is too large
Load diff
|
|
@ -266,7 +266,13 @@ extern int yydebug;
|
||||||
VAR_CACHEDB = 476,
|
VAR_CACHEDB = 476,
|
||||||
VAR_CACHEDB_BACKEND = 477,
|
VAR_CACHEDB_BACKEND = 477,
|
||||||
VAR_CACHEDB_SECRETSEED = 478,
|
VAR_CACHEDB_SECRETSEED = 478,
|
||||||
VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM = 479
|
VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM = 479,
|
||||||
|
VAR_FOR_UPSTREAM = 480,
|
||||||
|
VAR_AUTH_ZONE = 481,
|
||||||
|
VAR_ZONEFILE = 482,
|
||||||
|
VAR_MASTER = 483,
|
||||||
|
VAR_URL = 484,
|
||||||
|
VAR_FOR_DOWNSTREAM = 485
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
/* Tokens. */
|
/* Tokens. */
|
||||||
|
|
@ -492,6 +498,12 @@ extern int yydebug;
|
||||||
#define VAR_CACHEDB_BACKEND 477
|
#define VAR_CACHEDB_BACKEND 477
|
||||||
#define VAR_CACHEDB_SECRETSEED 478
|
#define VAR_CACHEDB_SECRETSEED 478
|
||||||
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 479
|
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 479
|
||||||
|
#define VAR_FOR_UPSTREAM 480
|
||||||
|
#define VAR_AUTH_ZONE 481
|
||||||
|
#define VAR_ZONEFILE 482
|
||||||
|
#define VAR_MASTER 483
|
||||||
|
#define VAR_URL 484
|
||||||
|
#define VAR_FOR_DOWNSTREAM 485
|
||||||
|
|
||||||
/* Value type. */
|
/* Value type. */
|
||||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||||
|
|
@ -502,7 +514,7 @@ union YYSTYPE
|
||||||
|
|
||||||
char* str;
|
char* str;
|
||||||
|
|
||||||
#line 506 "util/configparser.h" /* yacc.c:1909 */
|
#line 518 "util/configparser.h" /* yacc.c:1909 */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union YYSTYPE YYSTYPE;
|
typedef union YYSTYPE YYSTYPE;
|
||||||
|
|
|
||||||
|
|
@ -152,16 +152,16 @@ extern struct config_parser_state* cfg_parser;
|
||||||
%token VAR_IPSECMOD_ENABLED VAR_IPSECMOD_HOOK VAR_IPSECMOD_IGNORE_BOGUS
|
%token VAR_IPSECMOD_ENABLED VAR_IPSECMOD_HOOK VAR_IPSECMOD_IGNORE_BOGUS
|
||||||
%token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT
|
%token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT
|
||||||
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
|
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
|
||||||
%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM
|
%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM
|
||||||
|
%token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
|
||||||
|
|
||||||
%%
|
%%
|
||||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||||
toplevelvar: serverstart contents_server | stubstart contents_stub |
|
toplevelvar: serverstart contents_server | stubstart contents_stub |
|
||||||
forwardstart contents_forward | pythonstart contents_py |
|
forwardstart contents_forward | pythonstart contents_py |
|
||||||
rcstart contents_rc | dtstart contents_dt | viewstart
|
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
|
||||||
contents_view |
|
dnscstart contents_dnsc | cachedbstart contents_cachedb |
|
||||||
dnscstart contents_dnsc |
|
authstart contents_auth
|
||||||
cachedbstart contents_cachedb
|
|
||||||
;
|
;
|
||||||
|
|
||||||
/* server: declaration */
|
/* server: declaration */
|
||||||
|
|
@ -297,6 +297,26 @@ contents_view: contents_view content_view
|
||||||
content_view: view_name | view_local_zone | view_local_data | view_first |
|
content_view: view_name | view_local_zone | view_local_data | view_first |
|
||||||
view_response_ip | view_response_ip_data | view_local_data_ptr
|
view_response_ip | view_response_ip_data | view_local_data_ptr
|
||||||
;
|
;
|
||||||
|
authstart: VAR_AUTH_ZONE
|
||||||
|
{
|
||||||
|
struct config_auth* s;
|
||||||
|
OUTYY(("\nP(auth_zone:)\n"));
|
||||||
|
s = (struct config_auth*)calloc(1, sizeof(struct config_auth));
|
||||||
|
if(s) {
|
||||||
|
s->next = cfg_parser->cfg->auths;
|
||||||
|
cfg_parser->cfg->auths = s;
|
||||||
|
/* defaults for auth zone */
|
||||||
|
s->for_downstream = 1;
|
||||||
|
s->for_upstream = 1;
|
||||||
|
} else
|
||||||
|
yyerror("out of memory");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
contents_auth: contents_auth content_auth
|
||||||
|
| ;
|
||||||
|
content_auth: auth_name | auth_zonefile | auth_master | auth_url |
|
||||||
|
auth_for_downstream | auth_for_upstream
|
||||||
|
;
|
||||||
server_num_threads: VAR_NUM_THREADS STRING_ARG
|
server_num_threads: VAR_NUM_THREADS STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(server_num_threads:%s)\n", $2));
|
OUTYY(("P(server_num_threads:%s)\n", $2));
|
||||||
|
|
@ -1999,6 +2019,57 @@ forward_ssl_upstream: VAR_FORWARD_SSL_UPSTREAM STRING_ARG
|
||||||
free($2);
|
free($2);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
auth_name: VAR_NAME STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(name:%s)\n", $2));
|
||||||
|
if(cfg_parser->cfg->auths->name)
|
||||||
|
yyerror("auth name override, there must be one name "
|
||||||
|
"for one auth-zone");
|
||||||
|
free(cfg_parser->cfg->auths->name);
|
||||||
|
cfg_parser->cfg->auths->name = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
auth_zonefile: VAR_ZONEFILE STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(zonefile:%s)\n", $2));
|
||||||
|
free(cfg_parser->cfg->auths->zonefile);
|
||||||
|
cfg_parser->cfg->auths->zonefile = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
auth_master: VAR_MASTER STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(master:%s)\n", $2));
|
||||||
|
if(!cfg_strlist_insert(&cfg_parser->cfg->auths->masters, $2))
|
||||||
|
yyerror("out of memory");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
auth_url: VAR_URL STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(url:%s)\n", $2));
|
||||||
|
if(!cfg_strlist_insert(&cfg_parser->cfg->auths->urls, $2))
|
||||||
|
yyerror("out of memory");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
auth_for_downstream: VAR_FOR_DOWNSTREAM STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(for-downstream:%s)\n", $2));
|
||||||
|
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||||
|
yyerror("expected yes or no.");
|
||||||
|
else cfg_parser->cfg->auths->for_downstream =
|
||||||
|
(strcmp($2, "yes")==0);
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
auth_for_upstream: VAR_FOR_UPSTREAM STRING_ARG
|
||||||
|
{
|
||||||
|
OUTYY(("P(for-upstream:%s)\n", $2));
|
||||||
|
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||||
|
yyerror("expected yes or no.");
|
||||||
|
else cfg_parser->cfg->auths->for_upstream =
|
||||||
|
(strcmp($2, "yes")==0);
|
||||||
|
free($2);
|
||||||
|
}
|
||||||
|
;
|
||||||
view_name: VAR_NAME STRING_ARG
|
view_name: VAR_NAME STRING_ARG
|
||||||
{
|
{
|
||||||
OUTYY(("P(name:%s)\n", $2));
|
OUTYY(("P(name:%s)\n", $2));
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,7 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
|
||||||
else if(fptr == &view_cmp) return 1;
|
else if(fptr == &view_cmp) return 1;
|
||||||
else if(fptr == &auth_zone_cmp) return 1;
|
else if(fptr == &auth_zone_cmp) return 1;
|
||||||
else if(fptr == &auth_data_cmp) return 1;
|
else if(fptr == &auth_data_cmp) return 1;
|
||||||
|
else if(fptr == &auth_xfer_cmp) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue