Upgrade Unbound to 1.6.0. More to follow.
This commit is contained in:
commit
bc89214039
1
contrib/unbound/.gitattributes
vendored
Normal file
1
contrib/unbound/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
testdata/*.[0-9] linguist-documentation
|
@ -101,7 +101,7 @@ util/data/msgreply.c util/data/packed_rrset.c iterator/iterator.c \
|
||||
iterator/iter_delegpt.c iterator/iter_donotq.c iterator/iter_fwd.c \
|
||||
iterator/iter_hints.c iterator/iter_priv.c iterator/iter_resptype.c \
|
||||
iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \
|
||||
services/localzone.c services/mesh.c services/modstack.c \
|
||||
services/localzone.c services/mesh.c services/modstack.c services/view.c \
|
||||
services/outbound_list.c services/outside_network.c util/alloc.c \
|
||||
util/config_file.c util/configlexer.c util/configparser.c \
|
||||
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
|
||||
@ -117,7 +117,7 @@ $(DNSTAP_SRC)
|
||||
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
|
||||
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
|
||||
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
|
||||
iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo \
|
||||
iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo view.lo \
|
||||
outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \
|
||||
fptr_wlist.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
|
||||
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
|
||||
@ -625,7 +625,8 @@ msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/uti
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/services/localzone.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/module.h $(srcdir)/services/view.h
|
||||
msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
@ -635,7 +636,9 @@ msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/d
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
|
||||
packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h \
|
||||
@ -705,25 +708,32 @@ listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h
|
||||
$(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h
|
||||
localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/util/as112.h
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h $(srcdir)/util/as112.h
|
||||
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/timehist.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/alloc.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/alloc.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/services/view.h $(srcdir)/util/data/dname.h
|
||||
modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/dns64/dns64.h \
|
||||
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
|
||||
$(srcdir)/validator/val_utils.h $(PYTHONMOD_HEADER) $(srcdir)/cachedb/cachedb.h
|
||||
$(srcdir)/validator/val_utils.h $(PYTHONMOD_HEADER)
|
||||
view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h
|
||||
outbound_list.lo outbound_list.o: $(srcdir)/services/outbound_list.c config.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/netevent.h
|
||||
@ -760,15 +770,15 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
|
||||
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
|
||||
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \
|
||||
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
|
||||
$(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
|
||||
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h \
|
||||
$(PYTHONMOD_HEADER) $(srcdir)/cachedb/cachedb.h
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h $(srcdir)/iterator/iterator.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/validator/validator.h \
|
||||
$(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_nsec3.h \
|
||||
$(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_neg.h \
|
||||
$(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h $(srcdir)/libunbound/context.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/config_file.h $(PYTHONMOD_HEADER)
|
||||
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
|
||||
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
|
||||
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
||||
@ -778,7 +788,7 @@ mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
|
||||
module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
|
||||
netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/util/ub_event.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/net_help.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
@ -902,14 +912,7 @@ dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(src
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
|
||||
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.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)/util/data/msgencode.h $(srcdir)/services/cache/dns.h $(srcdir)/validator/val_neg.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/validator/val_secalgo.h $(srcdir)/iterator/iter_utils.h \
|
||||
$(srcdir)/iterator/iter_resptype.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h
|
||||
checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/testcode/checklocks.h
|
||||
unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
|
||||
@ -956,9 +959,11 @@ testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcod
|
||||
unitldns.lo unitldns.o: $(srcdir)/testcode/unitldns.c config.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
|
||||
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
|
||||
cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon/cachedump.h \
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
@ -978,10 +983,10 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
|
||||
remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
|
||||
@ -992,12 +997,12 @@ remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h
|
||||
$(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/data/dname.h $(srcdir)/validator/validator.h \
|
||||
$(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h \
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h \
|
||||
$(srcdir)/sldns/wire2str.h
|
||||
$(srcdir)/services/view.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
|
||||
$(srcdir)/iterator/iter_delegpt.h $(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h \
|
||||
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
|
||||
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
@ -1025,8 +1030,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
|
||||
@ -1054,8 +1059,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
|
||||
@ -1064,9 +1069,11 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/libworker.h
|
||||
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
|
||||
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
@ -1074,10 +1081,10 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
|
||||
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
@ -1125,7 +1132,7 @@ 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)/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)/sldns/sbuffer.h $(PYTHONMOD_HEADER)
|
||||
$(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(PYTHONMOD_HEADER)
|
||||
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)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
@ -1137,8 +1144,9 @@ context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbou
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/unbound-event.h 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 \
|
||||
@ -1146,9 +1154,9 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/sldns/sbuffer.h
|
||||
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||
@ -1156,12 +1164,12 @@ libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/li
|
||||
$(srcdir)/libunbound/unbound-event.h $(srcdir)/services/outside_network.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
|
||||
$(srcdir)/sldns/str2wire.h
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h \
|
||||
$(srcdir)/iterator/iter_hints.h $(srcdir)/sldns/str2wire.h
|
||||
unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
|
||||
asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \
|
||||
|
@ -547,8 +547,8 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->blacklist) {
|
||||
/* cache is blacklisted */
|
||||
if(qstate->blacklist || qstate->no_cache_lookup) {
|
||||
/* cache is blacklisted or we are instructed from edns to not look */
|
||||
/* pass request to next module */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
@ -556,10 +556,15 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
|
||||
/* lookup inside unbound's internal cache */
|
||||
if(cachedb_intcache_lookup(qstate)) {
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("cachedb internal cache lookup",
|
||||
&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
if(qstate->return_msg->rep)
|
||||
log_dns_msg("cachedb internal cache lookup",
|
||||
&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
else log_info("cachedb internal cache lookup: rcode %s",
|
||||
sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)?
|
||||
sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)->name:"??");
|
||||
}
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
@ -595,8 +600,8 @@ static void
|
||||
cachedb_handle_response(struct module_qstate* qstate,
|
||||
struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
|
||||
{
|
||||
/* check if we are enabled, and skip if not */
|
||||
if(!ie->enabled) {
|
||||
/* check if we are not enabled or instructed to not cache, and skip */
|
||||
if(!ie->enabled || qstate->no_cache_store) {
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
@ -649,6 +654,11 @@ cachedb_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
return;
|
||||
}
|
||||
if(!iq && (event == module_event_moddone)) {
|
||||
/* during priming, module done but we never started */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
log_err("bad event for cachedb");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
|
@ -107,6 +107,9 @@
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the `DSA_SIG_set0' function. */
|
||||
#undef HAVE_DSA_SIG_SET0
|
||||
|
||||
/* Define to 1 if you have the <endian.h> header file. */
|
||||
#undef HAVE_ENDIAN_H
|
||||
|
||||
@ -143,6 +146,9 @@
|
||||
/* Define to 1 if you have the `EVP_cleanup' function. */
|
||||
#undef HAVE_EVP_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `EVP_dss1' function. */
|
||||
#undef HAVE_EVP_DSS1
|
||||
|
||||
/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
|
||||
#undef HAVE_EVP_MD_CTX_NEW
|
||||
|
||||
@ -344,9 +350,6 @@
|
||||
/* Define to 1 if you have the `recvmsg' function. */
|
||||
#undef HAVE_RECVMSG
|
||||
|
||||
/* define if you have the sbrk() call */
|
||||
#undef HAVE_SBRK
|
||||
|
||||
/* Define to 1 if you have the `sendmsg' function. */
|
||||
#undef HAVE_SENDMSG
|
||||
|
||||
@ -395,6 +398,9 @@
|
||||
/* Define if you have the SSL libraries installed. */
|
||||
#undef HAVE_SSL
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
|
||||
#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
|
77
contrib/unbound/configure
vendored
77
contrib/unbound/configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.5.10.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.6.0.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
|
||||
#
|
||||
@ -590,8 +590,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='1.5.10'
|
||||
PACKAGE_STRING='unbound 1.5.10'
|
||||
PACKAGE_VERSION='1.6.0'
|
||||
PACKAGE_STRING='unbound 1.6.0'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@ -659,6 +659,7 @@ WINAPPS
|
||||
WINDRES
|
||||
CHECKLOCK_OBJ
|
||||
staticexe
|
||||
PC_LIBEVENT_DEPENDENCY
|
||||
UNBOUND_EVENT_UNINSTALL
|
||||
UNBOUND_EVENT_INSTALL
|
||||
SSLLIB
|
||||
@ -678,6 +679,7 @@ WITH_PYTHONMODULE
|
||||
swig
|
||||
SWIG_LIB
|
||||
SWIG
|
||||
PC_PY_DEPENDENCY
|
||||
PY_MAJOR_VERSION
|
||||
PYTHON_SITE_PKG
|
||||
PYTHON_LDFLAGS
|
||||
@ -1401,7 +1403,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures unbound 1.5.10 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.6.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1466,7 +1468,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.5.10:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.6.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1656,7 +1658,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.5.10
|
||||
unbound configure 1.6.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@ -2365,7 +2367,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by unbound $as_me 1.5.10, which was
|
||||
It was created by unbound $as_me 1.6.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -2715,13 +2717,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=5
|
||||
UNBOUND_VERSION_MINOR=6
|
||||
|
||||
UNBOUND_VERSION_MICRO=10
|
||||
UNBOUND_VERSION_MICRO=0
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=6
|
||||
LIBUNBOUND_REVISION=2
|
||||
LIBUNBOUND_REVISION=3
|
||||
LIBUNBOUND_AGE=4
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@ -2771,6 +2773,7 @@ LIBUNBOUND_AGE=4
|
||||
# 1.5.8 had 6:0:4 # adds ub_ctx_set_stub
|
||||
# 1.5.9 had 6:1:4
|
||||
# 1.5.10 had 6:2:4
|
||||
# 1.6.0 had 6:3:4
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@ -16823,6 +16826,8 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
|
||||
|
||||
# Check for SWIG
|
||||
ub_have_swig=no
|
||||
@ -17535,7 +17540,7 @@ fi
|
||||
|
||||
done
|
||||
|
||||
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup
|
||||
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
@ -17551,12 +17556,13 @@ done
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
for ac_func in OPENSSL_init_ssl
|
||||
for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
|
||||
if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_OPENSSL_INIT_SSL 1
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
@ -17925,13 +17931,13 @@ if test "${enable_dsa+set}" = set; then :
|
||||
fi
|
||||
|
||||
use_dsa="no"
|
||||
case "$enable_ecdsa" in
|
||||
case "$enable_dsa" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
ac_fn_c_check_func "$LINENO" "EVP_dss1" "ac_cv_func_EVP_dss1"
|
||||
if test "x$ac_cv_func_EVP_dss1" = xyes; then :
|
||||
ac_fn_c_check_func "$LINENO" "DSA_SIG_new" "ac_cv_func_DSA_SIG_new"
|
||||
if test "x$ac_cv_func_DSA_SIG_new" = xyes; then :
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@ -18378,6 +18384,8 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
# only in libev. (tested on 4.00)
|
||||
PC_LIBEVENT_DEPENDENCY="libevent"
|
||||
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
LDFLAGS="$BAK_LDFLAGS"
|
||||
fi
|
||||
@ -18959,33 +18967,6 @@ fi
|
||||
done
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sbrk" >&5
|
||||
$as_echo_n "checking for sbrk... " >&6; }
|
||||
# catch the warning of deprecated sbrk
|
||||
old_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
|
||||
int main(void) { void* cur = sbrk(0); printf("%u\n", (unsigned)(size_t)((char*)cur - (char*)sbrk(0))); return 0; }
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
$as_echo "#define HAVE_SBRK 1" >>confdefs.h
|
||||
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
CFLAGS="$old_cflags"
|
||||
|
||||
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
|
||||
@ -19939,7 +19920,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
version=1.5.10
|
||||
version=1.6.0
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
@ -20454,7 +20435,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by unbound $as_me 1.5.10, which was
|
||||
This file was extended by unbound $as_me 1.6.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -20520,7 +20501,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
unbound config.status 1.5.10
|
||||
unbound config.status 1.6.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
@ -9,15 +9,15 @@ sinclude(dnstap/dnstap.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[5])
|
||||
m4_define([VERSION_MICRO],[10])
|
||||
m4_define([VERSION_MINOR],[6])
|
||||
m4_define([VERSION_MICRO],[0])
|
||||
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=6
|
||||
LIBUNBOUND_REVISION=2
|
||||
LIBUNBOUND_REVISION=3
|
||||
LIBUNBOUND_AGE=4
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@ -67,6 +67,7 @@ LIBUNBOUND_AGE=4
|
||||
# 1.5.8 had 6:0:4 # adds ub_ctx_set_stub
|
||||
# 1.5.9 had 6:1:4
|
||||
# 1.5.10 had 6:2:4
|
||||
# 1.6.0 had 6:3:4
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@ -543,6 +544,8 @@ if test x_$ub_test_python != x_no; then
|
||||
LIBS="$PYTHON_LDFLAGS $LIBS"
|
||||
CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
|
||||
ub_have_python=yes
|
||||
PC_PY_DEPENDENCY="python"
|
||||
AC_SUBST(PC_PY_DEPENDENCY)
|
||||
|
||||
# Check for SWIG
|
||||
ub_have_swig=no
|
||||
@ -673,12 +676,12 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl])
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level])
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||
@ -864,12 +867,12 @@ esac
|
||||
|
||||
AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support]))
|
||||
use_dsa="no"
|
||||
case "$enable_ecdsa" in
|
||||
case "$enable_dsa" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
AC_CHECK_FUNC(EVP_dss1, [
|
||||
AC_CHECK_FUNC(DSA_SIG_new, [
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
|
||||
fi ])
|
||||
@ -1000,6 +1003,8 @@ large outgoing port ranges. ])
|
||||
AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later
|
||||
AC_CHECK_FUNCS([ev_loop]) # only in libev. (tested on 3.51)
|
||||
AC_CHECK_FUNCS([ev_default_loop]) # only in libev. (tested on 4.00)
|
||||
PC_LIBEVENT_DEPENDENCY="libevent"
|
||||
AC_SUBST(PC_LIBEVENT_DEPENDENCY)
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
LDFLAGS="$BAK_LDFLAGS"
|
||||
fi
|
||||
@ -1142,19 +1147,6 @@ AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit se
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
AC_MSG_CHECKING([for sbrk])
|
||||
# catch the warning of deprecated sbrk
|
||||
old_cflags="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT
|
||||
[[
|
||||
int main(void) { void* cur = sbrk(0); printf("%u\n", (unsigned)(size_t)((char*)cur - (char*)sbrk(0))); return 0; }
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SBRK, 1, [define if you have the sbrk() call])
|
||||
], [AC_MSG_RESULT(no)])
|
||||
CFLAGS="$old_cflags"
|
||||
|
||||
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||
|
@ -7,7 +7,7 @@ Name: unbound
|
||||
Description: Library with validating, recursive, and caching DNS resolver
|
||||
URL: http://www.unbound.net
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires:
|
||||
Libs: -L${libdir} -lunbound @SSLLIB@ @LIBS@
|
||||
Libs.private: @LDFLAGS@
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound
|
||||
Libs.private: @SSLLIB@ @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
|
@ -150,7 +150,7 @@ get_state ( ) {
|
||||
fi
|
||||
done
|
||||
# try to get it
|
||||
echo $$ >$lock
|
||||
if echo $$ >$lock ; then : ; else break; fi
|
||||
done
|
||||
# do not refetch if the file exists and only LEE seconds old
|
||||
if test -f $state; then
|
||||
@ -266,7 +266,6 @@ if test "$1" = "config" ; then
|
||||
echo "graph_args --base 1024 -l 0"
|
||||
echo "graph_vlabel memory used in bytes"
|
||||
echo "graph_category DNS"
|
||||
p_config "mem.total.sbrk" "Total memory" "GAUGE"
|
||||
p_config "mem.cache.rrset" "RRset cache memory" "GAUGE"
|
||||
p_config "mem.cache.message" "Message cache memory" "GAUGE"
|
||||
p_config "mem.mod.iterator" "Iterator module memory" "GAUGE"
|
||||
@ -458,20 +457,6 @@ queue)
|
||||
done
|
||||
;;
|
||||
memory)
|
||||
mn=`echo mem.total.sbrk | sed $ABBREV | tr . _`
|
||||
get_value 'mem.total.sbrk'
|
||||
if test $value -eq 0; then
|
||||
chk=`echo $ctrl | sed -e 's/-control$/-checkconf/'`
|
||||
pidf=`$chk -o pidfile $conf 2>&1`
|
||||
pid=`cat $pidf 2>&1`
|
||||
value=`ps -p "$pid" -o rss= 2>&1`
|
||||
if test "`expr $value + 1 - 1 2>&1`" -eq "$value" 2>&1; then
|
||||
value=`expr $value \* 1024`
|
||||
else
|
||||
value=0
|
||||
fi
|
||||
fi
|
||||
echo "$mn.value" $value
|
||||
for x in mem.cache.rrset mem.cache.message mem.mod.iterator \
|
||||
mem.mod.validator msg.cache.count rrset.cache.count \
|
||||
infra.cache.count key.cache.count; do
|
||||
|
@ -170,6 +170,23 @@ acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply acl_view string */
|
||||
static int
|
||||
acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
|
||||
struct views* vs)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
return 0;
|
||||
node->view = views_find_view(vs, str2, 0 /* get read lock*/);
|
||||
if(!node->view) {
|
||||
log_err("no view with name: %s", str2);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&node->view->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply acl_tag_action string */
|
||||
static int
|
||||
acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
@ -210,15 +227,47 @@ acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
|
||||
/** check wire data parse */
|
||||
static int
|
||||
check_data(const char* data)
|
||||
check_data(const char* data, const struct config_strlist* head)
|
||||
{
|
||||
char buf[65536];
|
||||
uint8_t rr[LDNS_RR_BUF_SIZE];
|
||||
size_t len = sizeof(rr);
|
||||
int res;
|
||||
snprintf(buf, sizeof(buf), "%s %s", "example.com.", data);
|
||||
/* '.' is sufficient for validation, and it makes the call to
|
||||
* sldns_wirerr_get_type() simpler below. */
|
||||
snprintf(buf, sizeof(buf), "%s %s", ".", data);
|
||||
res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0,
|
||||
NULL, 0);
|
||||
|
||||
/* Reject it if we would end up having CNAME and other data (including
|
||||
* another CNAME) for the same tag. */
|
||||
if(res == 0 && head) {
|
||||
const char* err_data = NULL;
|
||||
|
||||
if(sldns_wirerr_get_type(rr, len, 1) == LDNS_RR_TYPE_CNAME) {
|
||||
/* adding CNAME while other data already exists. */
|
||||
err_data = data;
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "%s %s", ".", head->str);
|
||||
len = sizeof(rr);
|
||||
res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600,
|
||||
NULL, 0, NULL, 0);
|
||||
if(res != 0) {
|
||||
/* This should be impossible here as head->str
|
||||
* has been validated, but we check it just in
|
||||
* case. */
|
||||
return 0;
|
||||
}
|
||||
if(sldns_wirerr_get_type(rr, len, 1) ==
|
||||
LDNS_RR_TYPE_CNAME) /* already have CNAME */
|
||||
err_data = head->str;
|
||||
}
|
||||
if(err_data) {
|
||||
log_err("redirect tag data '%s' must not coexist with "
|
||||
"other data.", err_data);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(res == 0)
|
||||
return 1;
|
||||
log_err("rr data [char %d] parse error %s",
|
||||
@ -258,7 +307,7 @@ acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
}
|
||||
|
||||
/* check data? */
|
||||
if(!check_data(data)) {
|
||||
if(!check_data(data, node->tag_datas[tagid])) {
|
||||
log_err("cannot parse access-control-tag data: %s %s '%s'",
|
||||
str, tag, data);
|
||||
return 0;
|
||||
@ -312,6 +361,27 @@ read_acl_tags(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl view config */
|
||||
static int
|
||||
read_acl_view(struct acl_list* acl, struct config_file* cfg, struct views* v)
|
||||
{
|
||||
struct config_str2list* np, *p = cfg->acl_view;
|
||||
cfg->acl_view = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_view_cfg(acl, p->str, p->str2, v)) {
|
||||
return 0;
|
||||
}
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tag actions config */
|
||||
static int
|
||||
read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
|
||||
@ -362,12 +432,15 @@ read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
|
||||
}
|
||||
|
||||
int
|
||||
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
|
||||
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
struct views* v)
|
||||
{
|
||||
regional_free_all(acl->region);
|
||||
addr_tree_init(&acl->tree);
|
||||
if(!read_acl_list(acl, cfg))
|
||||
return 0;
|
||||
if(!read_acl_view(acl, cfg, v))
|
||||
return 0;
|
||||
if(!read_acl_tags(acl, cfg))
|
||||
return 0;
|
||||
if(!read_acl_tag_actions(acl, cfg))
|
||||
|
@ -43,6 +43,7 @@
|
||||
#ifndef DAEMON_ACL_LIST_H
|
||||
#define DAEMON_ACL_LIST_H
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "services/view.h"
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
@ -100,6 +101,8 @@ struct acl_addr {
|
||||
struct config_strlist** tag_datas;
|
||||
/** size of the tag_datas array */
|
||||
size_t tag_datas_size;
|
||||
/* view element, NULL if none */
|
||||
struct view* view;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -118,9 +121,11 @@ void acl_list_delete(struct acl_list* acl);
|
||||
* Process access control config.
|
||||
* @param acl: where to store.
|
||||
* @param cfg: config options.
|
||||
* @param v: views structure
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg);
|
||||
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
struct views* v);
|
||||
|
||||
/**
|
||||
* Lookup access control status for acl structure.
|
||||
|
@ -563,6 +563,7 @@ load_qinfo(char* str, struct query_info* qinfo, struct regional* region)
|
||||
qinfo->qclass = sldns_wirerr_get_class(rr, rr_len, dname_len);
|
||||
qinfo->qname_len = dname_len;
|
||||
qinfo->qname = (uint8_t*)regional_alloc_init(region, rr, dname_len);
|
||||
qinfo->local_alias = NULL;
|
||||
if(!qinfo->qname) {
|
||||
log_warn("error out of memory");
|
||||
return NULL;
|
||||
@ -826,6 +827,7 @@ int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
|
||||
qinfo.qname_len = nmlen;
|
||||
qinfo.qtype = LDNS_RR_TYPE_A;
|
||||
qinfo.qclass = LDNS_RR_CLASS_IN;
|
||||
qinfo.local_alias = NULL;
|
||||
|
||||
dname_str(nm, b);
|
||||
if(!ssl_printf(ssl, "The following name servers are used for lookup "
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/view.h"
|
||||
#include "services/modstack.h"
|
||||
#include "util/module.h"
|
||||
#include "util/random.h"
|
||||
@ -248,9 +249,16 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
/* init edns_known_options */
|
||||
if(!edns_known_options_init(daemon->env)) {
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
alloc_init(&daemon->superalloc, NULL, 0);
|
||||
daemon->acl = acl_list_create();
|
||||
if(!daemon->acl) {
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
@ -347,6 +355,7 @@ static void daemon_setup_modules(struct daemon* daemon)
|
||||
daemon->env)) {
|
||||
fatal_exit("failed to setup modules");
|
||||
}
|
||||
log_edns_known_options(VERB_ALGO, daemon->env);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -542,8 +551,15 @@ void
|
||||
daemon_fork(struct daemon* daemon)
|
||||
{
|
||||
log_assert(daemon);
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg))
|
||||
if(!(daemon->views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
/* create individual views and their localzone/data trees */
|
||||
if(!views_apply_cfg(daemon->views, daemon->cfg))
|
||||
fatal_exit("Could not set up views");
|
||||
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||
fatal_exit("Could not setup access control list");
|
||||
/* create global local_zones */
|
||||
if(!(daemon->local_zones = local_zones_create()))
|
||||
fatal_exit("Could not create local zones: out of memory");
|
||||
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
|
||||
@ -605,6 +621,8 @@ daemon_cleanup(struct daemon* daemon)
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
views_delete(daemon->views);
|
||||
daemon->views = NULL;
|
||||
/* key cache is cleared by module desetup during next daemon_fork() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
for(i=0; i<daemon->num; i++)
|
||||
@ -634,6 +652,8 @@ daemon_delete(struct daemon* daemon)
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
rrset_cache_delete(daemon->env->rrset_cache);
|
||||
infra_delete(daemon->env->infra_cache);
|
||||
edns_known_options_delete(daemon->env);
|
||||
inplace_cb_lists_delete(daemon->env);
|
||||
}
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
|
@ -53,6 +53,7 @@ struct module_env;
|
||||
struct rrset_cache;
|
||||
struct acl_list;
|
||||
struct local_zones;
|
||||
struct views;
|
||||
struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
|
||||
@ -111,6 +112,8 @@ struct daemon {
|
||||
struct timeval time_last_stat;
|
||||
/** time when daemon started */
|
||||
struct timeval time_boot;
|
||||
/** views structure containing view tree */
|
||||
struct views* views;
|
||||
#ifdef USE_DNSTAP
|
||||
/** the dnstap environment master value, copied and changed by threads*/
|
||||
struct dt_env* dtenv;
|
||||
|
@ -146,6 +146,7 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
|
||||
* the command : "openssl dhparam -C 2048"
|
||||
* (some openssl versions reject DH that is 'too small', eg. 512).
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
#ifndef S_SPLINT_S
|
||||
static DH *get_dh2048(void)
|
||||
{
|
||||
@ -203,6 +204,7 @@ static DH *get_dh2048(void)
|
||||
return NULL;
|
||||
}
|
||||
#endif /* SPLINT */
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
|
||||
|
||||
struct daemon_remote*
|
||||
daemon_remote_create(struct config_file* cfg)
|
||||
@ -243,12 +245,18 @@ daemon_remote_create(struct config_file* cfg)
|
||||
|
||||
if (cfg->remote_control_use_cert == 0) {
|
||||
/* No certificates are requested */
|
||||
if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL")) {
|
||||
#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
|
||||
SSL_CTX_set_security_level(rc->ctx, 0);
|
||||
#endif
|
||||
if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL, eNULL")) {
|
||||
log_crypto_err("Failed to set aNULL cipher list");
|
||||
daemon_remote_delete(rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* in openssl 1.1, the securitylevel 0 allows eNULL, that
|
||||
* does not need the DH */
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
/* Since we have no certificates and hence no source of
|
||||
* DH params, let's generate and set them
|
||||
*/
|
||||
@ -257,6 +265,7 @@ daemon_remote_create(struct config_file* cfg)
|
||||
daemon_remote_delete(rc);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
rc->use_cert = 1;
|
||||
@ -760,6 +769,8 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s)
|
||||
(unsigned long)s->svr.num_queries_missed_cache)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_prefetch)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.zero_ttl"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.zero_ttl_responses)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm,
|
||||
(unsigned long)s->mesh_replies_sent)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.avg"SQ"%g\n", nm,
|
||||
@ -818,12 +829,6 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
|
||||
{
|
||||
int m;
|
||||
size_t msg, rrset, val, iter;
|
||||
#ifdef HAVE_SBRK
|
||||
extern void* unbound_start_brk;
|
||||
void* cur = sbrk(0);
|
||||
if(!print_longnum(ssl, "mem.total.sbrk"SQ,
|
||||
(size_t)((char*)cur - (char*)unbound_start_brk))) return 0;
|
||||
#endif /* HAVE_SBRK */
|
||||
msg = slabhash_get_mem(daemon->env->msg_cache);
|
||||
rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
|
||||
val=0;
|
||||
@ -1123,8 +1128,8 @@ find_arg2(SSL* ssl, char* arg, char** arg2)
|
||||
}
|
||||
|
||||
/** Add a new zone */
|
||||
static void
|
||||
do_zone_add(SSL* ssl, struct worker* worker, char* arg)
|
||||
static int
|
||||
perform_zone_add(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
@ -1133,83 +1138,266 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
|
||||
enum localzone_type t;
|
||||
struct local_zone* z;
|
||||
if(!find_arg2(ssl, arg, &arg2))
|
||||
return;
|
||||
return 0;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
return 0;
|
||||
if(!local_zone_str2type(arg2, &t)) {
|
||||
ssl_printf(ssl, "error not a zone type. %s\n", arg2);
|
||||
free(nm);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
lock_rw_wrlock(&worker->daemon->local_zones->lock);
|
||||
if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen,
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
if((z=local_zones_find(zones, nm, nmlen,
|
||||
nmlabs, LDNS_RR_CLASS_IN))) {
|
||||
/* already present in tree */
|
||||
lock_rw_wrlock(&z->lock);
|
||||
z->type = t; /* update type anyway */
|
||||
lock_rw_unlock(&z->lock);
|
||||
free(nm);
|
||||
lock_rw_unlock(&worker->daemon->local_zones->lock);
|
||||
send_ok(ssl);
|
||||
return;
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return 1;
|
||||
}
|
||||
if(!local_zones_add_zone(worker->daemon->local_zones, nm, nmlen,
|
||||
if(!local_zones_add_zone(zones, nm, nmlen,
|
||||
nmlabs, LDNS_RR_CLASS_IN, t)) {
|
||||
lock_rw_unlock(&worker->daemon->local_zones->lock);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
ssl_printf(ssl, "error out of memory\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&worker->daemon->local_zones->lock);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Do the local_zone command */
|
||||
static void
|
||||
do_zone_add(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
if(!perform_zone_add(ssl, zones, arg))
|
||||
return;
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** Remove a zone */
|
||||
/** Do the local_zones command */
|
||||
static void
|
||||
do_zone_remove(SSL* ssl, struct worker* worker, char* arg)
|
||||
do_zones_add(SSL* ssl, struct local_zones* zones)
|
||||
{
|
||||
char buf[2048];
|
||||
int num = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(!perform_zone_add(ssl, zones, buf)) {
|
||||
if(!ssl_printf(ssl, "error for input line: %s\n", buf))
|
||||
return;
|
||||
}
|
||||
else
|
||||
num++;
|
||||
}
|
||||
(void)ssl_printf(ssl, "added %d zones\n", num);
|
||||
}
|
||||
|
||||
/** Remove a zone */
|
||||
static int
|
||||
perform_zone_remove(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
struct local_zone* z;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
lock_rw_wrlock(&worker->daemon->local_zones->lock);
|
||||
if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen,
|
||||
return 0;
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
if((z=local_zones_find(zones, nm, nmlen,
|
||||
nmlabs, LDNS_RR_CLASS_IN))) {
|
||||
/* present in tree */
|
||||
local_zones_del_zone(worker->daemon->local_zones, z);
|
||||
local_zones_del_zone(zones, z);
|
||||
}
|
||||
lock_rw_unlock(&worker->daemon->local_zones->lock);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
free(nm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Do the local_zone_remove command */
|
||||
static void
|
||||
do_zone_remove(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
if(!perform_zone_remove(ssl, zones, arg))
|
||||
return;
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** Do the local_zones_remove command */
|
||||
static void
|
||||
do_zones_remove(SSL* ssl, struct local_zones* zones)
|
||||
{
|
||||
char buf[2048];
|
||||
int num = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(!perform_zone_remove(ssl, zones, buf)) {
|
||||
if(!ssl_printf(ssl, "error for input line: %s\n", buf))
|
||||
return;
|
||||
}
|
||||
else
|
||||
num++;
|
||||
}
|
||||
(void)ssl_printf(ssl, "removed %d zones\n", num);
|
||||
}
|
||||
|
||||
/** Add new RR data */
|
||||
static void
|
||||
do_data_add(SSL* ssl, struct worker* worker, char* arg)
|
||||
static int
|
||||
perform_data_add(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
if(!local_zones_add_RR(worker->daemon->local_zones, arg)) {
|
||||
if(!local_zones_add_RR(zones, arg)) {
|
||||
ssl_printf(ssl,"error in syntax or out of memory, %s\n", arg);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Do the local_data command */
|
||||
static void
|
||||
do_data_add(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
if(!perform_data_add(ssl, zones, arg))
|
||||
return;
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** Remove RR data */
|
||||
/** Do the local_datas command */
|
||||
static void
|
||||
do_data_remove(SSL* ssl, struct worker* worker, char* arg)
|
||||
do_datas_add(SSL* ssl, struct local_zones* zones)
|
||||
{
|
||||
char buf[2048];
|
||||
int num = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(!perform_data_add(ssl, zones, buf)) {
|
||||
if(!ssl_printf(ssl, "error for input line: %s\n", buf))
|
||||
return;
|
||||
}
|
||||
else
|
||||
num++;
|
||||
}
|
||||
(void)ssl_printf(ssl, "added %d datas\n", num);
|
||||
}
|
||||
|
||||
/** Remove RR data */
|
||||
static int
|
||||
perform_data_remove(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
local_zones_del_data(worker->daemon->local_zones, nm,
|
||||
return 0;
|
||||
local_zones_del_data(zones, nm,
|
||||
nmlen, nmlabs, LDNS_RR_CLASS_IN);
|
||||
free(nm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Do the local_data_remove command */
|
||||
static void
|
||||
do_data_remove(SSL* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
if(!perform_data_remove(ssl, zones, arg))
|
||||
return;
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
/** Do the local_datas_remove command */
|
||||
static void
|
||||
do_datas_remove(SSL* ssl, struct local_zones* zones)
|
||||
{
|
||||
char buf[2048];
|
||||
int num = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(!perform_data_remove(ssl, zones, buf)) {
|
||||
if(!ssl_printf(ssl, "error for input line: %s\n", buf))
|
||||
return;
|
||||
}
|
||||
else
|
||||
num++;
|
||||
}
|
||||
(void)ssl_printf(ssl, "removed %d datas\n", num);
|
||||
}
|
||||
|
||||
/** Add a new zone to view */
|
||||
static void
|
||||
do_view_zone_add(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
char* arg2;
|
||||
struct view* v;
|
||||
if(!find_arg2(ssl, arg, &arg2))
|
||||
return;
|
||||
v = views_find_view(worker->daemon->views,
|
||||
arg, 1 /* get write lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_zone_add(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** Remove a zone from view */
|
||||
static void
|
||||
do_view_zone_remove(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
char* arg2;
|
||||
struct view* v;
|
||||
if(!find_arg2(ssl, arg, &arg2))
|
||||
return;
|
||||
v = views_find_view(worker->daemon->views,
|
||||
arg, 1 /* get write lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_zone_remove(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** Add new RR data to view */
|
||||
static void
|
||||
do_view_data_add(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
char* arg2;
|
||||
struct view* v;
|
||||
if(!find_arg2(ssl, arg, &arg2))
|
||||
return;
|
||||
v = views_find_view(worker->daemon->views,
|
||||
arg, 1 /* get write lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_data_add(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** Remove RR data from view */
|
||||
static void
|
||||
do_view_data_remove(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
char* arg2;
|
||||
struct view* v;
|
||||
if(!find_arg2(ssl, arg, &arg2))
|
||||
return;
|
||||
v = views_find_view(worker->daemon->views,
|
||||
arg, 1 /* get write lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_data_remove(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** cache lookup of nameservers */
|
||||
static void
|
||||
do_lookup(SSL* ssl, struct worker* worker, char* arg)
|
||||
@ -1238,6 +1426,7 @@ do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen,
|
||||
k.qname_len = nmlen;
|
||||
k.qtype = t;
|
||||
k.qclass = c;
|
||||
k.local_alias = NULL;
|
||||
h = query_info_hash(&k, 0);
|
||||
slabhash_remove(worker->env.msg_cache, h, &k);
|
||||
if(t == LDNS_RR_TYPE_AAAA) {
|
||||
@ -2183,6 +2372,14 @@ do_set_option(SSL* ssl, struct worker* worker, char* arg)
|
||||
(void)ssl_printf(ssl, "error setting option\n");
|
||||
return;
|
||||
}
|
||||
/* effectuate some arguments */
|
||||
if(strcmp(arg, "val-override-date:") == 0) {
|
||||
int m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
struct val_env* val_env = NULL;
|
||||
if(m != -1) val_env = (struct val_env*)worker->env.modinfo[m];
|
||||
if(val_env)
|
||||
val_env->date_override = worker->env.cfg->val_date_override;
|
||||
}
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
@ -2263,9 +2460,8 @@ do_list_stubs(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** do the list_local_zones command */
|
||||
static void
|
||||
do_list_local_zones(SSL* ssl, struct worker* worker)
|
||||
do_list_local_zones(SSL* ssl, struct local_zones* zones)
|
||||
{
|
||||
struct local_zones* zones = worker->daemon->local_zones;
|
||||
struct local_zone* z;
|
||||
char buf[257];
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
@ -2286,9 +2482,8 @@ do_list_local_zones(SSL* ssl, struct worker* worker)
|
||||
|
||||
/** do the list_local_data command */
|
||||
static void
|
||||
do_list_local_data(SSL* ssl, struct worker* worker)
|
||||
do_list_local_data(SSL* ssl, struct worker* worker, struct local_zones* zones)
|
||||
{
|
||||
struct local_zones* zones = worker->daemon->local_zones;
|
||||
struct local_zone* z;
|
||||
struct local_data* d;
|
||||
struct local_rrset* p;
|
||||
@ -2324,6 +2519,34 @@ do_list_local_data(SSL* ssl, struct worker* worker)
|
||||
lock_rw_unlock(&zones->lock);
|
||||
}
|
||||
|
||||
/** do the view_list_local_zones command */
|
||||
static void
|
||||
do_view_list_local_zones(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct view* v = views_find_view(worker->daemon->views,
|
||||
arg, 0 /* get read lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_list_local_zones(ssl, v->local_zones);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** do the view_list_local_data command */
|
||||
static void
|
||||
do_view_list_local_data(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct view* v = views_find_view(worker->daemon->views,
|
||||
arg, 0 /* get read lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_list_local_data(ssl, worker, v->local_zones);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** struct for user arg ratelimit list */
|
||||
struct ratelimit_list_arg {
|
||||
/** the infra cache */
|
||||
@ -2436,10 +2659,16 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||
do_insecure_list(ssl, worker);
|
||||
return;
|
||||
} else if(cmdcmp(p, "list_local_zones", 16)) {
|
||||
do_list_local_zones(ssl, worker);
|
||||
do_list_local_zones(ssl, worker->daemon->local_zones);
|
||||
return;
|
||||
} else if(cmdcmp(p, "list_local_data", 15)) {
|
||||
do_list_local_data(ssl, worker);
|
||||
do_list_local_data(ssl, worker, worker->daemon->local_zones);
|
||||
return;
|
||||
} else if(cmdcmp(p, "view_list_local_zones", 21)) {
|
||||
do_view_list_local_zones(ssl, worker, skipwhite(p+21));
|
||||
return;
|
||||
} else if(cmdcmp(p, "view_list_local_data", 20)) {
|
||||
do_view_list_local_data(ssl, worker, skipwhite(p+20));
|
||||
return;
|
||||
} else if(cmdcmp(p, "ratelimit_list", 14)) {
|
||||
do_ratelimit_list(ssl, worker, p+14);
|
||||
@ -2505,13 +2734,29 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||
if(cmdcmp(p, "verbosity", 9)) {
|
||||
do_verbosity(ssl, skipwhite(p+9));
|
||||
} else if(cmdcmp(p, "local_zone_remove", 17)) {
|
||||
do_zone_remove(ssl, worker, skipwhite(p+17));
|
||||
do_zone_remove(ssl, worker->daemon->local_zones, skipwhite(p+17));
|
||||
} else if(cmdcmp(p, "local_zones_remove", 18)) {
|
||||
do_zones_remove(ssl, worker->daemon->local_zones);
|
||||
} else if(cmdcmp(p, "local_zone", 10)) {
|
||||
do_zone_add(ssl, worker, skipwhite(p+10));
|
||||
do_zone_add(ssl, worker->daemon->local_zones, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "local_zones", 11)) {
|
||||
do_zones_add(ssl, worker->daemon->local_zones);
|
||||
} else if(cmdcmp(p, "local_data_remove", 17)) {
|
||||
do_data_remove(ssl, worker, skipwhite(p+17));
|
||||
do_data_remove(ssl, worker->daemon->local_zones, skipwhite(p+17));
|
||||
} else if(cmdcmp(p, "local_datas_remove", 18)) {
|
||||
do_datas_remove(ssl, worker->daemon->local_zones);
|
||||
} else if(cmdcmp(p, "local_data", 10)) {
|
||||
do_data_add(ssl, worker, skipwhite(p+10));
|
||||
do_data_add(ssl, worker->daemon->local_zones, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "local_datas", 11)) {
|
||||
do_datas_add(ssl, worker->daemon->local_zones);
|
||||
} else if(cmdcmp(p, "view_local_zone_remove", 22)) {
|
||||
do_view_zone_remove(ssl, worker, skipwhite(p+22));
|
||||
} else if(cmdcmp(p, "view_local_zone", 15)) {
|
||||
do_view_zone_add(ssl, worker, skipwhite(p+15));
|
||||
} else if(cmdcmp(p, "view_local_data_remove", 22)) {
|
||||
do_view_data_remove(ssl, worker, skipwhite(p+22));
|
||||
} else if(cmdcmp(p, "view_local_data", 15)) {
|
||||
do_view_data_add(ssl, worker, skipwhite(p+15));
|
||||
} else if(cmdcmp(p, "flush_zone", 10)) {
|
||||
do_flush_zone(ssl, worker, skipwhite(p+10));
|
||||
} else if(cmdcmp(p, "flush_type", 10)) {
|
||||
|
@ -251,6 +251,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->svr.qEDNS += a->svr.qEDNS;
|
||||
total->svr.qEDNS_DO += a->svr.qEDNS_DO;
|
||||
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
|
||||
total->svr.zero_ttl_responses += a->svr.zero_ttl_responses;
|
||||
total->svr.ans_secure += a->svr.ans_secure;
|
||||
total->svr.ans_bogus += a->svr.ans_bogus;
|
||||
total->svr.rrset_bogus += a->svr.rrset_bogus;
|
||||
|
@ -131,7 +131,8 @@ struct server_stats {
|
||||
size_t unwanted_queries;
|
||||
/** usage of tcp accept list */
|
||||
size_t tcp_accept_usage;
|
||||
|
||||
/** answers served from expired cache */
|
||||
size_t zero_ttl_responses;
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
|
@ -87,11 +87,6 @@
|
||||
# include "nss.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SBRK
|
||||
/** global debug value to keep track of heap memory allocation */
|
||||
void* unbound_start_brk = 0;
|
||||
#endif
|
||||
|
||||
/** print usage. */
|
||||
static void usage(void)
|
||||
{
|
||||
@ -244,19 +239,32 @@ checkrlimits(struct config_file* cfg)
|
||||
#endif /* S_SPLINT_S */
|
||||
}
|
||||
|
||||
/** set default logfile identity based on value from argv[0] at startup **/
|
||||
static void
|
||||
log_ident_set_fromdefault(struct config_file* cfg,
|
||||
const char *log_default_identity)
|
||||
{
|
||||
if(cfg->log_identity == NULL || cfg->log_identity[0] == 0)
|
||||
log_ident_set(log_default_identity);
|
||||
else
|
||||
log_ident_set(cfg->log_identity);
|
||||
}
|
||||
|
||||
/** set verbosity, check rlimits, cache settings */
|
||||
static void
|
||||
apply_settings(struct daemon* daemon, struct config_file* cfg,
|
||||
int cmdline_verbose, int debug_mode)
|
||||
int cmdline_verbose, int debug_mode, const char* log_default_identity)
|
||||
{
|
||||
/* apply if they have changed */
|
||||
verbosity = cmdline_verbose + cfg->verbosity;
|
||||
if (debug_mode > 1) {
|
||||
cfg->use_syslog = 0;
|
||||
free(cfg->logfile);
|
||||
cfg->logfile = NULL;
|
||||
}
|
||||
daemon_apply_cfg(daemon, cfg);
|
||||
checkrlimits(cfg);
|
||||
log_ident_set_fromdefault(cfg, log_default_identity);
|
||||
}
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
@ -586,9 +594,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* @param cmdline_verbose: verbosity resulting from commandline -v.
|
||||
* These increase verbosity as specified in the config file.
|
||||
* @param debug_mode: if set, do not daemonize.
|
||||
* @param log_default_identity: Default identity to report in logs
|
||||
*/
|
||||
static void
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity)
|
||||
{
|
||||
struct config_file* cfg = NULL;
|
||||
struct daemon* daemon = NULL;
|
||||
@ -610,7 +619,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
cfgfile);
|
||||
log_warn("Continuing with default config settings");
|
||||
}
|
||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
|
||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity);
|
||||
if(!done_setup)
|
||||
config_lookup_uid(cfg);
|
||||
|
||||
@ -618,7 +627,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode)
|
||||
if(!daemon_open_shared_ports(daemon))
|
||||
fatal_exit("could not open ports");
|
||||
if(!done_setup) {
|
||||
perform_setup(daemon, cfg, debug_mode, &cfgfile);
|
||||
perform_setup(daemon, cfg, debug_mode, &cfgfile);
|
||||
done_setup = 1;
|
||||
} else {
|
||||
/* reopen log after HUP to facilitate log rotation */
|
||||
@ -665,19 +674,16 @@ main(int argc, char* argv[])
|
||||
int c;
|
||||
const char* cfgfile = CONFIGFILE;
|
||||
const char* winopt = NULL;
|
||||
const char* log_ident_default;
|
||||
int cmdline_verbose = 0;
|
||||
int debug_mode = 0;
|
||||
#ifdef UB_ON_WINDOWS
|
||||
int cmdline_cfg = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SBRK
|
||||
/* take debug snapshot of heap */
|
||||
unbound_start_brk = sbrk(0);
|
||||
#endif
|
||||
|
||||
log_init(NULL, 0, NULL);
|
||||
log_ident_set(strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0]);
|
||||
log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
|
||||
log_ident_set(log_ident_default);
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "c:dhvw:")) != -1) {
|
||||
switch(c) {
|
||||
@ -721,7 +727,7 @@ main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode);
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default);
|
||||
log_init(NULL, 0, NULL); /* close logfile */
|
||||
return 0;
|
||||
}
|
||||
|
@ -101,57 +101,14 @@
|
||||
*/
|
||||
#define PREFETCH_EXPIRY_ADD 60
|
||||
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
/** measure memory leakage */
|
||||
static void
|
||||
debug_memleak(size_t accounted, size_t heap,
|
||||
size_t total_alloc, size_t total_free)
|
||||
{
|
||||
static int init = 0;
|
||||
static size_t base_heap, base_accounted, base_alloc, base_free;
|
||||
size_t base_af, cur_af, grow_af, grow_acc;
|
||||
if(!init) {
|
||||
init = 1;
|
||||
base_heap = heap;
|
||||
base_accounted = accounted;
|
||||
base_alloc = total_alloc;
|
||||
base_free = total_free;
|
||||
}
|
||||
base_af = base_alloc - base_free;
|
||||
cur_af = total_alloc - total_free;
|
||||
grow_af = cur_af - base_af;
|
||||
grow_acc = accounted - base_accounted;
|
||||
log_info("Leakage: %d leaked. growth: %u use, %u acc, %u heap",
|
||||
(int)(grow_af - grow_acc), (unsigned)grow_af,
|
||||
(unsigned)grow_acc, (unsigned)(heap - base_heap));
|
||||
}
|
||||
|
||||
/** give debug heap size indication */
|
||||
static void
|
||||
debug_total_mem(size_t calctotal)
|
||||
{
|
||||
#ifdef HAVE_SBRK
|
||||
extern void* unbound_start_brk;
|
||||
extern size_t unbound_mem_alloc, unbound_mem_freed;
|
||||
void* cur = sbrk(0);
|
||||
int total = cur-unbound_start_brk;
|
||||
log_info("Total heap memory estimate: %u total-alloc: %u "
|
||||
"total-free: %u", (unsigned)total,
|
||||
(unsigned)unbound_mem_alloc, (unsigned)unbound_mem_freed);
|
||||
debug_memleak(calctotal, (size_t)total,
|
||||
unbound_mem_alloc, unbound_mem_freed);
|
||||
#else
|
||||
(void)calctotal;
|
||||
#endif /* HAVE_SBRK */
|
||||
}
|
||||
#endif /* UNBOUND_ALLOC_STATS */
|
||||
|
||||
/** Report on memory usage by this thread and global */
|
||||
static void
|
||||
worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
struct serviced_query* ATTR_UNUSED(cur_serv))
|
||||
{
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
/* measure memory leakage */
|
||||
extern size_t unbound_mem_alloc, unbound_mem_freed;
|
||||
/* debug func in validator module */
|
||||
size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
|
||||
size_t me, iter, val, anch;
|
||||
@ -199,7 +156,9 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
(unsigned)mesh, (unsigned)msg, (unsigned)rrset,
|
||||
(unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch,
|
||||
(unsigned)ac, (unsigned)superac, (unsigned)me);
|
||||
debug_total_mem(total);
|
||||
log_info("Total heap memory estimate: %u total-alloc: %u "
|
||||
"total-free: %u", (unsigned)total,
|
||||
(unsigned)unbound_mem_alloc, (unsigned)unbound_mem_freed);
|
||||
#else /* no UNBOUND_ALLOC_STATS */
|
||||
size_t val = 0;
|
||||
int i;
|
||||
@ -485,6 +444,10 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(!dp) { /* no delegation, need to reprime */
|
||||
return 0;
|
||||
}
|
||||
/* In case we have a local alias, copy it into the delegation message.
|
||||
* Shallow copy should be fine, as we'll be done with msg in this
|
||||
* function. */
|
||||
msg->qinfo.local_alias = qinfo->local_alias;
|
||||
if(must_validate) {
|
||||
switch(check_delegation_secure(msg->rep)) {
|
||||
case sec_status_unchecked:
|
||||
@ -497,8 +460,9 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
|
||||
return 0;
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL,
|
||||
msg->rep, LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
return 0;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
if(worker->stats.extended) {
|
||||
@ -526,12 +490,16 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
|
||||
return 0;
|
||||
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, msg->rep,
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
|
||||
return 0;
|
||||
msg->rep->flags |= BIT_QR|BIT_RA;
|
||||
if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
|
||||
repinfo->c->buffer, 0, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
}
|
||||
@ -553,17 +521,29 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
int secure;
|
||||
int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
|
||||
&& worker->env.need_to_validate;
|
||||
/* see if it is possible */
|
||||
if(rep->ttl < timenow) {
|
||||
/* the rrsets may have been updated in the meantime.
|
||||
* we will refetch the message format from the
|
||||
* authoritative server
|
||||
*/
|
||||
return 0;
|
||||
if(worker->env.cfg->serve_expired) {
|
||||
/* always lock rrsets, rep->ttl is ignored */
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
|
||||
return 0;
|
||||
/* below, rrsets with ttl before timenow become TTL 0 in
|
||||
* the response */
|
||||
/* This response was served with zero TTL */
|
||||
if (timenow >= rep->ttl) {
|
||||
worker->stats.zero_ttl_responses++;
|
||||
}
|
||||
} else {
|
||||
/* see if it is possible */
|
||||
if(rep->ttl < timenow) {
|
||||
/* the rrsets may have been updated in the meantime.
|
||||
* we will refetch the message format from the
|
||||
* authoritative server
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow))
|
||||
return 0;
|
||||
/* locked and ids and ttls are OK. */
|
||||
}
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow))
|
||||
return 0;
|
||||
/* locked and ids and ttls are OK. */
|
||||
/* check CNAME chain (if any) */
|
||||
if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
|
||||
htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
|
||||
@ -584,8 +564,9 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
|
||||
return 0;
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
return 0;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
@ -616,11 +597,15 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
|
||||
return 0;
|
||||
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, rep,
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
|
||||
return 0;
|
||||
if(!reply_info_answer_encode(qinfo, rep, id, flags,
|
||||
repinfo->c->buffer, timenow, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
}
|
||||
@ -692,8 +677,9 @@ chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
|
||||
LDNS_RCODE_NOERROR, edns, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
attach_edns_record(pkt, edns);
|
||||
}
|
||||
|
||||
@ -944,12 +930,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns,
|
||||
c->buffer, worker->scratchpad, repinfo,
|
||||
acladdr->taglist, acladdr->taglen, acladdr->tag_actions,
|
||||
if(local_zones_answer(worker->daemon->local_zones, &worker->env, &qinfo,
|
||||
&edns, c->buffer, worker->scratchpad, repinfo, acladdr->taglist,
|
||||
acladdr->taglen, acladdr->tag_actions,
|
||||
acladdr->tag_actions_size, acladdr->tag_datas,
|
||||
acladdr->tag_datas_size, worker->daemon->cfg->tagname,
|
||||
worker->daemon->cfg->num_tags)) {
|
||||
worker->daemon->cfg->num_tags, acladdr->view)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(sldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
@ -986,44 +972,70 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
goto send_reply;
|
||||
}
|
||||
h = query_info_hash(&qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
if(answer_from_cache(worker, &qinfo,
|
||||
(struct reply_info*)e->data,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
/* prefetch it if the prefetch TTL expired */
|
||||
if(worker->env.cfg->prefetch && *worker->env.now >=
|
||||
((struct reply_info*)e->data)->prefetch_ttl) {
|
||||
time_t leeway = ((struct reply_info*)e->
|
||||
data)->ttl - *worker->env.now;
|
||||
lock_rw_unlock(&e->lock);
|
||||
reply_and_prefetch(worker, &qinfo,
|
||||
sldns_buffer_read_u16_at(c->buffer, 2),
|
||||
repinfo, leeway);
|
||||
rc = 0;
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply_rc;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
||||
/* If we've found a local alias, replace the qname with the alias
|
||||
* target before resolving it. */
|
||||
if(qinfo.local_alias) {
|
||||
struct ub_packed_rrset_key* rrset = qinfo.local_alias->rrset;
|
||||
struct packed_rrset_data* d = rrset->entry.data;
|
||||
|
||||
/* Sanity check: our current implementation only supports
|
||||
* a single CNAME RRset as a local alias. */
|
||||
if(qinfo.local_alias->next ||
|
||||
rrset->rk.type != htons(LDNS_RR_TYPE_CNAME) ||
|
||||
d->count != 1) {
|
||||
log_err("assumption failure: unexpected local alias");
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
return 0; /* drop it */
|
||||
}
|
||||
verbose(VERB_ALGO, "answer from the cache failed");
|
||||
lock_rw_unlock(&e->lock);
|
||||
qinfo.qname = d->rr_data[0] + 2;
|
||||
qinfo.qname_len = d->rr_len[0] - 2;
|
||||
}
|
||||
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
|
||||
if(answer_norec_from_cache(worker, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
|
||||
if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) {
|
||||
h = query_info_hash(&qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
if(answer_from_cache(worker, &qinfo,
|
||||
(struct reply_info*)e->data,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
/* prefetch it if the prefetch TTL expired */
|
||||
if((worker->env.cfg->prefetch || worker->env.cfg->serve_expired)
|
||||
&& *worker->env.now >=
|
||||
((struct reply_info*)e->data)->prefetch_ttl) {
|
||||
time_t leeway = ((struct reply_info*)e->
|
||||
data)->ttl - *worker->env.now;
|
||||
if(((struct reply_info*)e->data)->ttl
|
||||
< *worker->env.now)
|
||||
leeway = 0;
|
||||
lock_rw_unlock(&e->lock);
|
||||
reply_and_prefetch(worker, &qinfo,
|
||||
sldns_buffer_read_u16_at(c->buffer, 2),
|
||||
repinfo, leeway);
|
||||
rc = 0;
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply_rc;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
verbose(VERB_ALGO, "answer from the cache failed");
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
|
||||
if(answer_norec_from_cache(worker, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
verbose(VERB_ALGO, "answer norec from cache -- "
|
||||
"need to validate or not primed");
|
||||
}
|
||||
verbose(VERB_ALGO, "answer norec from cache -- "
|
||||
"need to validate or not primed");
|
||||
}
|
||||
sldns_buffer_rewind(c->buffer);
|
||||
server_stats_querymiss(&worker->stats, worker);
|
||||
@ -1377,11 +1389,10 @@ worker_delete(struct worker* worker)
|
||||
}
|
||||
|
||||
struct outbound_entry*
|
||||
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
|
||||
int nocaps, struct edns_option* opt_list,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* q)
|
||||
worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream,
|
||||
struct module_qstate* q)
|
||||
{
|
||||
struct worker* worker = q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@ -1389,11 +1400,10 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
if(!e)
|
||||
return NULL;
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(worker->back, qname,
|
||||
qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
|
||||
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list,
|
||||
addr, addrlen, zone, zonelen, worker_handle_service_reply, e,
|
||||
worker->back->udp_buff);
|
||||
e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec,
|
||||
want_dnssec, nocaps, q->env->cfg->tcp_upstream,
|
||||
ssl_upstream, addr, addrlen, zone, zonelen, q,
|
||||
worker_handle_service_reply, e, worker->back->udp_buff, q->env);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@ -1433,14 +1443,13 @@ void worker_stop_accept(void* arg)
|
||||
}
|
||||
|
||||
/* --- fake callbacks for fptr_wlist to work --- */
|
||||
struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
|
||||
struct outbound_entry* libworker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo),
|
||||
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
@ -61,6 +61,7 @@ struct ub_randstate;
|
||||
struct regional;
|
||||
struct tube;
|
||||
struct daemon_remote;
|
||||
struct query_info;
|
||||
|
||||
/** worker commands */
|
||||
enum worker_commands {
|
||||
|
@ -825,8 +825,9 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
}
|
||||
|
||||
/* Store the generated response in cache. */
|
||||
if (!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, 0, 0, NULL, super->query_flags))
|
||||
if (!super->no_cache_store &&
|
||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, 0, 0, NULL, super->query_flags))
|
||||
log_err("out of memory");
|
||||
}
|
||||
|
||||
|
BIN
contrib/unbound/doc/CNAME-basedRedirectionDesignNotes.pdf
Normal file
BIN
contrib/unbound/doc/CNAME-basedRedirectionDesignNotes.pdf
Normal file
Binary file not shown.
@ -1,3 +1,177 @@
|
||||
8 December 2016: Wouter
|
||||
- Fix downcast warnings from visual studio in sldns code.
|
||||
|
||||
7 December 2016: Ralph
|
||||
- Add DSA support for OpenSSL 1.1.0
|
||||
- Fix remote control without cert for LibreSSL
|
||||
|
||||
6 December 2016: George
|
||||
- Added generic EDNS code for registering known EDNS option codes,
|
||||
bypassing the cache response stage and uniquifying mesh states. Four EDNS
|
||||
option lists were added to module_qstate (module_qstate.edns_opts_*) to
|
||||
store EDNS options from/to front/back side.
|
||||
- Added two flags to module_qstate (no_cache_lookup, no_cache_store) that
|
||||
control the modules' cache interactions.
|
||||
- Added code for registering inplace callback functions. The registered
|
||||
functions can be called just before replying with local data or Chaos,
|
||||
replying from cache, replying with SERVFAIL, replying with a resolved
|
||||
query, sending a query to a nameserver. The functions can inspect the
|
||||
available data and maybe change response/query related data (i.e. append
|
||||
EDNS options).
|
||||
- Updated Python module for the above.
|
||||
- Updated Python documentation.
|
||||
|
||||
5 December 2016: Ralph
|
||||
- Fix #1173: differ local-zone type deny from unset
|
||||
tag_actions element.
|
||||
|
||||
5 December 2016: Wouter
|
||||
- Fix #1170: document that 'inform' local-zone uses local-data.
|
||||
|
||||
1 December 2016: Ralph
|
||||
- hyphen as minus fix, by Andreas Schulze
|
||||
|
||||
30 November 2016: Ralph
|
||||
- Added local-zones and local-data bulk addition and removal
|
||||
functionality in unbound-control (local_zones, local_zones_remove,
|
||||
local_datas and local_datas_remove).
|
||||
- iana portlist update
|
||||
|
||||
29 November 2016: Wouter
|
||||
- version 1.6.0 is in the development branch.
|
||||
- braces in view.c around lock statements.
|
||||
|
||||
28 November 2016: Wouter
|
||||
- new install-sh.
|
||||
|
||||
25 November 2016: Wouter
|
||||
- Fix that with openssl 1.1 control-use-cert: no uses less cpu, by
|
||||
using no encryption over the unix socket.
|
||||
|
||||
22 Novenber 2016: Ralph
|
||||
- Make access-control-tag-data RDATA absolute. This makes the RDATA
|
||||
origin consistent between local-data and access-control-tag-data.
|
||||
- Fix NSEC ENT wildcard check. Matching wildcard does not have to be a
|
||||
subdomain of the NSEC owner.
|
||||
- QNAME minimisation uses QTYPE=A, therefore always check cache for
|
||||
this type in harden-below-nxdomain functionality.
|
||||
- Added unit test for QNAME minimisation + harden below nxdomain
|
||||
synergy.
|
||||
|
||||
22 November 2016: Wouter
|
||||
- iana portlist update.
|
||||
- Fix unit tests for DS hash processing for fake-dsa test option.
|
||||
- patch from Dag-Erling Smorgrav that removes code that relies
|
||||
on sbrk().
|
||||
|
||||
21 November 2016: Wouter
|
||||
- Fix #1158: reference RFC 8020 "NXDOMAIN: There Really Is Nothing
|
||||
Underneath" for the harden-below-nxdomain option.
|
||||
|
||||
10 November 2016: Ralph
|
||||
- Fix #1155: test status code of unbound-control in 04-checkconf,
|
||||
not the status code from the tee command.
|
||||
|
||||
4 November 2016: Ralph
|
||||
- Added stub-ssl-upstream and forward-ssl-upstream options.
|
||||
|
||||
4 November 2016: Wouter
|
||||
- configure detects ssl security level API function in the autoconf
|
||||
manner. Every function on its own, so that other libraries (eg.
|
||||
LibreSSL) can develop their API without hindrance.
|
||||
- Fix #1154: segfault when reading config with duplicate zones.
|
||||
- Note that for harden-below-nxdomain the nxdomain must be secure,
|
||||
this means nsec3 with optout is insufficient.
|
||||
|
||||
3 November 2016: Ralph
|
||||
- Set OpenSSL security level to 0 when using aNULL ciphers.
|
||||
|
||||
3 November 2016: Wouter
|
||||
- .gitattributes line for githubs code language display.
|
||||
- log-identity: config option to set sys log identity, patch from
|
||||
"Robin H. Johnson" <robbat2@gentoo.org>
|
||||
|
||||
2 November 2016: Wouter
|
||||
- iana portlist update.
|
||||
|
||||
31 October 2016: Wouter
|
||||
- Fix failure to build on arm64 with no sbrk.
|
||||
- iana portlist update.
|
||||
|
||||
28 October 2016: Wouter
|
||||
- Patch for server.num.zero_ttl stats for count of expired replies,
|
||||
from Pavel Odintsov.
|
||||
|
||||
26 October 2016: Wouter
|
||||
- Fix unit tests for openssl 1.1, with no DSA, by faking DSA, enabled
|
||||
with the undocumented switch 'fake-dsa'. It logs a warning.
|
||||
|
||||
25 October 2016: Wouter
|
||||
- Fix #1134: unbound-control set_option -- val-override-date: -1 works
|
||||
immediately to ignore datetime, or back to 0 to enable it again.
|
||||
The -- is to ignore the '-1' as an option flag.
|
||||
|
||||
24 October 2016: Wouter
|
||||
- serve-expired config option: serve expired responses with TTL 0.
|
||||
- g.root-servers.net has AAAA address.
|
||||
|
||||
21 October 2016: Wouter
|
||||
- Ported tests for local_cname unit test to testbound framework.
|
||||
|
||||
20 October 2016: Wouter
|
||||
- suppress compile warning in lex files.
|
||||
- init lzt variable, for older gcc compiler warnings.
|
||||
- fix --enable-dsa to work, instead of copying ecdsa enable.
|
||||
- Fix DNSSEC validation of query type ANY with DNAME answers.
|
||||
- Fixup query_info local_alias init.
|
||||
|
||||
19 October 2016: Wouter
|
||||
- Fix #1130: whitespace in example.conf.in more consistent.
|
||||
|
||||
18 October 2016: Wouter
|
||||
- Patch that resolves CNAMEs entered in local-data conf statements that
|
||||
point to data on the internet, from Jinmei Tatuya (Infoblox).
|
||||
- Removed patch comments from acllist.c and msgencode.c
|
||||
- Added documentation doc/CNAME-basedRedirectionDesignNotes.pdf,
|
||||
from Jinmei Tatuya (Infoblox).
|
||||
- Fix #1125: unbound could reuse an answer packet incorrectly for
|
||||
clients with different EDNS parameters, from Jinmei Tatuya.
|
||||
- Fix #1118: libunbound.pc sets strange Libs, Libs.private values.
|
||||
- Added Requires line to libunbound.pc
|
||||
- Please doxygen by modifying mesh.h
|
||||
|
||||
17 October 2016: Wouter
|
||||
- Re-fix #839 from view commit overwrite.
|
||||
- Fixup const void cast warning.
|
||||
|
||||
12 October 2016: Ralph
|
||||
- Free view config elements.
|
||||
|
||||
11 October 2016: Ralph
|
||||
- Added qname-minimisation-strict config option.
|
||||
- iana portlist update.
|
||||
- fix memoryleak logfile when in debug mode.
|
||||
|
||||
5 October 2016: Ralph
|
||||
- Added views functionality.
|
||||
- Fix #1117: spelling errors, from Robert Edmonds.
|
||||
|
||||
30 September 2016: Wouter
|
||||
- Fix Nits for 1.5.10 reported by Dag-Erling Smorgrav.
|
||||
|
||||
29 September 2016: Wouter
|
||||
- Fix #838: 1.5.10 cannot be built on Solaris, undefined PATH_MAX.
|
||||
- Fix #839: Memory grows unexpectedly with large RPZ files.
|
||||
- Fix #840: infinite loop in unbound_munin_ plugin on unowned lockfile.
|
||||
- Fix #841: big local-zone's make it consume large amounts of memory.
|
||||
|
||||
27 September 2016: Wouter
|
||||
- tag for 1.5.10 release
|
||||
- trunk contains 1.5.11 in development.
|
||||
- Fix dnstap relaying "random" messages instead of resolver/forwarder
|
||||
responses, from Nikolay Edigaryev.
|
||||
- Fix #836: unbound could echo back EDNS options in an error response.
|
||||
|
||||
20 September 2016: Wouter
|
||||
- iana portlist update.
|
||||
- Fix #835: fix --disable-dsa with nettle verify.
|
||||
|
@ -1,4 +1,4 @@
|
||||
README for Unbound 1.5.10
|
||||
README for Unbound 1.6.0
|
||||
Copyright 2007 NLnet Labs
|
||||
http://unbound.net
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Example configuration file.
|
||||
#
|
||||
# See unbound.conf(5) man page, version 1.5.10.
|
||||
# See unbound.conf(5) man page, version 1.6.0.
|
||||
#
|
||||
# this is a comment.
|
||||
|
||||
@ -52,7 +52,7 @@ server:
|
||||
# outgoing-interface: 192.0.2.153
|
||||
# outgoing-interface: 2001:DB8::5
|
||||
# outgoing-interface: 2001:DB8::6
|
||||
|
||||
|
||||
# Specify a netblock to use remainder 64 bits as random bits for
|
||||
# upstream queries. Uses freebind option (Linux).
|
||||
# outgoing-interface: 2001:DB8::/64
|
||||
@ -171,7 +171,7 @@ server:
|
||||
|
||||
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
|
||||
# infra-cache-numhosts: 10000
|
||||
|
||||
|
||||
# define a number of tags here, use with local-zone, access-control.
|
||||
# repeat the define-tag statement to add additional tags.
|
||||
# define-tag: "tag1 tag2 tag3"
|
||||
@ -230,6 +230,9 @@ server:
|
||||
# set redirect data for particular tag for access control element
|
||||
# access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
|
||||
|
||||
# Set view for access control element
|
||||
# access-control-view: 192.0.2.0/24 viewname
|
||||
|
||||
# if given, a chroot(2) is done to the given directory.
|
||||
# i.e. you can chroot to the working directory, for example,
|
||||
# for extra security, but make sure all files are in that directory.
|
||||
@ -272,9 +275,13 @@ server:
|
||||
# logfile: ""
|
||||
|
||||
# Log to syslog(3) if yes. The log facility LOG_DAEMON is used to
|
||||
# log to, with identity "unbound". If yes, it overrides the logfile.
|
||||
# log to. If yes, it overrides the logfile.
|
||||
# use-syslog: yes
|
||||
|
||||
# Log identity to report. if empty, defaults to the name of argv[0]
|
||||
# (usually "unbound").
|
||||
# log-identity: ""
|
||||
|
||||
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
|
||||
# log-time-ascii: no
|
||||
|
||||
@ -328,7 +335,7 @@ server:
|
||||
# Harden against queries that fall under dnssec-signed nxdomain names.
|
||||
# harden-below-nxdomain: no
|
||||
|
||||
# Harden the referral path by performing additional queries for
|
||||
# Harden the referral path by performing additional queries for
|
||||
# infrastructure data. Validates the replies (if possible).
|
||||
# Default off, because the lookups burden the server. Experimental
|
||||
# implementation of draft-wijngaards-dnsext-resolver-side-mitigation.
|
||||
@ -344,6 +351,12 @@ server:
|
||||
# to NS when possible.
|
||||
# qname-minimisation: no
|
||||
|
||||
# QNAME minimisation in strict mode. Do not fall-back to sending full
|
||||
# QNAME to potentially broken nameservers. A lot of domains will not be
|
||||
# resolvable when this option in enabled.
|
||||
# This option only has effect when qname-minimisation is enabled.
|
||||
# qname-minimisation-strict: no
|
||||
|
||||
# Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
# This feature is an experimental implementation of draft dns-0x20.
|
||||
# use-caps-for-id: no
|
||||
@ -477,6 +490,10 @@ server:
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
# Serve expired reponses from cache, with TTL 0 in the response,
|
||||
# and then attempt to fetch the data afresh.
|
||||
# serve-expired: no
|
||||
|
||||
# Have the validator log failed validations for your diagnosis.
|
||||
# 0: off. 1: A line per failed user query. 2: With reason and bad IP.
|
||||
# val-log-level: 0
|
||||
@ -578,7 +595,7 @@ server:
|
||||
# o redirect serves the zone data for any subdomain in the zone.
|
||||
# o nodefault can be used to normally resolve AS112 zones.
|
||||
# o typetransparent resolves normally for other types and other names
|
||||
# o inform resolves normally, but logs client IP address
|
||||
# o inform acts like transparent, but logs client IP address
|
||||
# o inform_deny drops queries and logs client IP address
|
||||
# o always_transparent, always_refuse, always_nxdomain, resolve in
|
||||
# that way but ignore local data for that name.
|
||||
@ -700,6 +717,7 @@ remote-control:
|
||||
# stub-addr: 192.0.2.68
|
||||
# stub-prime: no
|
||||
# stub-first: no
|
||||
# stub-ssl-upstream: no
|
||||
# stub-zone:
|
||||
# name: "example.org"
|
||||
# stub-host: ns.example.com.
|
||||
@ -715,6 +733,23 @@ remote-control:
|
||||
# forward-addr: 192.0.2.68
|
||||
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
|
||||
# forward-first: no
|
||||
# forward-ssl-upstream: no
|
||||
# forward-zone:
|
||||
# name: "example.org"
|
||||
# forward-host: fwd.example.com
|
||||
|
||||
# Views
|
||||
# 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
|
||||
# and local-data options. Options from matching views will override global
|
||||
# options. Global options will be used if no matching view is found.
|
||||
# With view-first yes, it will try to answer using the global local-zone and
|
||||
# local-data elements if there is no view specific match.
|
||||
# view:
|
||||
# name: "viewname"
|
||||
# local-zone: "example.com" redirect
|
||||
# local-data: "example.com A 192.0.2.3"
|
||||
# view-first: no
|
||||
# view:
|
||||
# name: "anotherview"
|
||||
# local-zone: "example.com" refuse
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "libunbound" "3" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
|
||||
.TH "libunbound" "3" "Dec 15, 2016" "NLnet Labs" "unbound 1.6.0"
|
||||
.\"
|
||||
.\" libunbound.3 -- unbound library functions manual
|
||||
.\"
|
||||
@ -43,7 +43,7 @@
|
||||
.B ub_ctx_zone_remove,
|
||||
.B ub_ctx_data_add,
|
||||
.B ub_ctx_data_remove
|
||||
\- Unbound DNS validating resolver 1.5.10 functions.
|
||||
\- Unbound DNS validating resolver 1.6.0 functions.
|
||||
.SH "SYNOPSIS"
|
||||
.B #include <unbound.h>
|
||||
.LP
|
||||
@ -180,7 +180,7 @@ and
|
||||
.B ub_ctx_hosts
|
||||
to read them.
|
||||
Before you call this, use the openssl functions CRYPTO_set_id_callback and
|
||||
CRYPTO_set_locking_callback to set up asyncronous operation if you use
|
||||
CRYPTO_set_locking_callback to set up asynchronous operation if you use
|
||||
lib openssl (the application calls these functions once for initialisation).
|
||||
Openssl 1.0.0 or later uses the CRYPTO_THREADID_set_callback function.
|
||||
.TP
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound-anchor" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
|
||||
.TH "unbound-anchor" "8" "Dec 15, 2016" "NLnet Labs" "unbound 1.6.0"
|
||||
.\"
|
||||
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
|
||||
.\"
|
||||
@ -67,7 +67,7 @@ List the builtin root key and builtin root update certificate on stdout.
|
||||
.B \-u \fIname
|
||||
The server name, it connects to https://name. Specify without https:// prefix.
|
||||
The default is "data.iana.org". It connects to the port specified with \-P.
|
||||
You can pass an IPv4 addres or IPv6 address (no brackets) if you want.
|
||||
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
|
||||
.TP
|
||||
.B \-x \fIpath
|
||||
The pathname to the root\-anchors.xml file on the server. (forms URL with \-u).
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound-checkconf" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
|
||||
.TH "unbound-checkconf" "8" "Dec 15, 2016" "NLnet Labs" "unbound 1.6.0"
|
||||
.\"
|
||||
.\" unbound-checkconf.8 -- unbound configuration checker manual
|
||||
.\"
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound-control" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
|
||||
.TH "unbound-control" "8" "Dec 15, 2016" "NLnet Labs" "unbound 1.6.0"
|
||||
.\"
|
||||
.\" unbound-control.8 -- unbound remote control manual
|
||||
.\"
|
||||
@ -99,6 +99,22 @@ but if the name has become an empty nonterminal (there is still data in
|
||||
domain names below the removed name), NOERROR nodata answers are the
|
||||
result for that name.
|
||||
.TP
|
||||
.B local_zones
|
||||
Add local zones read from stdin of unbound\-control. Input is read per line,
|
||||
with name space type on a line. For bulk additions.
|
||||
.TP
|
||||
.B local_zones_remove
|
||||
Remove local zones read from stdin of unbound\-control. Input is one name per
|
||||
line. For bulk removals.
|
||||
.TP
|
||||
.B local_datas
|
||||
Add local data RRs read from stdin of unbound\-control. Input is one RR per
|
||||
line. For bulk additions.
|
||||
.TP
|
||||
.B local_datas_remove
|
||||
Remove local data RRs read from stdin of unbound\-control. Input is one name per
|
||||
line. For bulk removals.
|
||||
.TP
|
||||
.B dump_cache
|
||||
The contents of the cache is printed in a text format to stdout. You can
|
||||
redirect it to a file to store the cache in a file.
|
||||
@ -263,6 +279,21 @@ estimated qps and qps limit from config. With +a it prints all domains, not
|
||||
just the ratelimited domains, with their estimated qps. The ratelimited
|
||||
domains return an error for uncached (new) queries, but cached queries work
|
||||
as normal.
|
||||
.TP
|
||||
.B view_list_local_zones \fIview\fR
|
||||
\fIlist_local_zones\fR for given view.
|
||||
.TP
|
||||
.B view_local_zone \fIview\fR \fIname\fR \fItype
|
||||
\fIlocal_zone\fR for given view.
|
||||
.TP
|
||||
.B view_local_zone_remove \fIview\fR \fIname
|
||||
\fIlocal_zone_remove\fR for given view.
|
||||
.TP
|
||||
.B view_local_data \fIview\fR \fIRR data...
|
||||
\fIlocal_data\fR for given view.
|
||||
.TP
|
||||
.B view_local_data_remove \fIview\fR \fIname
|
||||
\fIlocal_data_remove\fR for given view.
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-control program exits with status code 1 on error, 0 on success.
|
||||
.SH "SET UP"
|
||||
@ -301,6 +332,9 @@ and resulted in recursive processing, taking a slot in the requestlist.
|
||||
Not part of the recursivereplies (or the histogram thereof) or cachemiss,
|
||||
as a cache response was sent.
|
||||
.TP
|
||||
.I threadX.num.zero_ttl
|
||||
number of replies with ttl zero, because they served an expired cache entry.
|
||||
.TP
|
||||
.I threadX.num.recursivereplies
|
||||
The number of replies sent to queries that needed recursive processing. Could be smaller than threadX.num.cachemiss if due to timeouts no replies were sent for some queries.
|
||||
.TP
|
||||
@ -350,6 +384,9 @@ summed over threads.
|
||||
.I total.num.prefetch
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.zero_ttl
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.recursivereplies
|
||||
summed over threads.
|
||||
.TP
|
||||
@ -384,9 +421,6 @@ uptime since server boot in seconds.
|
||||
time since last statistics printout, in seconds.
|
||||
.SH EXTENDED STATISTICS
|
||||
.TP
|
||||
.I mem.total.sbrk
|
||||
If sbrk(2) is available, an estimate of the heap size of the program in number of bytes. Close to the total memory used by the program, as reported by top and ps. Could be wrong if the OS allocates memory non\-contiguously.
|
||||
.TP
|
||||
.I mem.cache.rrset
|
||||
Memory in bytes in use by the RRset cache.
|
||||
.TP
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound\-host" "1" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
|
||||
.TH "unbound\-host" "1" "Dec 15, 2016" "NLnet Labs" "unbound 1.6.0"
|
||||
.\"
|
||||
.\" unbound-host.1 -- unbound DNS lookup utility
|
||||
.\"
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
|
||||
.TH "unbound" "8" "Dec 15, 2016" "NLnet Labs" "unbound 1.6.0"
|
||||
.\"
|
||||
.\" unbound.8 -- unbound manual
|
||||
.\"
|
||||
@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.B unbound
|
||||
\- Unbound DNS validating resolver 1.5.10.
|
||||
\- Unbound DNS validating resolver 1.6.0.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound
|
||||
.RB [ \-h ]
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound.conf" "5" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
|
||||
.TH "unbound.conf" "5" "Dec 15, 2016" "NLnet Labs" "unbound 1.6.0"
|
||||
.\"
|
||||
.\" unbound.conf.5 -- unbound.conf manual
|
||||
.\"
|
||||
@ -151,8 +151,8 @@ netblock, or the randomisation will be compromised. Consider combining with
|
||||
to increase the likelihood of IPv6 nameservers being selected for queries.
|
||||
On Linux you need these two commands to be able to use the freebind socket
|
||||
option to receive traffic for the ip6 netblock:
|
||||
ip -6 addr add mynetblock/64 dev lo &&
|
||||
ip -6 route add local mynetblock/64 dev lo
|
||||
ip \-6 addr add mynetblock/64 dev lo &&
|
||||
ip \-6 route add local mynetblock/64 dev lo
|
||||
.TP
|
||||
.B outgoing\-range: \fI<number>
|
||||
Number of ports to open. This number of file descriptors can be opened per
|
||||
@ -474,6 +474,9 @@ order of the define-tag values.
|
||||
.B access\-control\-tag\-data: \fI<IP netblock> <tag> <"resource record string">
|
||||
Set redirect data for particular tag for given access control element.
|
||||
.TP
|
||||
.B access\-control\-view: \fI<IP netblock> <view name>
|
||||
Set view for given access control element.
|
||||
.TP
|
||||
.B chroot: \fI<directory>
|
||||
If chroot is enabled, you should pass the configfile (from the
|
||||
commandline) as a full path from the original root. After the
|
||||
@ -531,6 +534,13 @@ The log facility LOG_DAEMON is used, with identity "unbound".
|
||||
The logfile setting is overridden when use\-syslog is turned on.
|
||||
The default is to log to syslog.
|
||||
.TP
|
||||
.B log\-identity: \fI<string>
|
||||
If "" is given (default), then the name of the executable, usually "unbound"
|
||||
is used to report to the log. Enter a string to override it
|
||||
with that, which is useful on systems that run more than one instance of
|
||||
unbound, with different configurations, so that the logs can be easily
|
||||
distinguished against.
|
||||
.TP
|
||||
.B log\-time\-ascii: \fI<yes or no>
|
||||
Sets logfile lines to use a timestamp in UTC ascii. Default is no, which
|
||||
prints the seconds since 1970 in brackets. No effect if using syslog, in
|
||||
@ -614,14 +624,15 @@ unsigned to badly signed often. If turned off you run the risk of a
|
||||
downgrade attack that disables security for a zone. Default is on.
|
||||
.TP
|
||||
.B harden\-below\-nxdomain: \fI<yes or no>
|
||||
From draft\-vixie\-dnsext\-resimprove, returns nxdomain to queries for a name
|
||||
From RFC 8020 (with title "NXDOMAIN: There Really Is Nothing Underneath"),
|
||||
returns nxdomain to queries for a name
|
||||
below another name that is already known to be nxdomain. DNSSEC mandates
|
||||
noerror for empty nonterminals, hence this is possible. Very old software
|
||||
might return nxdomain for empty nonterminals (that usually happen for reverse
|
||||
IP address lookups), and thus may be incompatible with this. To try to avoid
|
||||
this only DNSSEC-secure nxdomains are used, because the old software does not
|
||||
have DNSSEC. Default is off.
|
||||
Currently, draft\-ietf\-dnsop\-nxdomain\-cut promotes this technique.
|
||||
The nxdomain must be secure, this means nsec3 with optout is insufficient.
|
||||
.TP
|
||||
.B harden\-referral\-path: \fI<yes or no>
|
||||
Harden the referral path by performing additional queries for
|
||||
@ -658,8 +669,15 @@ Can be given multiple times, for different domains.
|
||||
.B qname\-minimisation: \fI<yes or no>
|
||||
Send minimum amount of information to upstream servers to enhance privacy.
|
||||
Only sent minimum required labels of the QNAME and set QTYPE to NS when
|
||||
possible. Best effort approach, full QNAME and original QTYPE will be sent when
|
||||
upstream replies with a RCODE other than NOERROR. Default is off.
|
||||
possible. Best effort approach; full QNAME and original QTYPE will be sent when
|
||||
upstream replies with a RCODE other than NOERROR, except when receiving
|
||||
NXDOMAIN from a DNSSEC signed zone. Default is off.
|
||||
.TP
|
||||
.B qname\-minimisation\-strict: \fI<yes or no>
|
||||
QNAME minimisation in strict mode. Do not fall-back to sending full QNAME to
|
||||
potentially broken nameservers. A lot of domains will not be resolvable when
|
||||
this option in enabled. Only use if you know what you are doing.
|
||||
This option only has effect when qname-minimisation is enabled. Default is off.
|
||||
.TP
|
||||
.B private\-address: \fI<IP address or subnet>
|
||||
Give IPv4 of IPv6 addresses or classless subnets. These are addresses
|
||||
@ -859,6 +877,11 @@ servers that set the CD flag but cannot validate DNSSEC themselves are
|
||||
the clients, and then unbound provides them with DNSSEC protection.
|
||||
The default value is "no".
|
||||
.TP
|
||||
.B serve\-expired: \fI<yes or no>
|
||||
If enabled, unbound attempts to serve old responses from cache with a
|
||||
TTL of 0 in the response without waiting for the actual resolution to finish.
|
||||
The actual resolution answer ends up in the cache later on. Default is "no".
|
||||
.TP
|
||||
.B val\-nsec3\-keysize\-iterations: \fI<"list of values">
|
||||
List of keysize and iteration count values, separated by spaces, surrounded
|
||||
by quotes. Default is "1024 150 2048 500 4096 2500". This determines the
|
||||
@ -978,11 +1001,11 @@ queries for www.example.com and www.foo.example.com are redirected, so
|
||||
that users with web browsers cannot access sites with suffix example.com.
|
||||
.TP 10
|
||||
\h'5'\fIinform\fR
|
||||
The query is answered normally. The client IP address (@portnumber)
|
||||
is printed to the logfile. The log message is: timestamp, unbound-pid,
|
||||
info: zonename inform IP@port queryname type class. This option can be
|
||||
used for normal resolution, but machines looking up infected names are
|
||||
logged, eg. to run antivirus on them.
|
||||
The query is answered normally, same as transparent. The client IP
|
||||
address (@portnumber) is printed to the logfile. The log message is:
|
||||
timestamp, unbound-pid, info: zonename inform IP@port queryname type
|
||||
class. This option can be used for normal resolution, but machines
|
||||
looking up infected names are logged, eg. to run antivirus on them.
|
||||
.TP 10
|
||||
\h'5'\fIinform_deny\fR
|
||||
The query is dropped, like 'deny', and logged, like 'inform'. Ie. find
|
||||
@ -1280,6 +1303,10 @@ If enabled, a query is attempted without the stub clause if it fails.
|
||||
The data could not be retrieved and would have caused SERVFAIL because
|
||||
the servers are unreachable, instead it is tried without this clause.
|
||||
The default is no.
|
||||
.TP
|
||||
.B stub\-ssl\-upstream: \fI<yes or no>
|
||||
Enabled or disable whether the queries to this stub use SSL for transport.
|
||||
Default is no.
|
||||
.SS "Forward Zone Options"
|
||||
.LP
|
||||
There may be multiple
|
||||
@ -1310,6 +1337,36 @@ If enabled, a query is attempted without the forward clause if it fails.
|
||||
The data could not be retrieved and would have caused SERVFAIL because
|
||||
the servers are unreachable, instead it is tried without this clause.
|
||||
The default is no.
|
||||
.TP
|
||||
.B forward\-ssl\-upstream: \fI<yes or no>
|
||||
Enabled or disable whether the queries to this forwarder use SSL for transport.
|
||||
Default is no.
|
||||
.SS "View Options"
|
||||
.LP
|
||||
There may be multiple
|
||||
.B view:
|
||||
clauses. Each with a \fBname:\fR and zero or more \fBlocal\-zone\fR and
|
||||
\fBlocal\-data\fR elements. View can be mapped to requests by specifying the view
|
||||
name in an \fBaccess\-control\-view\fR element. Options from matching views will
|
||||
override global options. Global options will be used if no matching view
|
||||
is found.
|
||||
.TP
|
||||
.B name: \fI<view name>
|
||||
Name of the view. Must be unique. This name is used in access\-control\-view
|
||||
elements.
|
||||
.TP
|
||||
.B local\-zone: \fI<zone> <type>
|
||||
View specific local\-zone elements. Has the same types and behaviour as the
|
||||
global local\-zone elements.
|
||||
.TP
|
||||
.B local\-data: \fI"<resource record string>"
|
||||
View specific local\-data elements. Has the same behaviour as the global
|
||||
local\-data elements.
|
||||
.TP
|
||||
.B view\-first: \fI<yes or no>
|
||||
If enabled, it attempts to use the global local\-zone and local\-data if there
|
||||
is no match in the view specific options.
|
||||
The default is no.
|
||||
.SS "Python Module Options"
|
||||
.LP
|
||||
The
|
||||
|
@ -72,6 +72,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
return NULL;
|
||||
copy->bogus = dp->bogus;
|
||||
copy->has_parent_side_NS = dp->has_parent_side_NS;
|
||||
copy->ssl_upstream = dp->ssl_upstream;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(!delegpt_add_ns(copy, region, ns->name, ns->lame))
|
||||
return NULL;
|
||||
|
@ -81,6 +81,8 @@ struct delegpt {
|
||||
uint8_t has_parent_side_NS;
|
||||
/** for assertions on type of delegpt */
|
||||
uint8_t dp_type_mlc;
|
||||
/** use SSL for upstream query */
|
||||
uint8_t ssl_upstream;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -355,7 +357,7 @@ void delegpt_no_ipv4(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* create malloced delegation point, with the given name
|
||||
* @param name: uncompressed wireformat of degegpt name.
|
||||
* @param name: uncompressed wireformat of delegpt name.
|
||||
* @return NULL on alloc failure
|
||||
*/
|
||||
struct delegpt* delegpt_create_mlc(uint8_t* name);
|
||||
|
@ -265,6 +265,8 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
* last resort will ask for parent-side NS record and thus
|
||||
* fallback to the internet name servers on a failure */
|
||||
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
|
||||
/* use SSL for queries to this forwarder */
|
||||
dp->ssl_upstream = (uint8_t)s->ssl_upstream;
|
||||
verbose(VERB_QUERY, "Forward zone server list:");
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
|
||||
|
@ -149,6 +149,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
|
||||
if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
|
||||
if(!ah(dp, "G.ROOT-SERVERS.NET.", "2001:500:12::d0d")) goto failed;
|
||||
if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::53")) goto failed;
|
||||
if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
|
||||
if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed;
|
||||
@ -275,6 +276,8 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg)
|
||||
* last resort will ask for parent-side NS record and thus
|
||||
* fallback to the internet name servers on a failure */
|
||||
dp->has_parent_side_NS = (uint8_t)!s->isfirst;
|
||||
/* ssl_upstream */
|
||||
dp->ssl_upstream = (uint8_t)s->ssl_upstream;
|
||||
delegpt_log(VERB_QUERY, dp);
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime))
|
||||
return 0;
|
||||
|
@ -532,6 +532,7 @@ causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
|
||||
qinf.qname_len = namelen;
|
||||
qinf.qtype = t;
|
||||
qinf.qclass = c;
|
||||
qinf.local_alias = NULL;
|
||||
fptr_ok(fptr_whitelist_modenv_detect_cycle(
|
||||
qstate->env->detect_cycle));
|
||||
return (*qstate->env->detect_cycle)(qstate, &qinf,
|
||||
|
@ -230,9 +230,8 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
|
||||
return;
|
||||
} else {
|
||||
/* see if the failure did get (parent-lame) info */
|
||||
if(!cache_fill_missing(super->env,
|
||||
super_iq->qchase.qclass, super->region,
|
||||
super_iq->dp))
|
||||
if(!cache_fill_missing(super->env, super_iq->qchase.qclass,
|
||||
super->region, super_iq->dp))
|
||||
log_err("out of memory adding missing");
|
||||
}
|
||||
dpns->resolved = 1; /* mark as failed */
|
||||
@ -278,27 +277,29 @@ error_response(struct module_qstate* qstate, int id, int rcode)
|
||||
static int
|
||||
error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
{
|
||||
/* store in cache */
|
||||
struct reply_info err;
|
||||
if(qstate->prefetch_leeway > NORR_TTL) {
|
||||
verbose(VERB_ALGO, "error response for prefetch in cache");
|
||||
/* attempt to adjust the cache entry prefetch */
|
||||
if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
|
||||
NORR_TTL, qstate->query_flags))
|
||||
return error_response(qstate, id, rcode);
|
||||
/* if that fails (not in cache), fall through to store err */
|
||||
if(!qstate->no_cache_store) {
|
||||
/* store in cache */
|
||||
struct reply_info err;
|
||||
if(qstate->prefetch_leeway > NORR_TTL) {
|
||||
verbose(VERB_ALGO, "error response for prefetch in cache");
|
||||
/* attempt to adjust the cache entry prefetch */
|
||||
if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
|
||||
NORR_TTL, qstate->query_flags))
|
||||
return error_response(qstate, id, rcode);
|
||||
/* if that fails (not in cache), fall through to store err */
|
||||
}
|
||||
memset(&err, 0, sizeof(err));
|
||||
err.flags = (uint16_t)(BIT_QR | BIT_RA);
|
||||
FLAGS_SET_RCODE(err.flags, rcode);
|
||||
err.qdcount = 1;
|
||||
err.ttl = NORR_TTL;
|
||||
err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
|
||||
/* do not waste time trying to validate this servfail */
|
||||
err.security = sec_status_indeterminate;
|
||||
verbose(VERB_ALGO, "store error response in message cache");
|
||||
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
|
||||
qstate->query_flags);
|
||||
}
|
||||
memset(&err, 0, sizeof(err));
|
||||
err.flags = (uint16_t)(BIT_QR | BIT_RA);
|
||||
FLAGS_SET_RCODE(err.flags, rcode);
|
||||
err.qdcount = 1;
|
||||
err.ttl = NORR_TTL;
|
||||
err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
|
||||
/* do not waste time trying to validate this servfail */
|
||||
err.security = sec_status_indeterminate;
|
||||
verbose(VERB_ALGO, "store error response in message cache");
|
||||
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
|
||||
qstate->query_flags);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
|
||||
@ -551,6 +552,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
qinf.qname_len = qnamelen;
|
||||
qinf.qtype = qtype;
|
||||
qinf.qclass = qclass;
|
||||
qinf.local_alias = NULL;
|
||||
|
||||
/* RD should be set only when sending the query back through the INIT
|
||||
* state. */
|
||||
@ -968,7 +970,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
{
|
||||
uint8_t* delname;
|
||||
size_t delnamelen;
|
||||
struct dns_msg* msg;
|
||||
struct dns_msg* msg = NULL;
|
||||
|
||||
log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo);
|
||||
/* check effort */
|
||||
@ -1008,13 +1010,13 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* getting older results from cache is a bad idea, no cache */
|
||||
verbose(VERB_ALGO, "cache blacklisted, going to the network");
|
||||
msg = NULL;
|
||||
} else {
|
||||
} else if(!qstate->no_cache_lookup) {
|
||||
msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
|
||||
iq->qchase.qname_len, iq->qchase.qtype,
|
||||
iq->qchase.qclass, qstate->query_flags,
|
||||
qstate->region, qstate->env->scratch);
|
||||
if(!msg && qstate->env->neg_cache) {
|
||||
/* lookup in negative cache; may result in
|
||||
/* lookup in negative cache; may result in
|
||||
* NOERROR/NODATA or NXDOMAIN answers that need validation */
|
||||
msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
|
||||
qstate->region, qstate->env->rrset_cache,
|
||||
@ -1700,10 +1702,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* if this was a parent-side glue query itself, then store that
|
||||
* failure in cache. */
|
||||
if(iq->query_for_pside_glue && !iq->pside_glue)
|
||||
iter_store_parentside_neg(qstate->env, &qstate->qinfo,
|
||||
iq->deleg_msg?iq->deleg_msg->rep:
|
||||
(iq->response?iq->response->rep:NULL));
|
||||
if(!qstate->no_cache_store && iq->query_for_pside_glue
|
||||
&& !iq->pside_glue)
|
||||
iter_store_parentside_neg(qstate->env, &qstate->qinfo,
|
||||
iq->deleg_msg?iq->deleg_msg->rep:
|
||||
(iq->response?iq->response->rep:NULL));
|
||||
|
||||
verbose(VERB_QUERY, "out of query targets -- returning SERVFAIL");
|
||||
/* fail -- no more targets, no more hope of targets, no hope
|
||||
@ -1787,8 +1790,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int tf_policy;
|
||||
struct delegpt_addr* target;
|
||||
struct outbound_entry* outq;
|
||||
/* EDNS options to set on outgoing packet */
|
||||
struct edns_option* opt_list = NULL;
|
||||
|
||||
/* NOTE: a request will encounter this state for each target it
|
||||
* needs to send a query to. That is, at least one per referral,
|
||||
@ -2011,6 +2012,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->qinfo_out.qname_len = iq->dp->namelen;
|
||||
iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
|
||||
iq->qinfo_out.qclass = iq->qchase.qclass;
|
||||
iq->qinfo_out.local_alias = NULL;
|
||||
iq->minimise_count = 0;
|
||||
}
|
||||
|
||||
@ -2068,7 +2070,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|| iq->qchase.qtype == LDNS_RR_TYPE_A)))
|
||||
/* Stop minimising this query, resolve "as usual" */
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
else {
|
||||
else if(!qstate->no_cache_lookup) {
|
||||
struct dns_msg* msg = dns_cache_lookup(qstate->env,
|
||||
iq->qinfo_out.qname, iq->qinfo_out.qname_len,
|
||||
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
|
||||
@ -2088,7 +2090,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* Do not increment qname, continue incrementing next
|
||||
* iteration */
|
||||
iq->minimisation_state = MINIMISE_STATE;
|
||||
else
|
||||
else if(!qstate->env->cfg->qname_minimisation_strict)
|
||||
/* Too many time-outs detected for this QNAME and QTYPE.
|
||||
* We give up, disable QNAME minimisation. */
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
@ -2106,9 +2108,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dnssec_lame_query?" but lame_query anyway": "");
|
||||
}
|
||||
fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
|
||||
outq = (*qstate->env->send_query)(
|
||||
iq->qinfo_out.qname, iq->qinfo_out.qname_len,
|
||||
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
|
||||
outq = (*qstate->env->send_query)(&iq->qinfo_out,
|
||||
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
|
||||
/* unset CD if to forwarder(RD set) and not dnssec retry
|
||||
* (blacklist nonempty) and no trust-anchors are configured
|
||||
@ -2117,8 +2117,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
!qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env,
|
||||
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
|
||||
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
|
||||
ie, iq), opt_list, &target->addr, target->addrlen,
|
||||
iq->dp->name, iq->dp->namelen, qstate);
|
||||
ie, iq), &target->addr, target->addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), qstate);
|
||||
if(!outq) {
|
||||
log_addr(VERB_DETAIL, "error sending query to auth server",
|
||||
&target->addr, target->addrlen);
|
||||
@ -2259,10 +2260,11 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->num_target_queries = 0;
|
||||
return processDSNSFind(qstate, iq, id);
|
||||
}
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region, qstate->query_flags);
|
||||
if(!qstate->no_cache_store)
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region, qstate->query_flags);
|
||||
/* close down outstanding requests to be discarded */
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
@ -2275,12 +2277,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
qstate->region);
|
||||
if(iq->minimisation_state != DONOT_MINIMISE_STATE) {
|
||||
/* Best effort qname-minimisation.
|
||||
* Stop minimising and send full query when RCODE
|
||||
* is not NOERROR. */
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
|
||||
LDNS_RCODE_NOERROR)
|
||||
LDNS_RCODE_NOERROR) {
|
||||
if(qstate->env->cfg->qname_minimisation_strict)
|
||||
return final_state(iq);
|
||||
/* Best effort qname-minimisation.
|
||||
* Stop minimising and send full query when
|
||||
* RCODE is not NOERROR. */
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
}
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
/* Stop resolving when NXDOMAIN is DNSSEC
|
||||
@ -2327,7 +2332,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
|
||||
/* if hardened, only store referral if we asked for it */
|
||||
if(!qstate->env->cfg->harden_referral_path ||
|
||||
if(!qstate->no_cache_store &&
|
||||
(!qstate->env->cfg->harden_referral_path ||
|
||||
( qstate->qinfo.qtype == LDNS_RR_TYPE_NS
|
||||
&& (qstate->query_flags&BIT_RD)
|
||||
&& !(qstate->query_flags&BIT_CD)
|
||||
@ -2342,7 +2348,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->qchase.qname, iq->qchase.qname_len,
|
||||
LDNS_RR_TYPE_NS, iq->qchase.qclass)
|
||||
)
|
||||
)) {
|
||||
))) {
|
||||
/* Store the referral under the current query */
|
||||
/* no prefetch-leeway, since its not the answer */
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
@ -2355,16 +2361,17 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->response->rep, iq->dp->name);
|
||||
}
|
||||
/* store parent-side-in-zone-glue, if directly queried for */
|
||||
if(iq->query_for_pside_glue && !iq->pside_glue) {
|
||||
iq->pside_glue = reply_find_rrset(iq->response->rep,
|
||||
iq->qchase.qname, iq->qchase.qname_len,
|
||||
iq->qchase.qtype, iq->qchase.qclass);
|
||||
if(iq->pside_glue) {
|
||||
log_rrset_key(VERB_ALGO, "found parent-side "
|
||||
"glue", iq->pside_glue);
|
||||
iter_store_parentside_rrset(qstate->env,
|
||||
iq->pside_glue);
|
||||
}
|
||||
if(!qstate->no_cache_store && iq->query_for_pside_glue
|
||||
&& !iq->pside_glue) {
|
||||
iq->pside_glue = reply_find_rrset(iq->response->rep,
|
||||
iq->qchase.qname, iq->qchase.qname_len,
|
||||
iq->qchase.qtype, iq->qchase.qclass);
|
||||
if(iq->pside_glue) {
|
||||
log_rrset_key(VERB_ALGO, "found parent-side "
|
||||
"glue", iq->pside_glue);
|
||||
iter_store_parentside_rrset(qstate->env,
|
||||
iq->pside_glue);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the event state, setting the current delegation
|
||||
@ -2445,10 +2452,11 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* NOTE : set referral=1, so that rrsets get stored but not
|
||||
* the partial query answer (CNAME only). */
|
||||
/* prefetchleeway applied because this updates answer parts */
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS, NULL,
|
||||
qstate->query_flags);
|
||||
if(!qstate->no_cache_store)
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS, NULL,
|
||||
qstate->query_flags);
|
||||
/* set the current request's qname to the new value. */
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = snamelen;
|
||||
@ -2527,7 +2535,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* LAME, THROWAWAY and "unknown" all end up here.
|
||||
* Recycle to the QUERYTARGETS state to hopefully try a
|
||||
* different target. */
|
||||
if (qstate->env->cfg->qname_minimisation)
|
||||
if (qstate->env->cfg->qname_minimisation &&
|
||||
!qstate->env->cfg->qname_minimisation_strict)
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
@ -2927,10 +2936,11 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
&qstate->qinfo);
|
||||
|
||||
/* store negative cache element for parent side glue. */
|
||||
if(iq->query_for_pside_glue && !iq->pside_glue)
|
||||
iter_store_parentside_neg(qstate->env, &qstate->qinfo,
|
||||
iq->deleg_msg?iq->deleg_msg->rep:
|
||||
(iq->response?iq->response->rep:NULL));
|
||||
if(!qstate->no_cache_store && iq->query_for_pside_glue
|
||||
&& !iq->pside_glue)
|
||||
iter_store_parentside_neg(qstate->env, &qstate->qinfo,
|
||||
iq->deleg_msg?iq->deleg_msg->rep:
|
||||
(iq->response?iq->response->rep:NULL));
|
||||
if(!iq->response) {
|
||||
verbose(VERB_ALGO, "No response is set, servfail");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
@ -2966,7 +2976,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* store message with the finished prepended items,
|
||||
* but only if we did recursion. The nonrecursion referral
|
||||
* from cache does not need to be stored in the msg cache. */
|
||||
if(qstate->query_flags&BIT_RD) {
|
||||
if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) {
|
||||
iter_dns_store(qstate->env, &qstate->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
@ -3141,6 +3151,18 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
|
||||
LDNS_RCODE_NOERROR)
|
||||
goto handle_it;
|
||||
|
||||
/* Copy the edns options we may got from the back end */
|
||||
if(edns.opt_list) {
|
||||
qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list,
|
||||
qstate->region);
|
||||
if(!qstate->edns_opts_back_in) {
|
||||
log_err("out of memory on incoming message");
|
||||
/* like packet got dropped */
|
||||
goto handle_it;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove CD-bit, we asked for in case we handle validation ourself */
|
||||
prs->flags &= ~BIT_CD;
|
||||
|
||||
|
@ -62,6 +62,7 @@ context_finalize(struct ub_ctx* ctx)
|
||||
config_apply(cfg);
|
||||
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
|
||||
return UB_INITFAIL;
|
||||
log_edns_known_options(VERB_ALGO, ctx->env);
|
||||
ctx->local_zones = local_zones_create();
|
||||
if(!ctx->local_zones)
|
||||
return UB_NOMEM;
|
||||
|
@ -132,6 +132,15 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
/* init edns_known_options */
|
||||
if(!edns_known_options_init(ctx->env)) {
|
||||
config_delete(ctx->env->cfg);
|
||||
free(ctx->env);
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
free(ctx);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
ctx->env->alloc = &ctx->superalloc;
|
||||
ctx->env->worker = NULL;
|
||||
ctx->env->need_to_validate = 0;
|
||||
@ -151,6 +160,7 @@ ub_ctx_create(void)
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
config_delete(ctx->env->cfg);
|
||||
modstack_desetup(&ctx->mods, ctx->env);
|
||||
edns_known_options_delete(ctx->env);
|
||||
free(ctx->env);
|
||||
free(ctx);
|
||||
errno = e;
|
||||
@ -162,6 +172,7 @@ ub_ctx_create(void)
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
config_delete(ctx->env->cfg);
|
||||
modstack_desetup(&ctx->mods, ctx->env);
|
||||
edns_known_options_delete(ctx->env);
|
||||
free(ctx->env);
|
||||
free(ctx);
|
||||
errno = e;
|
||||
@ -298,6 +309,8 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
rrset_cache_delete(ctx->env->rrset_cache);
|
||||
infra_delete(ctx->env->infra_cache);
|
||||
config_delete(ctx->env->cfg);
|
||||
edns_known_options_delete(ctx->env);
|
||||
inplace_cb_lists_delete(ctx->env);
|
||||
free(ctx->env);
|
||||
}
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
|
@ -573,10 +573,12 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
|
||||
{
|
||||
qinfo->qtype = (uint16_t)q->res->qtype;
|
||||
qinfo->qclass = (uint16_t)q->res->qclass;
|
||||
qinfo->local_alias = NULL;
|
||||
qinfo->qname = sldns_str2wire_dname(q->res->qname, &qinfo->qname_len);
|
||||
if(!qinfo->qname) {
|
||||
return 0;
|
||||
}
|
||||
qinfo->local_alias = NULL;
|
||||
edns->edns_present = 1;
|
||||
edns->ext_rcode = 0;
|
||||
edns->edns_version = 0;
|
||||
@ -607,9 +609,9 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
/* see if there is a fixed answer */
|
||||
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
|
||||
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
|
||||
if(local_zones_answer(ctx->local_zones, &qinfo, &edns,
|
||||
if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns,
|
||||
w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
|
||||
NULL, 0, NULL, 0)) {
|
||||
NULL, 0, NULL, 0, NULL)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
|
||||
w->back->udp_buff, sec_status_insecure, NULL);
|
||||
@ -678,9 +680,9 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
||||
/* see if there is a fixed answer */
|
||||
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
|
||||
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
|
||||
if(local_zones_answer(ctx->local_zones, &qinfo, &edns,
|
||||
if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns,
|
||||
w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
|
||||
NULL, 0, NULL, 0)) {
|
||||
NULL, 0, NULL, 0, NULL)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
free(qinfo.qname);
|
||||
libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
|
||||
@ -799,9 +801,9 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
/* see if there is a fixed answer */
|
||||
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
|
||||
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
|
||||
if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns,
|
||||
if(local_zones_answer(w->ctx->local_zones, w->env, &qinfo, &edns,
|
||||
w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
|
||||
NULL, 0, NULL, 0)) {
|
||||
NULL, 0, NULL, 0, NULL)) {
|
||||
regional_free_all(w->env->scratch);
|
||||
q->msg_security = sec_status_insecure;
|
||||
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
|
||||
@ -824,11 +826,10 @@ void libworker_alloc_cleanup(void* arg)
|
||||
slabhash_clear(w->env->msg_cache);
|
||||
}
|
||||
|
||||
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, struct edns_option* opt_list,
|
||||
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* q)
|
||||
size_t zonelen, int ssl_upstream, struct module_qstate* q)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@ -836,11 +837,10 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
if(!e)
|
||||
return NULL;
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(w->back, qname,
|
||||
qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
|
||||
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list,
|
||||
addr, addrlen, zone, zonelen, libworker_handle_service_reply,
|
||||
e, w->back->udp_buff);
|
||||
e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
|
||||
want_dnssec, nocaps, q->env->cfg->tcp_upstream, ssl_upstream,
|
||||
addr, addrlen, zone, zonelen, q, libworker_handle_service_reply,
|
||||
e, w->back->udp_buff, q->env);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@ -955,14 +955,12 @@ void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
|
||||
struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
|
||||
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* libunbound/worker.h - worker thread or process that resolves
|
||||
* libunbound/libworker.h - worker thread or process that resolves
|
||||
*
|
||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
*
|
||||
@ -59,6 +59,7 @@ struct regional;
|
||||
struct tube;
|
||||
struct sldns_buffer;
|
||||
struct ub_event_base;
|
||||
struct query_info;
|
||||
|
||||
/**
|
||||
* The library-worker status structure
|
||||
|
@ -82,10 +82,13 @@
|
||||
# Options for HTML output
|
||||
# -----------------------
|
||||
|
||||
# The theme that the html output should use.
|
||||
html_theme = "classic"
|
||||
|
||||
# The style sheet to use for HTML and HTML Help pages. A file of that name
|
||||
# must exist either in Sphinx' static/ path, or in one of the custom paths
|
||||
# given in html_static_path.
|
||||
html_style = 'default.css'
|
||||
#html_style = 'default.css'
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
|
@ -1,26 +1,33 @@
|
||||
.. _example_resolve_name:
|
||||
|
||||
==============================
|
||||
Resolve a name
|
||||
==============================
|
||||
==============
|
||||
|
||||
This basic example shows how to create a context and resolve a host address (DNS record of A type).
|
||||
This basic example shows how to create a context and resolve a host address
|
||||
(DNS record of A type).
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
import unbound
|
||||
|
||||
ctx = unbound.ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
status, result = ctx.resolve("www.google.com")
|
||||
if status == 0 and result.havedata:
|
||||
print "Result.data:", result.data.address_list
|
||||
elif status != 0:
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
#!/usr/bin/python
|
||||
import unbound
|
||||
|
||||
In contrast with C API, the source code is more compact while the performance of C implementation is preserved.
|
||||
The main advantage is that you need not take care about the deallocation and allocation of context and result structures; pyUnbound module do it automatically for you.
|
||||
ctx = unbound.ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
If only domain name is given, the :meth:`unbound.ub_ctx.resolve` looks for A records in IN class.
|
||||
status, result = ctx.resolve("www.google.com")
|
||||
if status == 0 and result.havedata:
|
||||
print "Result.data:", result.data.address_list
|
||||
elif status != 0:
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
|
||||
In contrast with the C API, the source code is more compact while the
|
||||
performance of C implementation is preserved.
|
||||
The main advantage is that you need not take care about the deallocation and
|
||||
allocation of context and result structures; pyUnbound module does it
|
||||
automatically for you.
|
||||
|
||||
If only domain name is given, the :meth:`unbound.ub_ctx.resolve` looks for
|
||||
A records in IN class.
|
||||
|
@ -1,33 +1,37 @@
|
||||
.. _example_reverse_lookup:
|
||||
|
||||
==============================
|
||||
Reverse DNS lookup
|
||||
==============================
|
||||
==================
|
||||
|
||||
Reverse DNS lookup involves determining the hostname associated with a given IP address.
|
||||
Reverse DNS lookup involves determining the hostname associated with a given IP
|
||||
address.
|
||||
This example shows how reverse lookup can be done using unbound module.
|
||||
|
||||
For the reverse DNS records, the special domain in-addr.arpa is reserved.
|
||||
For example, a host name for the IP address 74.125.43.147 can be obtained by issuing a DNS query for the PTR record for address 147.43.125.74.in-addr.arpa.
|
||||
For example, a host name for the IP address ``74.125.43.147`` can be obtained
|
||||
by issuing a DNS query for the PTR record for address
|
||||
``147.43.125.74.in-addr.arpa.``
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
import unbound
|
||||
|
||||
ctx = unbound.ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
print "Result.data:", result.data.domain_list
|
||||
elif status != 0:
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
#!/usr/bin/python
|
||||
import unbound
|
||||
|
||||
In order to simplify the python code, unbound module contains function which reverses the hostname components.
|
||||
ctx = unbound.ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
status, result = ctx.resolve(unbound.reverse("74.125.43.147") + ".in-addr.arpa.", unbound.RR_TYPE_PTR, unbound.RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
print "Result.data:", result.data.domain_list
|
||||
elif status != 0:
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
|
||||
In order to simplify the python code, unbound module contains the
|
||||
:meth:`unbound.reverse` function which reverses the hostname components.
|
||||
This function is defined as follows::
|
||||
|
||||
def reverse(domain):
|
||||
return '.'.join([a for a in domain.split(".")][::-1])
|
||||
|
||||
|
||||
def reverse(domain):
|
||||
return '.'.join([a for a in domain.split(".")][::-1])
|
||||
|
@ -1,41 +1,41 @@
|
||||
.. _example_setup_ctx:
|
||||
|
||||
==============================
|
||||
Lookup from threads
|
||||
==============================
|
||||
===================
|
||||
|
||||
This example shows how to use unbound module from a threaded program.
|
||||
In this example, three lookup threads are created which work in background.
|
||||
Each thread resolves different DNS record.
|
||||
This example shows how to use unbound module from a threaded program.
|
||||
In this example, three lookup threads are created which work in background.
|
||||
Each thread resolves different DNS record.
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
from unbound import ub_ctx, RR_TYPE_A, RR_CLASS_IN
|
||||
from threading import Thread
|
||||
|
||||
ctx = ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
class LookupThread(Thread):
|
||||
def __init__(self,ctx, name):
|
||||
Thread.__init__(self)
|
||||
self.ctx = ctx
|
||||
self.name = name
|
||||
#!/usr/bin/python
|
||||
from unbound import ub_ctx, RR_TYPE_A, RR_CLASS_IN
|
||||
from threading import Thread
|
||||
|
||||
def run(self):
|
||||
print "Thread lookup started:",self.name
|
||||
status, result = self.ctx.resolve(self.name, RR_TYPE_A, RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
print " Result:",self.name,":", result.data.address_list
|
||||
|
||||
threads = []
|
||||
for name in ["www.fit.vutbr.cz","www.vutbr.cz","www.google.com"]:
|
||||
thread = LookupThread(ctx, name)
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
ctx = ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
|
||||
class LookupThread(Thread):
|
||||
def __init__(self,ctx, name):
|
||||
Thread.__init__(self)
|
||||
self.ctx = ctx
|
||||
self.name = name
|
||||
|
||||
def run(self):
|
||||
print "Thread lookup started:",self.name
|
||||
status, result = self.ctx.resolve(self.name, RR_TYPE_A, RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
print " Result:",self.name,":", result.data.address_list
|
||||
|
||||
threads = []
|
||||
for name in ["www.fit.vutbr.cz","www.vutbr.cz","www.google.com"]:
|
||||
thread = LookupThread(ctx, name)
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
@ -1,12 +1,14 @@
|
||||
.. _example_asynch:
|
||||
|
||||
==============================
|
||||
Asynchronous lookup
|
||||
==============================
|
||||
===================
|
||||
|
||||
This example performs the name lookup in the background.
|
||||
The main program keeps running while the name is resolved.
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
@ -33,4 +35,5 @@ The main program keeps running while the name is resolved.
|
||||
if (status != 0):
|
||||
print "Resolve error:", unbound.ub_strerror(status)
|
||||
|
||||
The :meth:`unbound.ub_ctx.resolve_async` method is able to pass on any Python object. In this example, we used a dictionary object `my_data`.
|
||||
The :meth:`unbound.ub_ctx.resolve_async` method is able to pass on any Python
|
||||
object. In this example, we used a dictionary object ``my_data``.
|
||||
|
@ -1,33 +1,35 @@
|
||||
.. _example_examine:
|
||||
|
||||
==============================
|
||||
DNSSEC validator
|
||||
==============================
|
||||
================
|
||||
|
||||
This example program performs DNSSEC validation of a DNS lookup.
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN
|
||||
|
||||
ctx = ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
if (os.path.isfile("keys")):
|
||||
ctx.add_ta_file("keys") #read public keys for DNSSEC verification
|
||||
|
||||
status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
|
||||
print "Result:", result.data.address_list
|
||||
|
||||
if result.secure:
|
||||
print "Result is secure"
|
||||
elif result.bogus:
|
||||
print "Result is bogus"
|
||||
else:
|
||||
print "Result is insecure"
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
from unbound import ub_ctx,RR_TYPE_A,RR_CLASS_IN
|
||||
|
||||
ctx = ub_ctx()
|
||||
ctx.resolvconf("/etc/resolv.conf")
|
||||
if (os.path.isfile("keys")):
|
||||
ctx.add_ta_file("keys") #read public keys for DNSSEC verification
|
||||
|
||||
status, result = ctx.resolve("www.nic.cz", RR_TYPE_A, RR_CLASS_IN)
|
||||
if status == 0 and result.havedata:
|
||||
|
||||
print "Result:", result.data.address_list
|
||||
|
||||
if result.secure:
|
||||
print "Result is secure"
|
||||
elif result.bogus:
|
||||
print "Result is bogus"
|
||||
else:
|
||||
print "Result is insecure"
|
||||
|
||||
More detailed informations can be seen in libUnbound DNSSEC tutorial `here`_.
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
.. _example_resolver_only:
|
||||
|
||||
==============================
|
||||
Resolver only
|
||||
==============================
|
||||
=============
|
||||
|
||||
This example program shows how to perform DNS resolution only.
|
||||
Unbound contains two basic modules: resolver and validator.
|
||||
In case, the validator is not necessary, the validator module can be turned off using "module-config" option.
|
||||
This option contains a list of module names separated by the space char. This list determined which modules should be employed and in what order.
|
||||
In case, the validator is not necessary, the validator module can be turned off
|
||||
using "module-config" option.
|
||||
This option contains a list of module names separated by the space char. This
|
||||
list determined which modules should be employed and in what order.
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
@ -25,5 +29,6 @@ This option contains a list of module names separated by the space char. This li
|
||||
print "Result:", result.data.address_list
|
||||
|
||||
.. note::
|
||||
The :meth:`unbound.ub_ctx.set_option` method must be used before the first resolution (i.e. before :meth:`unbound.ub_ctx.resolve` or :meth:`unbound.ub_ctx.resolve_async` call).
|
||||
|
||||
The :meth:`unbound.ub_ctx.set_option` method must be used before the first
|
||||
resolution (i.e. before :meth:`unbound.ub_ctx.resolve` or
|
||||
:meth:`unbound.ub_ctx.resolve_async` call).
|
||||
|
@ -1,11 +1,13 @@
|
||||
.. _example_localzone:
|
||||
|
||||
==============================
|
||||
Local zone manipulation
|
||||
==============================
|
||||
=======================
|
||||
|
||||
This example program shows how to define local zone containing custom DNS records.
|
||||
This example program shows how to define local zone containing custom DNS
|
||||
records.
|
||||
|
||||
.. literalinclude:: example6-1.py
|
||||
:language: python
|
||||
Source code
|
||||
-----------
|
||||
|
||||
.. literalinclude:: example6-1.py
|
||||
:language: python
|
||||
|
@ -1,18 +1,33 @@
|
||||
.. _example_idna:
|
||||
|
||||
=================================================
|
||||
Internationalized domain name support
|
||||
=================================================
|
||||
=====================================
|
||||
|
||||
Unlike the libUnbound, pyUnbound is able to handle IDN queries.
|
||||
|
||||
.. literalinclude:: example7-1.py
|
||||
:language: python
|
||||
Automatic IDN DNAME conversion
|
||||
-------------------------------
|
||||
|
||||
If we use unicode string in :meth:`unbound.ub_ctx.resolve` method, the IDN DNAME conversion (if it is necessary) is performed on background.
|
||||
If we use unicode string in :meth:`unbound.ub_ctx.resolve` method,
|
||||
the IDN DNAME conversion (if it is necessary) is performed on background.
|
||||
|
||||
.. literalinclude:: example7-2.py
|
||||
:language: python
|
||||
Source code
|
||||
...........
|
||||
|
||||
The :class:`unbound.ub_data` class contains attributes suffix which converts the dname to UTF string. These attributes have the '_idn' suffix.
|
||||
Apart from this aproach, two conversion functions exist (:func:`unbound.idn2dname` and :func:`unbound.dname2idn`).
|
||||
.. literalinclude:: example7-1.py
|
||||
:language: python
|
||||
|
||||
IDN converted attributes
|
||||
------------------------
|
||||
|
||||
The :class:`unbound.ub_data` class contains attributes suffix which converts
|
||||
the dname to UTF string. These attributes have the ``_idn`` suffix.
|
||||
|
||||
Apart from this aproach, two conversion functions exist
|
||||
(:func:`unbound.idn2dname` and :func:`unbound.dname2idn`).
|
||||
|
||||
Source code
|
||||
...........
|
||||
|
||||
.. literalinclude:: example7-2.py
|
||||
:language: python
|
||||
|
@ -1,28 +1,34 @@
|
||||
.. _example_mxlookup:
|
||||
|
||||
=================================================
|
||||
Lookup for MX and NS records
|
||||
=================================================
|
||||
============================
|
||||
|
||||
The pyUnbound extension provides functions which are able to encode RAW RDATA produces by unbound resolver (see :class:`unbound.ub_data`).
|
||||
The pyUnbound extension provides functions which are able to encode RAW RDATA
|
||||
produces by unbound resolver (see :class:`unbound.ub_data`).
|
||||
|
||||
.. literalinclude:: example8-1.py
|
||||
:language: python
|
||||
Source code
|
||||
-----------
|
||||
|
||||
Previous example produces following output::
|
||||
.. literalinclude:: example8-1.py
|
||||
:language: python
|
||||
|
||||
Result:
|
||||
raw data: 00 0F 05 6D 61 69 6C 34 03 6E 69 63 02 63 7A 00;00 14 02 6D 78 05 63 7A 6E 69 63 03 6F 72 67 00;00 0A 04 6D 61 69 6C 03 6E 69 63 02 63 7A 00
|
||||
priority:15 address: mail4.nic.cz.
|
||||
priority:20 address: mx.cznic.org.
|
||||
priority:10 address: mail.nic.cz.
|
||||
Output
|
||||
------
|
||||
|
||||
Result:
|
||||
raw data: D9 1F CD 32
|
||||
address: 217.31.205.50
|
||||
The previous example produces the following output::
|
||||
|
||||
Result:
|
||||
raw data: 01 61 02 6E 73 03 6E 69 63 02 63 7A 00;01 65 02 6E 73 03 6E 69 63 02 63 7A 00;01 63 02 6E 73 03 6E 69 63 02 63 7A 00
|
||||
host: a.ns.nic.cz.
|
||||
host: e.ns.nic.cz.
|
||||
host: c.ns.nic.cz.
|
||||
Result:
|
||||
raw data: 00 0F 05 6D 61 69 6C 34 03 6E 69 63 02 63 7A 00;00 14 02 6D 78 05 63 7A 6E 69 63 03 6F 72 67 00;00 0A 04 6D 61 69 6C 03 6E 69 63 02 63 7A 00
|
||||
priority:15 address: mail4.nic.cz.
|
||||
priority:20 address: mx.cznic.org.
|
||||
priority:10 address: mail.nic.cz.
|
||||
|
||||
Result:
|
||||
raw data: D9 1F CD 32
|
||||
address: 217.31.205.50
|
||||
|
||||
Result:
|
||||
raw data: 01 61 02 6E 73 03 6E 69 63 02 63 7A 00;01 65 02 6E 73 03 6E 69 63 02 63 7A 00;01 63 02 6E 73 03 6E 69 63 02 63 7A 00
|
||||
host: a.ns.nic.cz.
|
||||
host: e.ns.nic.cz.
|
||||
host: c.ns.nic.cz.
|
||||
|
@ -1,14 +1,16 @@
|
||||
Examples
|
||||
==============================
|
||||
========
|
||||
|
||||
Here you can find several examples which utilizes the unbound library in Python environment.
|
||||
Unbound is a caching validator and resolver and can be linked into an application, as a library where can answer DNS queries for the application.
|
||||
Here you can find several examples which utilizes the unbound library in Python
|
||||
environment. Unbound is a caching validator and resolver and can be linked into
|
||||
an application, as a library where can answer DNS queries for the application.
|
||||
This set of examples shows how to use the functions from Python environment.
|
||||
|
||||
`Tutorials`
|
||||
Tutorials
|
||||
---------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
example*
|
||||
example*
|
||||
|
@ -1,31 +1,38 @@
|
||||
Installation
|
||||
===================================
|
||||
============
|
||||
|
||||
**Prerequisites**
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Python 2.4 or higher, SWIG 1.3 or higher, GNU make
|
||||
|
||||
**Compiling**
|
||||
Compiling
|
||||
---------
|
||||
|
||||
After downloading, you can compile the pyUnbound library by doing::
|
||||
|
||||
> tar -xzf unbound-x.x.x-py.tar.gz
|
||||
> cd unbound-x.x.x
|
||||
> ./configure --with-pyunbound
|
||||
> make
|
||||
> tar -xzf unbound-x.x.x-py.tar.gz
|
||||
> cd unbound-x.x.x
|
||||
> ./configure --with-pyunbound
|
||||
> make
|
||||
|
||||
You may want to --with-pythonmodule as well if you want to use python as
|
||||
a module in the resolver.
|
||||
You may want to enable ``--with-pythonmodule`` as well if you want to use
|
||||
python as a module in the resolver.
|
||||
|
||||
You need GNU make to compile sources; SWIG and Python devel libraries to compile extension module.
|
||||
You need ``GNU make`` to compile sources; ``SWIG`` and ``Python devel``
|
||||
libraries to compile extension module.
|
||||
|
||||
|
||||
**Testing**
|
||||
Testing
|
||||
-------
|
||||
|
||||
If the compilation is successful, you can test the python LDNS extension module by::
|
||||
If the compilation is successful, you can test the python LDNS extension module
|
||||
by::
|
||||
|
||||
> cd contrib/python
|
||||
> make testenv
|
||||
> ./dns-lookup.py
|
||||
> cd contrib/python
|
||||
> make testenv
|
||||
> ./dns-lookup.py
|
||||
|
||||
You may want to make install in the main directory since make testenv is for debugging. In contrib/examples you can find simple applications written in Python using the Unbound extension.
|
||||
You may want to ``make install`` in the main directory since ``make testenv``
|
||||
is for debugging. In contrib/examples you can find simple applications written
|
||||
in Python using the Unbound extension.
|
||||
|
@ -1,39 +1,58 @@
|
||||
Introduction
|
||||
===================================
|
||||
============
|
||||
|
||||
**Unbound**
|
||||
Unbound
|
||||
-------
|
||||
|
||||
`Unbound`_ is an implementation of a DNS resolver, that performs caching and DNSSEC validation.
|
||||
Together with unbound, the libunbound library is provided.
|
||||
This library can be used to convert hostnames to ip addresses, and back, as well as obtain other information.
|
||||
Since the resolver allows to specify the class and type of a query (A record, NS, MX, ...), this library offers powerful resolving tool.
|
||||
The library also performs public-key validation of results with DNSSEC.
|
||||
|
||||
.. _Unbound: http://www.unbound.net/documentation
|
||||
`Unbound`_ is an implementation of a DNS resolver, that performs caching and
|
||||
DNSSEC validation.
|
||||
Together with unbound, the libunbound library is provided.
|
||||
This library can be used to convert hostnames to ip addresses, and back, as
|
||||
well as obtain other information.
|
||||
Since the resolver allows to specify the class and type of a query (A record,
|
||||
NS, MX, ...), this library offers powerful resolving tool.
|
||||
The library also performs public-key validation of results with DNSSEC.
|
||||
|
||||
**pyUnbound**
|
||||
.. _Unbound: http://www.unbound.net/documentation
|
||||
|
||||
The pyUnbound is an extension module for Python which provides an object-oriented interface to libunbound.
|
||||
It is the first Python module which offers thread-safe caching resolver.
|
||||
|
||||
The interface was designed with the emphasis on the simplicity of use.
|
||||
There are two main classes :class:`unbound.ub_ctx` (a validation and resolution context) and :class:`unbound.ub_result` which contains the validation and resolution results.
|
||||
The objects are thread-safe, and a context can be used in non-threaded as well as threaded environment.
|
||||
Resolution can be performed blocking and non-blocking (i.e. asynchronous).
|
||||
The asynchronous method returns from the call immediately, so that processing can go on, while the results become available later.
|
||||
pyUnbound
|
||||
---------
|
||||
|
||||
**Features**
|
||||
* customizable caching validation resolver for synchronous and asynchronous lookups
|
||||
* easy to use object interface
|
||||
* easy to integrate extension module
|
||||
* designed for thread environment (i.e. thread-safe)
|
||||
* allows define and customize of local zone and its RR's during the operation (i.e. without restart)
|
||||
* includes encoding functions to simplify the results retrieval
|
||||
* Internationalized domain name (`IDN`_) support
|
||||
The pyUnbound is an extension module for Python which provides an
|
||||
object-oriented interface to libunbound.
|
||||
It is the first Python module which offers thread-safe caching resolver.
|
||||
|
||||
.. _IDN: http://en.wikipedia.org/wiki/Internationalized_domain_name
|
||||
The interface was designed with the emphasis on the simplicity of use.
|
||||
There are two main classes :class:`unbound.ub_ctx` (a validation and resolution
|
||||
context) and :class:`unbound.ub_result` which contains the validation and
|
||||
resolution results.
|
||||
The objects are thread-safe, and a context can be used in non-threaded as well
|
||||
as threaded environment.
|
||||
Resolution can be performed blocking and non-blocking (i.e. asynchronous).
|
||||
The asynchronous method returns from the call immediately, so that processing
|
||||
can go on, while the results become available later.
|
||||
|
||||
**Application area**
|
||||
* DNS-based applications performing DNS lookups; the caching resolver can reduce overhead
|
||||
* Applications where the validation of DNS records is required
|
||||
* Great solution for customizable and dynamic DNS-based white/blacklists (spam rejection, connection rejection, ...) using the dynamic local zone manipulation
|
||||
Features
|
||||
--------
|
||||
|
||||
* Customizable caching validation resolver for synchronous and asynchronous
|
||||
lookups
|
||||
* Easy to use object interface
|
||||
* Easy to integrate extension module
|
||||
* Designed for thread environment (i.e. thread-safe)
|
||||
* Allows define and customize of local zone and its RR's during the operation
|
||||
(i.e. without restart)
|
||||
* Includes encoding functions to simplify the results retrieval
|
||||
* Internationalized domain name (`IDN`_) support
|
||||
|
||||
.. _IDN: http://en.wikipedia.org/wiki/Internationalized_domain_name
|
||||
|
||||
Application area
|
||||
----------------
|
||||
|
||||
* DNS-based applications performing DNS lookups; the caching resolver can
|
||||
reduce overhead
|
||||
* Applications where the validation of DNS records is required
|
||||
* Great solution for customizable and dynamic DNS-based white/blacklists (spam
|
||||
rejection, connection rejection, ...) using the dynamic local zone
|
||||
manipulation
|
||||
|
@ -49,31 +49,28 @@ struct comm_point;
|
||||
struct module_qstate;
|
||||
struct tube;
|
||||
struct edns_option;
|
||||
struct query_info;
|
||||
|
||||
/**
|
||||
* Worker service routine to send serviced queries to authoritative servers.
|
||||
* @param qname: query name. (host order)
|
||||
* @param qnamelen: length in bytes of qname, including trailing 0.
|
||||
* @param qtype: query type. (host order)
|
||||
* @param qclass: query class. (host order)
|
||||
* @param qinfo: query info.
|
||||
* @param flags: host order flags word, with opcode and CD bit.
|
||||
* @param dnssec: if set, EDNS record will have DO bit set.
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
|
||||
* @param opt_list: EDNS options on outgoing packet.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: delegation point name.
|
||||
* @param zonelen: length of zone name wireformat dname.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, struct edns_option* opt_list,
|
||||
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* q);
|
||||
size_t zonelen, int ssl_upstream, struct module_qstate* q);
|
||||
|
||||
/** process incoming replies from the network */
|
||||
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
|
||||
@ -108,28 +105,24 @@ void worker_sighandler(int sig, void* arg);
|
||||
|
||||
/**
|
||||
* Worker service routine to send serviced queries to authoritative servers.
|
||||
* @param qname: query name. (host order)
|
||||
* @param qnamelen: length in bytes of qname, including trailing 0.
|
||||
* @param qtype: query type. (host order)
|
||||
* @param qclass: query class. (host order)
|
||||
* @param qinfo: query info.
|
||||
* @param flags: host order flags word, with opcode and CD bit.
|
||||
* @param dnssec: if set, EDNS record will have DO bit set.
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
|
||||
* @param opt_list: EDNS options on outgoing packet.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: wireformat dname of the zone.
|
||||
* @param zonelen: length of zone name.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, struct edns_option* opt_list,
|
||||
struct outbound_entry* worker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* q);
|
||||
size_t zonelen, int ssl_upstream, struct module_qstate* q);
|
||||
|
||||
/**
|
||||
* process control messages from the main thread. Frees the control
|
||||
|
9
contrib/unbound/services/cache/dns.c
vendored
9
contrib/unbound/services/cache/dns.c
vendored
@ -194,6 +194,7 @@ msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
k.qname_len = qnamelen;
|
||||
k.qtype = qtype;
|
||||
k.qclass = qclass;
|
||||
k.local_alias = NULL;
|
||||
h = query_info_hash(&k, flags);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, wr);
|
||||
|
||||
@ -361,6 +362,7 @@ dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
msg->qinfo.qname_len = qnamelen;
|
||||
msg->qinfo.qtype = qtype;
|
||||
msg->qinfo.qclass = qclass;
|
||||
msg->qinfo.local_alias = NULL;
|
||||
/* non-packed reply_info, because it needs to grow the array */
|
||||
msg->rep = (struct reply_info*)regional_alloc_zero(region,
|
||||
sizeof(struct reply_info)-sizeof(struct rrset_ref));
|
||||
@ -716,6 +718,7 @@ dns_cache_lookup(struct module_env* env,
|
||||
k.qname_len = qnamelen;
|
||||
k.qtype = qtype;
|
||||
k.qclass = qclass;
|
||||
k.local_alias = NULL;
|
||||
h = query_info_hash(&k, flags);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, 0);
|
||||
if(e) {
|
||||
@ -795,9 +798,9 @@ dns_cache_lookup(struct module_env* env,
|
||||
dname_remove_label(&k.qname, &k.qname_len);
|
||||
h = query_info_hash(&k, flags);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, 0);
|
||||
if(!e && k.qtype != LDNS_RR_TYPE_NS &&
|
||||
if(!e && k.qtype != LDNS_RR_TYPE_A &&
|
||||
env->cfg->qname_minimisation) {
|
||||
k.qtype = LDNS_RR_TYPE_NS;
|
||||
k.qtype = LDNS_RR_TYPE_A;
|
||||
h = query_info_hash(&k, flags);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, 0);
|
||||
}
|
||||
@ -817,7 +820,7 @@ dns_cache_lookup(struct module_env* env,
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
k.qtype = qtype;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill common RR types for ANY response to avoid requery */
|
||||
if(qtype == LDNS_RR_TYPE_ANY) {
|
||||
|
@ -52,6 +52,11 @@
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/as112.h"
|
||||
#include "util/config_file.h"
|
||||
|
||||
/* maximum RRs in an RRset, to cap possible 'endless' list RRs.
|
||||
* with 16 bytes for an A record, a 64K packet has about 4000 max */
|
||||
#define LOCALZONE_RRSET_COUNT_MAX 4096
|
||||
|
||||
struct local_zones*
|
||||
local_zones_create(void)
|
||||
@ -154,7 +159,7 @@ local_zone_create(uint8_t* nm, size_t len, int labs,
|
||||
z->namelen = len;
|
||||
z->namelabs = labs;
|
||||
lock_rw_init(&z->lock);
|
||||
z->region = regional_create();
|
||||
z->region = regional_create_custom(sizeof(struct regional));
|
||||
if(!z->region) {
|
||||
free(z);
|
||||
return NULL;
|
||||
@ -181,13 +186,17 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
lock_rw_wrlock(&z->lock);
|
||||
if(!rbtree_insert(&zones->ztree, &z->node)) {
|
||||
struct local_zone* oldz;
|
||||
log_warn("duplicate local-zone");
|
||||
lock_rw_unlock(&z->lock);
|
||||
local_zone_delete(z);
|
||||
/* save zone name locally before deallocation,
|
||||
* otherwise, nm is gone if we zone_delete now. */
|
||||
oldz = z;
|
||||
/* find the correct zone, so not an error for duplicate */
|
||||
z = local_zones_find(zones, nm, len, labs, c);
|
||||
lock_rw_wrlock(&z->lock);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
local_zone_delete(oldz);
|
||||
return z;
|
||||
}
|
||||
lock_rw_unlock(&zones->lock);
|
||||
@ -275,16 +284,20 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass)
|
||||
* Find an rrset in local data structure.
|
||||
* @param data: local data domain name structure.
|
||||
* @param type: type to look for (host order).
|
||||
* @param alias_ok: 1 if matching a non-exact, alias type such as CNAME is
|
||||
* allowed. otherwise 0.
|
||||
* @return rrset pointer or NULL if not found.
|
||||
*/
|
||||
static struct local_rrset*
|
||||
local_data_find_type(struct local_data* data, uint16_t type)
|
||||
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
|
||||
{
|
||||
struct local_rrset* p;
|
||||
type = htons(type);
|
||||
for(p = data->rrsets; p; p = p->next) {
|
||||
if(p->rrset->rk.type == type)
|
||||
return p;
|
||||
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -342,13 +355,18 @@ new_local_rrset(struct regional* region, struct local_data* node,
|
||||
/** insert RR into RRset data structure; Wastes a couple of bytes */
|
||||
static int
|
||||
insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
uint8_t* rdata, size_t rdata_len, time_t ttl)
|
||||
uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr)
|
||||
{
|
||||
size_t* oldlen = pd->rr_len;
|
||||
time_t* oldttl = pd->rr_ttl;
|
||||
uint8_t** olddata = pd->rr_data;
|
||||
|
||||
/* add RR to rrset */
|
||||
if(pd->count > LOCALZONE_RRSET_COUNT_MAX) {
|
||||
log_warn("RRset '%s' has more than %d records, record ignored",
|
||||
rrstr, LOCALZONE_RRSET_COUNT_MAX);
|
||||
return 1;
|
||||
}
|
||||
pd->count++;
|
||||
pd->rr_len = regional_alloc(region, sizeof(*pd->rr_len)*pd->count);
|
||||
pd->rr_ttl = regional_alloc(region, sizeof(*pd->rr_ttl)*pd->count);
|
||||
@ -459,7 +477,23 @@ lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
||||
log_assert(node);
|
||||
free(nm);
|
||||
|
||||
rrset = local_data_find_type(node, rrtype);
|
||||
/* Reject it if we would end up having CNAME and other data (including
|
||||
* another CNAME) for a redirect zone. */
|
||||
if(z->type == local_zone_redirect && node->rrsets) {
|
||||
const char* othertype = NULL;
|
||||
if (rrtype == LDNS_RR_TYPE_CNAME)
|
||||
othertype = "other";
|
||||
else if (node->rrsets->rrset->rk.type ==
|
||||
htons(LDNS_RR_TYPE_CNAME)) {
|
||||
othertype = "CNAME";
|
||||
}
|
||||
if(othertype) {
|
||||
log_err("local-data '%s' in redirect zone must not "
|
||||
"coexist with %s local-data", rrstr, othertype);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rrset = local_data_find_type(node, rrtype, 0);
|
||||
if(!rrset) {
|
||||
rrset = new_local_rrset(z->region, node, rrtype, rrclass);
|
||||
if(!rrset)
|
||||
@ -479,7 +513,7 @@ lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
||||
verbose(VERB_ALGO, "ignoring duplicate RR: %s", rrstr);
|
||||
return 1;
|
||||
}
|
||||
return insert_rr(z->region, pd, rdata, rdata_len, ttl);
|
||||
return insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr);
|
||||
}
|
||||
|
||||
/** enter a data RR into auth data; a zone for it must exist */
|
||||
@ -1148,8 +1182,8 @@ void local_zones_print(struct local_zones* zones)
|
||||
|
||||
/** encode answer consisting of 1 rrset */
|
||||
static int
|
||||
local_encode(struct query_info* qinfo, struct edns_data* edns,
|
||||
sldns_buffer* buf, struct regional* temp,
|
||||
local_encode(struct query_info* qinfo, struct module_env* env,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
struct ub_packed_rrset_key* rrset, int ansec, int rcode)
|
||||
{
|
||||
struct reply_info rep;
|
||||
@ -1168,23 +1202,22 @@ local_encode(struct query_info* qinfo, struct edns_data* edns,
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!edns_opt_inplace_reply(edns, temp) ||
|
||||
!reply_info_answer_encode(qinfo, &rep,
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, temp)
|
||||
|| !reply_info_answer_encode(qinfo, &rep,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2),
|
||||
buf, 0, 0, temp, udpsize, edns,
|
||||
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);
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** find local data tag string match for the given type in the list */
|
||||
static int
|
||||
find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
struct ub_packed_rrset_key* r, struct regional* temp,
|
||||
uint8_t* zname, size_t zlen)
|
||||
struct ub_packed_rrset_key* r, struct regional* temp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
char buf[65536];
|
||||
@ -1193,18 +1226,21 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
int res;
|
||||
struct packed_rrset_data* d;
|
||||
for(p=list; p; p=p->next) {
|
||||
uint16_t rdr_type;
|
||||
|
||||
len = sizeof(rr);
|
||||
/* does this element match the type? */
|
||||
snprintf(buf, sizeof(buf), ". %s", p->str);
|
||||
res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600,
|
||||
zname, zlen, NULL, 0);
|
||||
NULL, 0, NULL, 0);
|
||||
if(res != 0)
|
||||
/* parse errors are already checked before, in
|
||||
* acllist check_data, skip this for robustness */
|
||||
continue;
|
||||
if(len < 1 /* . */ + 8 /* typeclassttl*/ + 2 /*rdatalen*/)
|
||||
continue;
|
||||
if(sldns_wirerr_get_type(rr, len, 1) != qinfo->qtype)
|
||||
rdr_type = sldns_wirerr_get_type(rr, len, 1);
|
||||
if(rdr_type != qinfo->qtype && rdr_type != LDNS_RR_TYPE_CNAME)
|
||||
continue;
|
||||
|
||||
/* do we have entries already? if not setup key */
|
||||
@ -1212,7 +1248,7 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
r->entry.key = r;
|
||||
r->rk.dname = qinfo->qname;
|
||||
r->rk.dname_len = qinfo->qname_len;
|
||||
r->rk.type = htons(qinfo->qtype);
|
||||
r->rk.type = htons(rdr_type);
|
||||
r->rk.rrset_class = htons(qinfo->qclass);
|
||||
r->rk.flags = 0;
|
||||
d = (struct packed_rrset_data*)regional_alloc_zero(
|
||||
@ -1261,6 +1297,20 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
if(!d) return 0; /* out of memory */
|
||||
d->count++;
|
||||
}
|
||||
/* If we've found a non-exact alias type of local data, make a shallow
|
||||
* copy of the RRset and remember it in qinfo to complete the alias
|
||||
* chain later. */
|
||||
if(r->rk.dname && qinfo->qtype != LDNS_RR_TYPE_CNAME &&
|
||||
r->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
|
||||
qinfo->local_alias =
|
||||
regional_alloc_zero(temp, sizeof(struct local_rrset));
|
||||
if(!qinfo->local_alias)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset =
|
||||
regional_alloc_init(temp, r, sizeof(*r));
|
||||
if(!qinfo->local_alias->rrset)
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
if(r->rk.dname)
|
||||
return 1;
|
||||
return 0;
|
||||
@ -1268,11 +1318,11 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
|
||||
/** answer local data match */
|
||||
static int
|
||||
local_data_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
int labs, struct local_data** ldp, enum localzone_type lz_type,
|
||||
int tag, struct config_strlist** tag_datas, size_t tag_datas_size,
|
||||
char** tagname, int num_tags)
|
||||
local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct regional* temp, int labs, struct local_data** ldp,
|
||||
enum localzone_type lz_type, int tag, struct config_strlist** tag_datas,
|
||||
size_t tag_datas_size, char** tagname, int num_tags)
|
||||
{
|
||||
struct local_data key;
|
||||
struct local_data* ld;
|
||||
@ -1288,11 +1338,17 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
if(tag != -1 && (size_t)tag<tag_datas_size && tag_datas[tag]) {
|
||||
struct ub_packed_rrset_key r;
|
||||
memset(&r, 0, sizeof(r));
|
||||
if(find_tag_datas(qinfo, tag_datas[tag], &r, temp,
|
||||
z->name, z->namelen)) {
|
||||
if(find_tag_datas(qinfo, tag_datas[tag], &r, temp)) {
|
||||
verbose(VERB_ALGO, "redirect with tag data [%d] %s",
|
||||
tag, (tag<num_tags?tagname[tag]:"null"));
|
||||
return local_encode(qinfo, edns, buf, temp,
|
||||
|
||||
/* If we found a matching alias, we should
|
||||
* use it as part of the answer, but we can't
|
||||
* encode it until we complete the alias
|
||||
* chain. */
|
||||
if(qinfo->local_alias)
|
||||
return 1;
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
&r, 1, LDNS_RCODE_NOERROR);
|
||||
}
|
||||
}
|
||||
@ -1302,24 +1358,42 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
if(!ld) {
|
||||
return 0;
|
||||
}
|
||||
lr = local_data_find_type(ld, qinfo->qtype);
|
||||
lr = local_data_find_type(ld, qinfo->qtype, 1);
|
||||
if(!lr)
|
||||
return 0;
|
||||
|
||||
/* Special case for alias matching. See local_data_answer(). */
|
||||
if(lz_type == local_zone_redirect &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_CNAME &&
|
||||
lr->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
|
||||
qinfo->local_alias =
|
||||
regional_alloc_zero(temp, sizeof(struct local_rrset));
|
||||
if(!qinfo->local_alias)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset =
|
||||
regional_alloc_init(temp, lr->rrset, sizeof(*lr->rrset));
|
||||
if(!qinfo->local_alias->rrset)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
|
||||
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
|
||||
return 1;
|
||||
}
|
||||
if(lz_type == local_zone_redirect) {
|
||||
/* convert rrset name to query name; like a wildcard */
|
||||
struct ub_packed_rrset_key r = *lr->rrset;
|
||||
r.rk.dname = qinfo->qname;
|
||||
r.rk.dname_len = qinfo->qname_len;
|
||||
return local_encode(qinfo, edns, buf, temp, &r, 1,
|
||||
return local_encode(qinfo, env, edns, buf, temp, &r, 1,
|
||||
LDNS_RCODE_NOERROR);
|
||||
}
|
||||
return local_encode(qinfo, edns, buf, temp, lr->rrset, 1,
|
||||
return local_encode(qinfo, env, edns, buf, temp, lr->rrset, 1,
|
||||
LDNS_RCODE_NOERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* answer in case where no exact match is found
|
||||
* @param z: zone for query
|
||||
* @param env: module environment
|
||||
* @param qinfo: query
|
||||
* @param edns: edns from query
|
||||
* @param buf: buffer for answer.
|
||||
@ -1329,9 +1403,9 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
* @return 1 if a reply is to be sent, 0 if not.
|
||||
*/
|
||||
static int
|
||||
lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
struct local_data* ld, enum localzone_type lz_type)
|
||||
lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct regional* temp, struct local_data* ld, enum localzone_type lz_type)
|
||||
{
|
||||
if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
|
||||
/** no reply at all, signal caller by clearing buffer. */
|
||||
@ -1357,7 +1431,7 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
int rcode = (ld || lz_type == local_zone_redirect)?
|
||||
LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
|
||||
if(z->soa)
|
||||
return local_encode(qinfo, edns, buf, temp,
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
z->soa, 0, rcode);
|
||||
error_encode(buf, (rcode|BIT_AA), qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
@ -1375,7 +1449,7 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
|
||||
if(ld && ld->rrsets) {
|
||||
int rcode = LDNS_RCODE_NOERROR;
|
||||
if(z->soa)
|
||||
return local_encode(qinfo, edns, buf, temp,
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
z->soa, 0, rcode);
|
||||
error_encode(buf, (rcode|BIT_AA), qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
@ -1448,54 +1522,79 @@ lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
|
||||
}
|
||||
|
||||
int
|
||||
local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
|
||||
uint8_t* tagactions, size_t tagactionssize,
|
||||
local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
|
||||
size_t taglen, uint8_t* tagactions, size_t tagactionssize,
|
||||
struct config_strlist** tag_datas, size_t tag_datas_size,
|
||||
char** tagname, int num_tags)
|
||||
char** tagname, int num_tags, struct view* view)
|
||||
{
|
||||
/* see if query is covered by a zone,
|
||||
* if so: - try to match (exact) local data
|
||||
* - look at zone type for negative response. */
|
||||
int labs = dname_count_labels(qinfo->qname);
|
||||
struct local_data* ld = NULL;
|
||||
struct local_zone* z;
|
||||
enum localzone_type lzt;
|
||||
struct local_zone* z = NULL;
|
||||
enum localzone_type lzt = local_zone_transparent;
|
||||
int r, tag = -1;
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
z = local_zones_tags_lookup(zones, qinfo->qname,
|
||||
qinfo->qname_len, labs, qinfo->qclass, taglist, taglen, 0);
|
||||
if(!z) {
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return 0;
|
||||
|
||||
if(view) {
|
||||
lock_rw_rdlock(&view->lock);
|
||||
if(view->local_zones &&
|
||||
(z = local_zones_lookup(view->local_zones,
|
||||
qinfo->qname, qinfo->qname_len, labs,
|
||||
qinfo->qclass))) {
|
||||
verbose(VERB_ALGO,
|
||||
"using localzone from view: %s",
|
||||
view->name);
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lzt = z->type;
|
||||
}
|
||||
if(!z && !view->isfirst){
|
||||
lock_rw_unlock(&view->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&view->lock);
|
||||
}
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
|
||||
lzt = lz_type(taglist, taglen, z->taglist, z->taglen, tagactions,
|
||||
tagactionssize, z->type, repinfo, z->override_tree, &tag,
|
||||
tagname, num_tags);
|
||||
if(!z) {
|
||||
/* try global local_zones tree */
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
if(!(z = local_zones_tags_lookup(zones, qinfo->qname,
|
||||
qinfo->qname_len, labs, qinfo->qclass, taglist,
|
||||
taglen, 0))) {
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_rdlock(&z->lock);
|
||||
|
||||
lzt = lz_type(taglist, taglen, z->taglist, z->taglen,
|
||||
tagactions, tagactionssize, z->type, repinfo,
|
||||
z->override_tree, &tag, tagname, num_tags);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
}
|
||||
if((lzt == local_zone_inform || lzt == local_zone_inform_deny)
|
||||
&& repinfo)
|
||||
lz_inform_print(z, qinfo, repinfo);
|
||||
|
||||
if(lzt != local_zone_always_refuse && lzt != local_zone_always_transparent
|
||||
if(lzt != local_zone_always_refuse
|
||||
&& lzt != local_zone_always_transparent
|
||||
&& lzt != local_zone_always_nxdomain
|
||||
&& local_data_answer(z, qinfo, edns, buf, temp, labs, &ld, lzt,
|
||||
tag, tag_datas, tag_datas_size, tagname, num_tags)) {
|
||||
&& local_data_answer(z, env, qinfo, edns, buf, temp, labs, &ld, lzt,
|
||||
tag, tag_datas, tag_datas_size, tagname, num_tags)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1;
|
||||
/* We should tell the caller that encode is deferred if we found
|
||||
* a local alias. */
|
||||
return !qinfo->local_alias;
|
||||
}
|
||||
r = lz_zone_answer(z, qinfo, edns, buf, temp, ld, lzt);
|
||||
r = lz_zone_answer(z, env, qinfo, edns, buf, temp, ld, lzt);
|
||||
lock_rw_unlock(&z->lock);
|
||||
return r;
|
||||
return r && !qinfo->local_alias; /* see above */
|
||||
}
|
||||
|
||||
const char* local_zone_type2str(enum localzone_type t)
|
||||
{
|
||||
switch(t) {
|
||||
case local_zone_unset: return "unset";
|
||||
case local_zone_deny: return "deny";
|
||||
case local_zone_refuse: return "refuse";
|
||||
case local_zone_redirect: return "redirect";
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "util/module.h"
|
||||
#include "services/view.h"
|
||||
struct ub_packed_rrset_key;
|
||||
struct regional;
|
||||
struct config_file;
|
||||
@ -59,8 +61,10 @@ struct config_strlist;
|
||||
* local-data directly.
|
||||
*/
|
||||
enum localzone_type {
|
||||
/** unset type, used for unset tag_action elements */
|
||||
local_zone_unset = 0,
|
||||
/** drop query */
|
||||
local_zone_deny = 0,
|
||||
local_zone_deny,
|
||||
/** answer with error */
|
||||
local_zone_refuse,
|
||||
/** answer nxdomain or nodata */
|
||||
@ -264,6 +268,7 @@ void local_zones_print(struct local_zones* zones);
|
||||
* Answer authoritatively for local zones.
|
||||
* Takes care of locking.
|
||||
* @param zones: the stored zones (shared, read only).
|
||||
* @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.
|
||||
@ -277,16 +282,25 @@ void local_zones_print(struct local_zones* zones);
|
||||
* @param tag_datas_size: size of tag_datas array.
|
||||
* @param tagname: array of tag name strings (for debug output).
|
||||
* @param num_tags: number of items in tagname array.
|
||||
* @param view: answer using this view. May be NULL.
|
||||
* @return true if answer is in buffer. false if query is not answered
|
||||
* by authority data. If the reply should be dropped altogether, the return
|
||||
* value is true, but the buffer is cleared (empty).
|
||||
* It can also return true if a non-exact alias answer is found. In this
|
||||
* case qinfo->local_alias points to the corresponding alias RRset but the
|
||||
* answer is NOT encoded in buffer. It's the caller's responsibility to
|
||||
* complete the alias chain (if needed) and encode the final set of answer.
|
||||
* Data pointed to by qinfo->local_alias is allocated in 'temp' or refers to
|
||||
* configuration data. So the caller will need to make a deep copy of it
|
||||
* if it needs to keep it beyond the lifetime of 'temp' or a dynamic update
|
||||
* to local zone data.
|
||||
*/
|
||||
int local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
|
||||
struct edns_data* edns, struct sldns_buffer* buf, struct regional* temp,
|
||||
struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
|
||||
uint8_t* tagactions, size_t tagactionssize,
|
||||
int local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
|
||||
struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
|
||||
size_t taglen, uint8_t* tagactions, size_t tagactionssize,
|
||||
struct config_strlist** tag_datas, size_t tag_datas_size,
|
||||
char** tagname, int num_tags);
|
||||
char** tagname, int num_tags, struct view* view);
|
||||
|
||||
/**
|
||||
* Parse the string into localzone type.
|
||||
|
@ -56,6 +56,9 @@
|
||||
#include "util/alloc.h"
|
||||
#include "util/config_file.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
@ -127,6 +130,11 @@ mesh_state_compare(const void* ap, const void* bp)
|
||||
struct mesh_state* a = (struct mesh_state*)ap;
|
||||
struct mesh_state* b = (struct mesh_state*)bp;
|
||||
|
||||
if(a->unique < b->unique)
|
||||
return -1;
|
||||
if(a->unique > b->unique)
|
||||
return 1;
|
||||
|
||||
if(a->s.is_priming && !b->s.is_priming)
|
||||
return -1;
|
||||
if(!a->s.is_priming && b->s.is_priming)
|
||||
@ -282,10 +290,13 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
|
||||
uint16_t qid)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = edns_unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
/* does this create a new reply state? */
|
||||
if(!s || s->list_select == mesh_no_list) {
|
||||
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
|
||||
@ -315,13 +326,32 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!edns_opt_inplace_reply(edns, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
return;
|
||||
}
|
||||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
/* copy the edns options we got from the front */
|
||||
if(edns->opt_list) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list,
|
||||
s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#else
|
||||
@ -338,10 +368,11 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(!s->reply_list && !s->cb_list)
|
||||
was_noreply = 1;
|
||||
/* add reply to s */
|
||||
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo->qname)) {
|
||||
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
|
||||
log_err("mesh_new_client: out of memory; SERVFAIL");
|
||||
if(!edns_opt_inplace_reply(edns, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
@ -380,10 +411,13 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_t cb, void* cb_arg)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = edns_unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
/* there are no limits on the number of callbacks */
|
||||
|
||||
/* see if it already exists, if not, create one */
|
||||
@ -395,6 +429,15 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
if(edns->opt_list) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list,
|
||||
s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#else
|
||||
@ -433,7 +476,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, time_t leeway)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD),
|
||||
0, 0);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
@ -452,6 +496,7 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
mesh->stats_dropped ++;
|
||||
return;
|
||||
}
|
||||
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) {
|
||||
log_err("prefetch mesh_state_create: out of memory");
|
||||
@ -525,9 +570,11 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
rbtree_init(&mstate->super_set, &mesh_state_ref_compare);
|
||||
rbtree_init(&mstate->sub_set, &mesh_state_ref_compare);
|
||||
mstate->num_activated = 0;
|
||||
mstate->unique = NULL;
|
||||
/* init module qstate */
|
||||
mstate->s.qinfo.qtype = qinfo->qtype;
|
||||
mstate->s.qinfo.qclass = qinfo->qclass;
|
||||
mstate->s.qinfo.local_alias = NULL;
|
||||
mstate->s.qinfo.qname_len = qinfo->qname_len;
|
||||
mstate->s.qinfo.qname = regional_alloc_init(region, qinfo->qname,
|
||||
qinfo->qname_len);
|
||||
@ -547,14 +594,34 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
mstate->s.env = env;
|
||||
mstate->s.mesh_info = mstate;
|
||||
mstate->s.prefetch_leeway = 0;
|
||||
mstate->s.no_cache_lookup = 0;
|
||||
mstate->s.no_cache_store = 0;
|
||||
/* init modules */
|
||||
for(i=0; i<env->mesh->mods.num; i++) {
|
||||
mstate->s.minfo[i] = NULL;
|
||||
mstate->s.ext_state[i] = module_state_initial;
|
||||
}
|
||||
/* init edns option lists */
|
||||
mstate->s.edns_opts_front_in = NULL;
|
||||
mstate->s.edns_opts_back_out = NULL;
|
||||
mstate->s.edns_opts_back_in = NULL;
|
||||
mstate->s.edns_opts_front_out = NULL;
|
||||
|
||||
return mstate;
|
||||
}
|
||||
|
||||
int
|
||||
mesh_state_is_unique(struct mesh_state* mstate)
|
||||
{
|
||||
return mstate->unique != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
mesh_state_make_unique(struct mesh_state* mstate)
|
||||
{
|
||||
mstate->unique = mstate;
|
||||
}
|
||||
|
||||
void
|
||||
mesh_state_cleanup(struct mesh_state* mstate)
|
||||
{
|
||||
@ -689,8 +756,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
{
|
||||
/* find it, if not, create it */
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime,
|
||||
valrec);
|
||||
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime, valrec);
|
||||
int was_detached;
|
||||
if(mesh_detect_cycle_found(qstate, sub)) {
|
||||
verbose(VERB_ALGO, "attach failed, cycle detected");
|
||||
@ -701,8 +767,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
struct rbnode_t* n;
|
||||
#endif
|
||||
/* create a new one */
|
||||
sub = mesh_state_create(qstate->env, qinfo, qflags, prime,
|
||||
valrec);
|
||||
sub = mesh_state_create(qstate->env, qinfo, qflags, prime, valrec);
|
||||
if(!sub) {
|
||||
log_err("mesh_attach_sub: out of memory");
|
||||
return 0;
|
||||
@ -804,6 +869,15 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
}
|
||||
/* send the reply */
|
||||
if(rcode) {
|
||||
if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, rcode, &r->edns, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
} else {
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
&r->edns, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
}
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL);
|
||||
} else {
|
||||
@ -813,8 +887,10 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
r->edns.ext_rcode = 0;
|
||||
r->edns.bits &= EDNS_DO;
|
||||
if(!edns_opt_inplace_reply(&r->edns, m->s.region) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
|
||||
LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r->buf, 0, 1,
|
||||
m->s.env->scratch, udp_size, &r->edns,
|
||||
(int)(r->edns.bits & EDNS_DO), secure))
|
||||
@ -847,6 +923,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
struct timeval end_time;
|
||||
struct timeval duration;
|
||||
int secure;
|
||||
/* Copy the client's EDNS for later restore, to make sure the edns
|
||||
* compare is with the correct edns options. */
|
||||
struct edns_data edns_bak = r->edns;
|
||||
/* examine security status */
|
||||
if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
|
||||
m->s.env->cfg->ignore_cd) && rep &&
|
||||
@ -861,7 +940,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
if(!rep && rcode == LDNS_RCODE_NOERROR)
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
/* send the reply */
|
||||
/* We don't reuse the encoded answer if either the previous or current
|
||||
* response has a local alias. We could compare the alias records
|
||||
* and still reuse the previous answer if they are the same, but that
|
||||
* would be complicated and error prone for the relatively minor case.
|
||||
* So we err on the side of safety. */
|
||||
if(prev && prev->qflags == r->qflags &&
|
||||
!prev->local_alias && !r->local_alias &&
|
||||
prev->edns.edns_present == r->edns.edns_present &&
|
||||
prev->edns.bits == r->edns.bits &&
|
||||
prev->edns.udp_size == r->edns.udp_size &&
|
||||
@ -878,6 +963,16 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
} else if(rcode) {
|
||||
m->s.qinfo.qname = r->qname;
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, rcode, &r->edns, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
} else {
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
&r->edns, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
}
|
||||
error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
|
||||
r->qid, r->qflags, &r->edns);
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
@ -888,16 +983,22 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
r->edns.ext_rcode = 0;
|
||||
r->edns.bits &= EDNS_DO;
|
||||
m->s.qinfo.qname = r->qname;
|
||||
if(!edns_opt_inplace_reply(&r->edns, m->s.region) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
|
||||
LDNS_RCODE_NOERROR, &r->edns, m->s.region) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r->query_reply.c->buffer, 0, 1,
|
||||
m->s.env->scratch, udp_size, &r->edns,
|
||||
(int)(r->edns.bits & EDNS_DO), secure))
|
||||
{
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, LDNS_RCODE_SERVFAIL, &r->edns, m->s.region))
|
||||
r->edns.opt_list = NULL;
|
||||
error_encode(r->query_reply.c->buffer,
|
||||
LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid,
|
||||
r->qflags, &r->edns);
|
||||
}
|
||||
r->edns = edns_bak;
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
}
|
||||
/* account */
|
||||
@ -963,6 +1064,10 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
key.s.is_valrec = valrec;
|
||||
key.s.qinfo = *qinfo;
|
||||
key.s.query_flags = qflags;
|
||||
/* We are searching for a similar mesh state when we DO want to
|
||||
* aggregate the state. Thus unique is set to NULL. (default when we
|
||||
* desire aggregation).*/
|
||||
key.unique = NULL;
|
||||
|
||||
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
|
||||
return result;
|
||||
@ -996,7 +1101,8 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
}
|
||||
|
||||
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
struct comm_reply* rep, uint16_t qid, uint16_t qflags, uint8_t* qname)
|
||||
struct comm_reply* rep, uint16_t qid, uint16_t qflags,
|
||||
const struct query_info* qinfo)
|
||||
{
|
||||
struct mesh_reply* r = regional_alloc(s->s.region,
|
||||
sizeof(struct mesh_reply));
|
||||
@ -1014,10 +1120,62 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
r->qflags = qflags;
|
||||
r->start_time = *s->s.env->now_tv;
|
||||
r->next = s->reply_list;
|
||||
r->qname = regional_alloc_init(s->s.region, qname,
|
||||
r->qname = regional_alloc_init(s->s.region, qinfo->qname,
|
||||
s->s.qinfo.qname_len);
|
||||
if(!r->qname)
|
||||
return 0;
|
||||
|
||||
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
|
||||
* and can be different for different original queries (even if the
|
||||
* replaced query name is the same). So we need to make a deep copy
|
||||
* and store the copy for each reply info. */
|
||||
if(qinfo->local_alias) {
|
||||
struct packed_rrset_data* d;
|
||||
struct packed_rrset_data* dsrc;
|
||||
r->local_alias = regional_alloc_zero(s->s.region,
|
||||
sizeof(*qinfo->local_alias));
|
||||
if(!r->local_alias)
|
||||
return 0;
|
||||
r->local_alias->rrset = regional_alloc_init(s->s.region,
|
||||
qinfo->local_alias->rrset,
|
||||
sizeof(*qinfo->local_alias->rrset));
|
||||
if(!r->local_alias->rrset)
|
||||
return 0;
|
||||
dsrc = qinfo->local_alias->rrset->entry.data;
|
||||
|
||||
/* In the current implementation, a local alias must be
|
||||
* a single CNAME RR (see worker_handle_request()). */
|
||||
log_assert(!qinfo->local_alias->next && dsrc->count == 1 &&
|
||||
qinfo->local_alias->rrset->rk.type ==
|
||||
htons(LDNS_RR_TYPE_CNAME));
|
||||
/* Technically, we should make a local copy for the owner
|
||||
* name of the RRset, but in the case of the first (and
|
||||
* currently only) local alias RRset, the owner name should
|
||||
* point to the qname of the corresponding query, which should
|
||||
* be valid throughout the lifetime of this mesh_reply. So
|
||||
* we can skip copying. */
|
||||
log_assert(qinfo->local_alias->rrset->rk.dname ==
|
||||
sldns_buffer_at(rep->c->buffer, LDNS_HEADER_SIZE));
|
||||
|
||||
d = regional_alloc_init(s->s.region, dsrc,
|
||||
sizeof(struct packed_rrset_data)
|
||||
+ sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t));
|
||||
if(!d)
|
||||
return 0;
|
||||
r->local_alias->rrset->entry.data = d;
|
||||
d->rr_len = (size_t*)((uint8_t*)d +
|
||||
sizeof(struct packed_rrset_data));
|
||||
d->rr_data = (uint8_t**)&(d->rr_len[1]);
|
||||
d->rr_ttl = (time_t*)&(d->rr_data[1]);
|
||||
d->rr_len[0] = dsrc->rr_len[0];
|
||||
d->rr_ttl[0] = dsrc->rr_ttl[0];
|
||||
d->rr_data[0] = regional_alloc_init(s->s.region,
|
||||
dsrc->rr_data[0], d->rr_len[0]);
|
||||
if(!d->rr_data[0])
|
||||
return 0;
|
||||
} else
|
||||
r->local_alias = NULL;
|
||||
|
||||
s->reply_list = r;
|
||||
return 1;
|
||||
}
|
||||
@ -1212,8 +1370,9 @@ mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t flags, int prime, int valrec)
|
||||
{
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime,
|
||||
valrec);
|
||||
struct mesh_state* dep_m = NULL;
|
||||
if(!mesh_state_is_unique(qstate->mesh_info))
|
||||
dep_m = mesh_area_find(mesh, qinfo, flags, prime, valrec);
|
||||
return mesh_detect_cycle_found(qstate, dep_m);
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,8 @@ struct mesh_state {
|
||||
/** if this state is in the forever list, jostle list, or neither */
|
||||
enum mesh_list_select { mesh_no_list, mesh_forever_list,
|
||||
mesh_jostle_list } list_select;
|
||||
/** pointer to this state for uniqueness or NULL */
|
||||
struct mesh_state* unique;
|
||||
|
||||
/** true if replies have been sent out (at end for alignment) */
|
||||
uint8_t replies_sent;
|
||||
@ -214,6 +216,8 @@ struct mesh_reply {
|
||||
uint16_t qflags;
|
||||
/** qname from this query. len same as mesh qinfo. */
|
||||
uint8_t* qname;
|
||||
/** same as that in query_info. */
|
||||
struct local_rrset* local_alias;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -414,6 +418,21 @@ void mesh_state_delete(struct module_qstate* qstate);
|
||||
struct mesh_state* mesh_state_create(struct module_env* env,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime, int valrec);
|
||||
|
||||
/**
|
||||
* Check if the mesh state is unique.
|
||||
* A unique mesh state uses it's unique member to point to itself, else NULL.
|
||||
* @param mstate: mesh state to check.
|
||||
* @return true if the mesh state is unique, false otherwise.
|
||||
*/
|
||||
int mesh_state_is_unique(struct mesh_state* mstate);
|
||||
|
||||
/**
|
||||
* Make a mesh state unique.
|
||||
* A unique mesh state uses it's unique member to point to itself.
|
||||
* @param mstate: mesh state to check.
|
||||
*/
|
||||
void mesh_state_make_unique(struct mesh_state* mstate);
|
||||
|
||||
/**
|
||||
* Cleanup a mesh state and its query state. Does not do rbtree or
|
||||
* reference cleanup.
|
||||
@ -459,11 +478,12 @@ int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub);
|
||||
* @param rep: comm point reply info.
|
||||
* @param qid: ID of reply.
|
||||
* @param qflags: original query flags.
|
||||
* @param qname: original query name.
|
||||
* @param qinfo: original query info.
|
||||
* @return: 0 on alloc error.
|
||||
*/
|
||||
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
struct comm_reply* rep, uint16_t qid, uint16_t qflags, uint8_t* qname);
|
||||
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
struct comm_reply* rep, uint16_t qid, uint16_t qflags,
|
||||
const struct query_info* qinfo);
|
||||
|
||||
/**
|
||||
* Create new callback structure and attach it to a mesh state.
|
||||
|
@ -1879,7 +1879,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_DNSTAP
|
||||
if(outnet->dtenv &&
|
||||
if(error == NETEVENT_NOERROR && outnet->dtenv &&
|
||||
(outnet->dtenv->log_resolver_response_messages ||
|
||||
outnet->dtenv->log_forwarder_response_messages))
|
||||
dt_msg_send_outside_response(outnet->dtenv, &sq->addr, c->type,
|
||||
@ -1986,17 +1986,22 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
|
||||
struct serviced_query*
|
||||
outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
int tcp_upstream, int ssl_upstream, struct edns_option* opt_list,
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
|
||||
int nocaps, int tcp_upstream, int ssl_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
|
||||
sldns_buffer* buff)
|
||||
size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_t* callback, void* callback_arg, sldns_buffer* buff,
|
||||
struct module_env* env)
|
||||
{
|
||||
struct serviced_query* sq;
|
||||
struct service_callback* cb;
|
||||
serviced_gen_query(buff, qname, qnamelen, qtype, qclass, flags);
|
||||
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen, opt_list);
|
||||
if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen, zone, zonelen,
|
||||
qstate, qstate->region))
|
||||
return NULL;
|
||||
serviced_gen_query(buff, qinfo->qname, qinfo->qname_len, qinfo->qtype,
|
||||
qinfo->qclass, flags);
|
||||
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen,
|
||||
qstate->edns_opts_back_out);
|
||||
/* duplicate entries are included in the callback list, because
|
||||
* there is a counterpart registration by our caller that needs to
|
||||
* be doubly-removed (with callbacks perhaps). */
|
||||
@ -2006,7 +2011,7 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
/* make new serviced query entry */
|
||||
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
|
||||
tcp_upstream, ssl_upstream, addr, addrlen, zone,
|
||||
zonelen, (int)qtype, opt_list);
|
||||
zonelen, (int)qinfo->qtype, qstate->edns_opts_back_out);
|
||||
if(!sq) {
|
||||
free(cb);
|
||||
return NULL;
|
||||
|
@ -59,6 +59,9 @@ struct sldns_buffer;
|
||||
struct serviced_query;
|
||||
struct dt_env;
|
||||
struct edns_option;
|
||||
struct module_env;
|
||||
struct module_qstate;
|
||||
struct query_info;
|
||||
|
||||
/**
|
||||
* Send queries to outside servers and wait for answers from servers.
|
||||
@ -471,10 +474,7 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
* Perform a serviced query to the authoritative servers.
|
||||
* Duplicate efforts are detected, and EDNS, TCP and UDP retry is performed.
|
||||
* @param outnet: outside network, with rbtree of serviced queries.
|
||||
* @param qname: what qname to query.
|
||||
* @param qnamelen: length of qname in octets including 0 root label.
|
||||
* @param qtype: rrset type to query (host format)
|
||||
* @param qclass: query class. (host format)
|
||||
* @param qinfo: query info.
|
||||
* @param flags: flags u16 (host format), includes opcode, CD bit.
|
||||
* @param dnssec: if set, DO bit is set in EDNS queries.
|
||||
* If the value includes BIT_CD, CD bit is set when in EDNS queries.
|
||||
@ -484,27 +484,28 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
* @param nocaps: ignore use_caps_for_id and use unperturbed qname.
|
||||
* @param tcp_upstream: use TCP for upstream queries.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param opt_list: pass edns option list (deep copied into serviced query)
|
||||
* these options are set on the outgoing packets.
|
||||
* @param callback: callback function.
|
||||
* @param callback_arg: user argument to callback function.
|
||||
* @param addr: to which server to send the query.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: name of the zone of the delegation point. wireformat dname.
|
||||
This is the delegation point name for which the server is deemed
|
||||
authoritative.
|
||||
* @param zonelen: length of zone.
|
||||
* @param qstate: module qstate. Mainly for inspecting the available
|
||||
* edns_opts_lists.
|
||||
* @param callback: callback function.
|
||||
* @param callback_arg: user argument to callback function.
|
||||
* @param buff: scratch buffer to create query contents in. Empty on exit.
|
||||
* @param env: the module environment.
|
||||
* @return 0 on error, or pointer to serviced query that is used to answer
|
||||
* this serviced query may be shared with other callbacks as well.
|
||||
*/
|
||||
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
int tcp_upstream, int ssl_upstream, struct edns_option* opt_list,
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
|
||||
int nocaps, int tcp_upstream, int ssl_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
|
||||
struct sldns_buffer* buff);
|
||||
size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
struct sldns_buffer* buff, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Remove service query callback.
|
||||
|
207
contrib/unbound/services/view.c
Normal file
207
contrib/unbound/services/view.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* services/view.c - named views containing local zones authority service.
|
||||
*
|
||||
* Copyright (c) 2016, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to enable named views that can hold local zone
|
||||
* authority service.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "services/view.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/config_file.h"
|
||||
|
||||
int
|
||||
view_cmp(const void* v1, const void* v2)
|
||||
{
|
||||
struct view* a = (struct view*)v1;
|
||||
struct view* b = (struct view*)v2;
|
||||
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
struct views*
|
||||
views_create(void)
|
||||
{
|
||||
struct views* v = (struct views*)calloc(1,
|
||||
sizeof(*v));
|
||||
if(!v)
|
||||
return NULL;
|
||||
rbtree_init(&v->vtree, &view_cmp);
|
||||
lock_rw_init(&v->lock);
|
||||
lock_protect(&v->lock, &v->vtree, sizeof(v->vtree));
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
view_delete(struct view* v)
|
||||
{
|
||||
if(!v)
|
||||
return;
|
||||
lock_rw_destroy(&v->lock);
|
||||
local_zones_delete(v->local_zones);
|
||||
free(v->name);
|
||||
free(v);
|
||||
}
|
||||
|
||||
static void
|
||||
delviewnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct view* v = (struct view*)n;
|
||||
view_delete(v);
|
||||
}
|
||||
|
||||
void
|
||||
views_delete(struct views* v)
|
||||
{
|
||||
if(!v)
|
||||
return;
|
||||
lock_rw_destroy(&v->lock);
|
||||
traverse_postorder(&v->vtree, delviewnode, NULL);
|
||||
free(v);
|
||||
}
|
||||
|
||||
/** create a new view */
|
||||
static struct view*
|
||||
view_create(char* name)
|
||||
{
|
||||
struct view* v = (struct view*)calloc(1, sizeof(*v));
|
||||
if(!v)
|
||||
return NULL;
|
||||
v->node.key = v;
|
||||
if(!(v->name = strdup(name))) {
|
||||
free(v);
|
||||
return NULL;
|
||||
}
|
||||
lock_rw_init(&v->lock);
|
||||
lock_protect(&v->lock, &v->name, sizeof(*v)-sizeof(rbnode_t));
|
||||
return v;
|
||||
}
|
||||
|
||||
/** enter a new view returns with WRlock */
|
||||
static struct view*
|
||||
views_enter_view_name(struct views* vs, char* name)
|
||||
{
|
||||
struct view* v = view_create(name);
|
||||
if(!v) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add to rbtree */
|
||||
lock_rw_wrlock(&vs->lock);
|
||||
lock_rw_wrlock(&v->lock);
|
||||
if(!rbtree_insert(&vs->vtree, &v->node)) {
|
||||
log_warn("duplicate view: %s", name);
|
||||
lock_rw_unlock(&v->lock);
|
||||
view_delete(v);
|
||||
lock_rw_unlock(&vs->lock);
|
||||
return NULL;
|
||||
}
|
||||
lock_rw_unlock(&vs->lock);
|
||||
return v;
|
||||
}
|
||||
|
||||
int
|
||||
views_apply_cfg(struct views* vs, struct config_file* cfg)
|
||||
{
|
||||
struct config_view* cv;
|
||||
struct view* v;
|
||||
struct config_file lz_cfg;
|
||||
/* Check existence of name in first view (last in config). Rest of
|
||||
* views are already checked when parsing config. */
|
||||
if(cfg->views && !cfg->views->name) {
|
||||
log_err("view without a name");
|
||||
return 0;
|
||||
}
|
||||
for(cv = cfg->views; cv; cv = cv->next) {
|
||||
/* create and enter view */
|
||||
if(!(v = views_enter_view_name(vs, cv->name)))
|
||||
return 0;
|
||||
v->isfirst = cv->isfirst;
|
||||
if(cv->local_zones || cv->local_data) {
|
||||
if(!(v->local_zones = local_zones_create())){
|
||||
lock_rw_unlock(&v->lock);
|
||||
return 0;
|
||||
}
|
||||
memset(&lz_cfg, 0, sizeof(lz_cfg));
|
||||
lz_cfg.local_zones = cv->local_zones;
|
||||
lz_cfg.local_data = cv->local_data;
|
||||
lz_cfg.local_zones_nodefault =
|
||||
cv->local_zones_nodefault;
|
||||
if(!local_zones_apply_cfg(v->local_zones, &lz_cfg)){
|
||||
lock_rw_unlock(&v->lock);
|
||||
return 0;
|
||||
}
|
||||
/* local_zones, local_zones_nodefault and local_data
|
||||
* are free'd from config_view by local_zones_apply_cfg.
|
||||
* Set pointers to NULL. */
|
||||
cv->local_zones = NULL;
|
||||
cv->local_data = NULL;
|
||||
cv->local_zones_nodefault = NULL;
|
||||
}
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** find a view by name */
|
||||
struct view*
|
||||
views_find_view(struct views* vs, const char* name, int write)
|
||||
{
|
||||
struct view* v;
|
||||
struct view key;
|
||||
key.node.key = &v;
|
||||
key.name = (char *)name;
|
||||
lock_rw_rdlock(&vs->lock);
|
||||
if(!(v = (struct view*)rbtree_search(&vs->vtree, &key.node))) {
|
||||
lock_rw_unlock(&vs->lock);
|
||||
return 0;
|
||||
}
|
||||
if(write) {
|
||||
lock_rw_wrlock(&v->lock);
|
||||
} else {
|
||||
lock_rw_rdlock(&v->lock);
|
||||
}
|
||||
lock_rw_unlock(&vs->lock);
|
||||
return v;
|
||||
}
|
||||
|
||||
void views_print(struct views* v)
|
||||
{
|
||||
/* TODO implement print */
|
||||
(void)v;
|
||||
}
|
135
contrib/unbound/services/view.h
Normal file
135
contrib/unbound/services/view.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* services/view.h - named views containing local zones authority service.
|
||||
*
|
||||
* Copyright (c) 2016, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to enable named views that can hold local zone
|
||||
* authority service.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_VIEW_H
|
||||
#define SERVICES_VIEW_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
struct regional;
|
||||
struct config_file;
|
||||
struct config_view;
|
||||
|
||||
|
||||
/**
|
||||
* Views storage, shared.
|
||||
*/
|
||||
struct views {
|
||||
/** lock on the view tree */
|
||||
lock_rw_t lock;
|
||||
/** rbtree of struct view */
|
||||
rbtree_t vtree;
|
||||
};
|
||||
|
||||
/**
|
||||
* View. Named structure holding local authority zones.
|
||||
*/
|
||||
struct view {
|
||||
/** rbtree node, key is name */
|
||||
rbnode_t node;
|
||||
/** view name.
|
||||
* Has to be right after rbnode_t due to pointer arithmatic in
|
||||
* view_create's lock protect */
|
||||
char* name;
|
||||
/** view specific local authority zones */
|
||||
struct local_zones* local_zones;
|
||||
/** Fallback to global local_zones when there is no match in the view
|
||||
* specific tree. 1 for yes, 0 for no */
|
||||
int isfirst;
|
||||
/** lock on the data in the structure
|
||||
* For the node and name you
|
||||
* need to also hold the views_tree lock to change them (or to
|
||||
* delete this view) */
|
||||
lock_rw_t lock;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create views storage
|
||||
* @return new struct or NULL on error.
|
||||
*/
|
||||
struct views* views_create(void);
|
||||
|
||||
/**
|
||||
* Delete views storage
|
||||
* @param v: views to delete.
|
||||
*/
|
||||
void views_delete(struct views* v);
|
||||
|
||||
/**
|
||||
* Apply config settings;
|
||||
* Takes care of locking.
|
||||
* @param v: view is set up.
|
||||
* @param cfg: config data.
|
||||
* @return false on error.
|
||||
*/
|
||||
int views_apply_cfg(struct views* v, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Compare two view entries in rbtree. Sort canonical.
|
||||
* @param v1: view 1
|
||||
* @param v2: view 2
|
||||
* @return: negative, positive or 0 comparison value.
|
||||
*/
|
||||
int view_cmp(const void* v1, const void* v2);
|
||||
|
||||
/**
|
||||
* Delete one view
|
||||
* @param v: view to delete.
|
||||
*/
|
||||
void view_delete(struct view* v);
|
||||
|
||||
/**
|
||||
* Debug helper. Print all views
|
||||
* Takes care of locking.
|
||||
* @param v: the views tree
|
||||
*/
|
||||
void views_print(struct views* v);
|
||||
|
||||
/* Find a view by name.
|
||||
* @param vs: views
|
||||
* @param name: name of the view we are looking for
|
||||
* @param write: 1 for obtaining write lock on found view, 0 for read lock
|
||||
* @return: locked view or NULL.
|
||||
*/
|
||||
struct view* views_find_view(struct views* vs, const char* name, int write);
|
||||
|
||||
#endif /* SERVICES_VIEW_H */
|
@ -328,7 +328,7 @@ rrinternal_write_typeclassttl(sldns_buffer* strbuf, uint8_t* rr, size_t len,
|
||||
|
||||
/** find delimiters for type */
|
||||
static const char*
|
||||
rrinternal_get_delims(sldns_rdf_type rdftype, uint16_t r_cnt, uint16_t r_max)
|
||||
rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_t r_max)
|
||||
{
|
||||
switch(rdftype) {
|
||||
case LDNS_RDF_TYPE_B64 :
|
||||
@ -463,7 +463,7 @@ rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
static int
|
||||
rrinternal_parse_rdf(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
uint8_t* rr, size_t rr_len, size_t* rr_cur_len, sldns_rdf_type rdftype,
|
||||
uint16_t rr_type, uint16_t r_cnt, uint16_t r_max, size_t dname_len,
|
||||
uint16_t rr_type, size_t r_cnt, size_t r_max, size_t dname_len,
|
||||
uint8_t* origin, size_t origin_len)
|
||||
{
|
||||
size_t len;
|
||||
@ -613,7 +613,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
uint8_t* origin, size_t origin_len)
|
||||
{
|
||||
const sldns_rr_descriptor *desc = sldns_rr_descript((uint16_t)rr_type);
|
||||
uint16_t r_cnt, r_min, r_max;
|
||||
size_t r_cnt, r_min, r_max;
|
||||
size_t rr_cur_len = dname_len + 10, pre_data_pos, token_strlen;
|
||||
int was_unknown_rr_format = 0, parens = 0, status, quoted;
|
||||
const char* delimiters;
|
||||
@ -693,7 +693,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
sldns_buffer_position(strbuf));
|
||||
}
|
||||
/* write rdata length */
|
||||
sldns_write_uint16(rr+dname_len+8, rr_cur_len-dname_len-10);
|
||||
sldns_write_uint16(rr+dname_len+8, (uint16_t)(rr_cur_len-dname_len-10));
|
||||
*rr_len = rr_cur_len;
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
@ -1369,7 +1369,7 @@ int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
if (tm.tm_sec < 0 || tm.tm_sec > 59)
|
||||
return LDNS_WIREPARSE_ERR_SYNTAX_TIME;
|
||||
|
||||
sldns_write_uint32(rd, sldns_mktime_from_utc(&tm));
|
||||
sldns_write_uint32(rd, (uint32_t)sldns_mktime_from_utc(&tm));
|
||||
} else {
|
||||
/* handle it as 32 bits timestamp */
|
||||
char *end;
|
||||
@ -1932,7 +1932,7 @@ int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
if(!isalnum((unsigned char)*ptr))
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str);
|
||||
}
|
||||
rd[0] = slen;
|
||||
rd[0] = (uint8_t)slen;
|
||||
memmove(rd+1, str, slen);
|
||||
*len = slen+1;
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
@ -2000,7 +2000,7 @@ int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
return RET_ERR_SHIFT(e, s-(char*)str);
|
||||
if(pklen > 65535)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535);
|
||||
sldns_write_uint16(rd+2, pklen);
|
||||
sldns_write_uint16(rd+2, (uint16_t)pklen);
|
||||
|
||||
*len = 4 + hitlen + pklen;
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
|
@ -667,7 +667,7 @@ int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s,
|
||||
uint8_t* origd = *d;
|
||||
char* origs = *s;
|
||||
size_t origdlen = *dlen, origslen = *slen;
|
||||
uint16_t r_cnt, r_max;
|
||||
size_t r_cnt, r_max;
|
||||
sldns_rdf_type rdftype;
|
||||
int w = 0, n;
|
||||
|
||||
@ -788,8 +788,9 @@ int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
|
||||
}
|
||||
|
||||
/* spool label characters, end with '.' */
|
||||
if(in_buf && *dlen < labellen) labellen = *dlen;
|
||||
else if(!in_buf && pos+labellen > pkt+pktlen)
|
||||
if(in_buf && *dlen < (size_t)labellen)
|
||||
labellen = (uint8_t)*dlen;
|
||||
else if(!in_buf && pos+(size_t)labellen > pkt+pktlen)
|
||||
labellen = (uint8_t)(pkt + pktlen - pos);
|
||||
for(i=0; i<(unsigned)labellen; i++) {
|
||||
w += dname_char_print(s, slen, *pos++);
|
||||
@ -1960,10 +1961,10 @@ int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
|
||||
w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize);
|
||||
|
||||
if(rdatalen) {
|
||||
if(*data_len < rdatalen) {
|
||||
if((size_t)*data_len < rdatalen) {
|
||||
w += sldns_str_print(str, str_len,
|
||||
" ; Error EDNS rdata too short; ");
|
||||
rdatalen = *data_len;
|
||||
rdatalen = (uint16_t)*data_len;
|
||||
}
|
||||
w += print_edns_opts(str, str_len, *data, rdatalen);
|
||||
(*data) += rdatalen;
|
||||
|
@ -97,7 +97,10 @@ static void
|
||||
print_option(struct config_file* cfg, const char* opt, int final)
|
||||
{
|
||||
if(strcmp(opt, "pidfile") == 0 && final) {
|
||||
printf("%s\n", fname_after_chroot(cfg->pidfile, cfg, 1));
|
||||
char *p = fname_after_chroot(cfg->pidfile, cfg, 1);
|
||||
if(!p) fatal_exit("out of memory");
|
||||
printf("%s\n", p);
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
if(!config_get_option(cfg, opt, config_print_func, stdout))
|
||||
@ -115,12 +118,15 @@ check_mod(struct config_file* cfg, struct module_func_block* fb)
|
||||
env.scratch_buffer = sldns_buffer_new(BUFSIZ);
|
||||
if(!env.scratch || !env.scratch_buffer)
|
||||
fatal_exit("out of memory");
|
||||
if(!edns_known_options_init(&env))
|
||||
fatal_exit("out of memory");
|
||||
if(!(*fb->init)(&env, 0)) {
|
||||
fatal_exit("bad config for %s module", fb->name);
|
||||
}
|
||||
(*fb->deinit)(&env, 0);
|
||||
sldns_buffer_free(env.scratch_buffer);
|
||||
regional_destroy(env.scratch);
|
||||
edns_known_options_delete(&env);
|
||||
}
|
||||
|
||||
/** check localzones */
|
||||
@ -486,7 +492,7 @@ check_hints(struct config_file* cfg)
|
||||
static void
|
||||
checkconf(const char* cfgfile, const char* opt, int final)
|
||||
{
|
||||
char oldwd[PATH_MAX];
|
||||
char oldwd[4096];
|
||||
struct config_file* cfg = config_create();
|
||||
if(!cfg)
|
||||
fatal_exit("out of memory");
|
||||
|
@ -176,7 +176,10 @@ setup_ctx(struct config_file* cfg)
|
||||
free(c_cert);
|
||||
} else {
|
||||
/* Use ciphers that don't require authentication */
|
||||
if(!SSL_CTX_set_cipher_list(ctx, "aNULL"))
|
||||
#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
|
||||
SSL_CTX_set_security_level(ctx, 0);
|
||||
#endif
|
||||
if(!SSL_CTX_set_cipher_list(ctx, "aNULL, eNULL"))
|
||||
ssl_err("Error setting NULL cipher!");
|
||||
}
|
||||
return ctx;
|
||||
@ -300,6 +303,15 @@ send_file(SSL* ssl, FILE* in, char* buf, size_t sz)
|
||||
}
|
||||
}
|
||||
|
||||
/** send end-of-file marker to server */
|
||||
static void
|
||||
send_eof(SSL* ssl)
|
||||
{
|
||||
char e[] = {0x04, 0x0a};
|
||||
if(SSL_write(ssl, e, (int)sizeof(e)) <= 0)
|
||||
ssl_err("could not SSL_write end-of-file marker");
|
||||
}
|
||||
|
||||
/** send command and display result */
|
||||
static int
|
||||
go_cmd(SSL* ssl, int quiet, int argc, char* argv[])
|
||||
@ -325,6 +337,13 @@ go_cmd(SSL* ssl, int quiet, int argc, char* argv[])
|
||||
if(argc == 1 && strcmp(argv[0], "load_cache") == 0) {
|
||||
send_file(ssl, stdin, buf, sizeof(buf));
|
||||
}
|
||||
else if(argc == 1 && (strcmp(argv[0], "local_zones") == 0 ||
|
||||
strcmp(argv[0], "local_zones_remove") == 0 ||
|
||||
strcmp(argv[0], "local_datas") == 0 ||
|
||||
strcmp(argv[0], "local_datas_remove") == 0)) {
|
||||
send_file(ssl, stdin, buf, sizeof(buf));
|
||||
send_eof(ssl);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
ERR_clear_error();
|
||||
|
@ -99,14 +99,13 @@ void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
|
||||
struct outbound_entry* worker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@ -132,14 +131,13 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
|
||||
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
|
||||
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
|
||||
struct outbound_entry* libworker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
@ -105,6 +105,7 @@ config_create(void)
|
||||
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;
|
||||
#ifndef USE_WINSOCK
|
||||
@ -170,6 +171,7 @@ config_create(void)
|
||||
cfg->out_ifs = NULL;
|
||||
cfg->stubs = NULL;
|
||||
cfg->forwards = NULL;
|
||||
cfg->views = NULL;
|
||||
cfg->acls = NULL;
|
||||
cfg->harden_short_bufsize = 0;
|
||||
cfg->harden_large_queries = 0;
|
||||
@ -202,6 +204,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 */
|
||||
@ -247,6 +250,7 @@ config_create(void)
|
||||
cfg->ratelimit_below_domain = NULL;
|
||||
cfg->ratelimit_factor = 10;
|
||||
cfg->qname_minimisation = 0;
|
||||
cfg->qname_minimisation_strict = 0;
|
||||
return cfg;
|
||||
error_exit:
|
||||
config_delete(cfg);
|
||||
@ -367,6 +371,7 @@ 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("do-ip4:", do_ip4)
|
||||
@ -453,6 +458,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||
else S_YNO("log-queries:", log_queries)
|
||||
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)
|
||||
@ -486,6 +492,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
|
||||
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,
|
||||
@ -509,10 +516,11 @@ 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,
|
||||
* 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 */
|
||||
* local-zone-tag, access-control-view */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -675,6 +683,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
else O_YNO(opt, "statistics-cumulative", stat_cumulative)
|
||||
else O_YNO(opt, "extended-statistics", stat_extended)
|
||||
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)
|
||||
@ -748,6 +757,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)
|
||||
@ -791,12 +801,14 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
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_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
|
||||
@ -983,6 +995,27 @@ config_delstubs(struct config_stub* p)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@ -1021,10 +1054,12 @@ config_delete(struct config_file* cfg)
|
||||
free(cfg->target_fetch_policy);
|
||||
free(cfg->ssl_service_key);
|
||||
free(cfg->ssl_service_pem);
|
||||
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);
|
||||
free(cfg->identity);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#ifndef UTIL_CONFIG_FILE_H
|
||||
#define UTIL_CONFIG_FILE_H
|
||||
struct config_stub;
|
||||
struct config_view;
|
||||
struct config_strlist;
|
||||
struct config_str2list;
|
||||
struct config_str3list;
|
||||
@ -167,6 +168,8 @@ struct config_file {
|
||||
struct config_stub* stubs;
|
||||
/** the forward zone definitions, linked list */
|
||||
struct config_stub* forwards;
|
||||
/** the views definitions, linked list */
|
||||
struct config_view* views;
|
||||
/** list of donotquery addresses, linked list */
|
||||
struct config_strlist* donotqueryaddrs;
|
||||
/** list of access control entries, linked list */
|
||||
@ -226,6 +229,8 @@ struct config_file {
|
||||
int log_time_ascii;
|
||||
/** log queries with one line per query */
|
||||
int log_queries;
|
||||
/** log identity to report */
|
||||
char* log_identity;
|
||||
|
||||
/** do not report identity (id.server, hostname.bind) */
|
||||
int hide_identity;
|
||||
@ -272,6 +277,8 @@ struct config_file {
|
||||
int val_permissive_mode;
|
||||
/** ignore the CD flag in incoming queries and refuse them bogus data */
|
||||
int ignore_cd;
|
||||
/** serve expired entries and prefetch them */
|
||||
int serve_expired;
|
||||
/** nsec3 maximum iterations per key size, string */
|
||||
char* val_nsec3_key_iterations;
|
||||
/** autotrust add holddown time, in seconds */
|
||||
@ -310,6 +317,8 @@ struct config_file {
|
||||
struct config_str3list* acl_tag_actions;
|
||||
/** list of aclname, tagname, redirectdata */
|
||||
struct config_str3list* acl_tag_datas;
|
||||
/** list of aclname, view*/
|
||||
struct config_str2list* acl_view;
|
||||
/** tag list, array with tagname[i] is malloced string */
|
||||
char** tagname;
|
||||
/** number of items in the taglist */
|
||||
@ -396,6 +405,9 @@ struct config_file {
|
||||
int ratelimit_factor;
|
||||
/** minimise outgoing QNAME and hide original QTYPE if possible */
|
||||
int qname_minimisation;
|
||||
/** minimise QNAME in strict mode, minimise according to RFC.
|
||||
* Do not apply fallback */
|
||||
int qname_minimisation_strict;
|
||||
};
|
||||
|
||||
/** from cfg username, after daemonise setup performed */
|
||||
@ -421,6 +433,27 @@ struct config_stub {
|
||||
int isprime;
|
||||
/** if forward-first is set (failover to without if fails) */
|
||||
int isfirst;
|
||||
/* use SSL for queries to this stub */
|
||||
int ssl_upstream;
|
||||
};
|
||||
|
||||
/**
|
||||
* View config options
|
||||
*/
|
||||
struct config_view {
|
||||
/** next in list */
|
||||
struct config_view* next;
|
||||
/** view name */
|
||||
char* name;
|
||||
/** local zones */
|
||||
struct config_str2list* local_zones;
|
||||
/** local data RRs */
|
||||
struct config_strlist* local_data;
|
||||
/** local zones nodefault list */
|
||||
struct config_strlist* local_zones_nodefault;
|
||||
/** Fallback to global local_zones when there is no match in the view
|
||||
* view specific tree. 1 for yes, 0 for no */
|
||||
int isfirst;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -681,6 +714,18 @@ void config_delstub(struct config_stub* p);
|
||||
*/
|
||||
void config_delstubs(struct config_stub* list);
|
||||
|
||||
/**
|
||||
* Delete a view item
|
||||
* @param p: view item
|
||||
*/
|
||||
void config_delview(struct config_view* p);
|
||||
|
||||
/**
|
||||
* Delete items in config view list.
|
||||
* @param list: list.
|
||||
*/
|
||||
void config_delviews(struct config_view* list);
|
||||
|
||||
/**
|
||||
* Convert 14digit to time value
|
||||
* @param str: string of 14 digits
|
||||
@ -904,4 +949,7 @@ char* w_lookup_reg_str(const char* key, const char* name);
|
||||
void w_config_adjust_directory(struct config_file* cfg);
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
|
||||
/** debug option for unit tests. */
|
||||
extern int fake_dsa;
|
||||
|
||||
#endif /* UTIL_CONFIG_FILE_H */
|
||||
|
@ -10,7 +10,9 @@
|
||||
#include "config.h"
|
||||
|
||||
/* because flex keeps having sign-unsigned compare problems that are unfixed*/
|
||||
#if defined(__clang__)||(defined(__GNUC__)&&((__GNUC__ >4)||(defined(__GNUC_MINOR__)&&(__GNUC__ ==4)&&(__GNUC_MINOR__ >=2))))
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
@ -211,6 +213,7 @@ SQANY [^\'\n\r\\]|\\.
|
||||
LEXOUT(("comment(%s) ", ub_c_text)); /* ignore */ }
|
||||
server{COLON} { YDVAR(0, VAR_SERVER) }
|
||||
qname-minimisation{COLON} { YDVAR(1, VAR_QNAME_MINIMISATION) }
|
||||
qname-minimisation-strict{COLON} { YDVAR(1, VAR_QNAME_MINIMISATION_STRICT) }
|
||||
num-threads{COLON} { YDVAR(1, VAR_NUM_THREADS) }
|
||||
verbosity{COLON} { YDVAR(1, VAR_VERBOSITY) }
|
||||
port{COLON} { YDVAR(1, VAR_PORT) }
|
||||
@ -286,10 +289,14 @@ stub-addr{COLON} { YDVAR(1, VAR_STUB_ADDR) }
|
||||
stub-host{COLON} { YDVAR(1, VAR_STUB_HOST) }
|
||||
stub-prime{COLON} { YDVAR(1, VAR_STUB_PRIME) }
|
||||
stub-first{COLON} { YDVAR(1, VAR_STUB_FIRST) }
|
||||
stub-ssl-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) }
|
||||
forward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) }
|
||||
forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) }
|
||||
forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) }
|
||||
forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) }
|
||||
forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
|
||||
view{COLON} { YDVAR(0, VAR_VIEW) }
|
||||
view-first{COLON} { YDVAR(1, VAR_VIEW_FIRST) }
|
||||
do-not-query-address{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) }
|
||||
do-not-query-localhost{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) }
|
||||
access-control{COLON} { YDVAR(2, VAR_ACCESS_CONTROL) }
|
||||
@ -311,6 +318,8 @@ val-bogus-ttl{COLON} { YDVAR(1, VAR_BOGUS_TTL) }
|
||||
val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) }
|
||||
val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) }
|
||||
ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) }
|
||||
serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) }
|
||||
fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) }
|
||||
val-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) }
|
||||
key-cache-size{COLON} { YDVAR(1, VAR_KEY_CACHE_SIZE) }
|
||||
key-cache-slabs{COLON} { YDVAR(1, VAR_KEY_CACHE_SLABS) }
|
||||
@ -322,6 +331,7 @@ del-holddown{COLON} { YDVAR(1, VAR_DEL_HOLDDOWN) }
|
||||
keep-missing{COLON} { YDVAR(1, VAR_KEEP_MISSING) }
|
||||
permit-small-holddown{COLON} { YDVAR(1, VAR_PERMIT_SMALL_HOLDDOWN) }
|
||||
use-syslog{COLON} { YDVAR(1, VAR_USE_SYSLOG) }
|
||||
log-identity{COLON} { YDVAR(1, VAR_LOG_IDENTITY) }
|
||||
log-time-ascii{COLON} { YDVAR(1, VAR_LOG_TIME_ASCII) }
|
||||
log-queries{COLON} { YDVAR(1, VAR_LOG_QUERIES) }
|
||||
local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) }
|
||||
@ -354,6 +364,7 @@ local-zone-tag{COLON} { YDVAR(2, VAR_LOCAL_ZONE_TAG) }
|
||||
access-control-tag{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_TAG) }
|
||||
access-control-tag-action{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_ACTION) }
|
||||
access-control-tag-data{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_DATA) }
|
||||
access-control-view{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_VIEW) }
|
||||
local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) }
|
||||
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
|
||||
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
|
||||
|
@ -106,6 +106,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_SO_REUSEPORT VAR_HARDEN_BELOW_NXDOMAIN
|
||||
%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
|
||||
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
|
||||
%token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM
|
||||
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
|
||||
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE
|
||||
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
|
||||
@ -125,15 +126,19 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
|
||||
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN VAR_RATELIMIT_FACTOR
|
||||
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
|
||||
%token VAR_QNAME_MINIMISATION VAR_IP_FREEBIND VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG
|
||||
%token VAR_ACCESS_CONTROL_TAG VAR_LOCAL_ZONE_OVERRIDE
|
||||
%token VAR_ACCESS_CONTROL_TAG_ACTION VAR_ACCESS_CONTROL_TAG_DATA
|
||||
%token VAR_QNAME_MINIMISATION VAR_QNAME_MINIMISATION_STRICT VAR_IP_FREEBIND
|
||||
%token VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG VAR_ACCESS_CONTROL_TAG
|
||||
%token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION
|
||||
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
|
||||
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA
|
||||
%token VAR_LOG_IDENTITY
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
toplevelvar: serverstart contents_server | stubstart contents_stub |
|
||||
forwardstart contents_forward | pythonstart contents_py |
|
||||
rcstart contents_rc | dtstart contents_dt
|
||||
rcstart contents_rc | dtstart contents_dt | viewstart
|
||||
contents_view
|
||||
;
|
||||
|
||||
/* server: declaration */
|
||||
@ -199,7 +204,9 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_ip_freebind | server_define_tag | server_local_zone_tag |
|
||||
server_disable_dnssec_lame_check | server_access_control_tag |
|
||||
server_local_zone_override | server_access_control_tag_action |
|
||||
server_access_control_tag_data
|
||||
server_access_control_tag_data | server_access_control_view |
|
||||
server_qname_minimisation_strict | server_serve_expired |
|
||||
server_fake_dsa | server_log_identity
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
@ -215,7 +222,8 @@ stubstart: VAR_STUB_ZONE
|
||||
;
|
||||
contents_stub: contents_stub content_stub
|
||||
| ;
|
||||
content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first
|
||||
content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first |
|
||||
stub_ssl_upstream
|
||||
;
|
||||
forwardstart: VAR_FORWARD_ZONE
|
||||
{
|
||||
@ -231,7 +239,26 @@ forwardstart: VAR_FORWARD_ZONE
|
||||
;
|
||||
contents_forward: contents_forward content_forward
|
||||
| ;
|
||||
content_forward: forward_name | forward_host | forward_addr | forward_first
|
||||
content_forward: forward_name | forward_host | forward_addr | forward_first |
|
||||
forward_ssl_upstream
|
||||
;
|
||||
viewstart: VAR_VIEW
|
||||
{
|
||||
struct config_view* s;
|
||||
OUTYY(("\nP(view:)\n"));
|
||||
s = (struct config_view*)calloc(1, sizeof(struct config_view));
|
||||
if(s) {
|
||||
s->next = cfg_parser->cfg->views;
|
||||
if(s->next && !s->next->name)
|
||||
yyerror("view without name");
|
||||
cfg_parser->cfg->views = s;
|
||||
} else
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
contents_view: contents_view content_view
|
||||
| ;
|
||||
content_view: view_name | view_local_zone | view_local_data | view_first
|
||||
;
|
||||
server_num_threads: VAR_NUM_THREADS STRING_ARG
|
||||
{
|
||||
@ -1160,6 +1187,26 @@ server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_serve_expired: VAR_SERVE_EXPIRED STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_serve_expired:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->serve_expired = (strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_fake_dsa: VAR_FAKE_DSA STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_fake_dsa:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else fake_dsa = (strcmp($2, "yes")==0);
|
||||
if(fake_dsa)
|
||||
log_warn("test option fake_dsa is enabled");
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_val_log_level: VAR_VAL_LOG_LEVEL STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_val_log_level:%s)\n", $2));
|
||||
@ -1422,6 +1469,17 @@ server_local_zone_override: VAR_LOCAL_ZONE_OVERRIDE STRING_ARG STRING_ARG STRING
|
||||
}
|
||||
}
|
||||
;
|
||||
server_access_control_view: VAR_ACCESS_CONTROL_VIEW STRING_ARG STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_access_control_view:%s %s)\n", $2, $3));
|
||||
if(!cfg_str2list_insert(&cfg_parser->cfg->acl_view,
|
||||
$2, $3)) {
|
||||
yyerror("out of memory");
|
||||
free($2);
|
||||
free($3);
|
||||
}
|
||||
}
|
||||
;
|
||||
server_ratelimit: VAR_RATELIMIT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_ratelimit:%s)\n", $2));
|
||||
@ -1497,6 +1555,16 @@ server_qname_minimisation: VAR_QNAME_MINIMISATION STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_qname_minimisation_strict: VAR_QNAME_MINIMISATION_STRICT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_qname_minimisation_strict:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->qname_minimisation_strict =
|
||||
(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
stub_name: VAR_NAME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
@ -1530,6 +1598,16 @@ stub_first: VAR_STUB_FIRST STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
stub_ssl_upstream: VAR_STUB_SSL_UPSTREAM STRING_ARG
|
||||
{
|
||||
OUTYY(("P(stub-ssl-upstream:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->stubs->ssl_upstream =
|
||||
(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
stub_prime: VAR_STUB_PRIME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(stub-prime:%s)\n", $2));
|
||||
@ -1573,6 +1651,73 @@ forward_first: VAR_FORWARD_FIRST STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
forward_ssl_upstream: VAR_FORWARD_SSL_UPSTREAM STRING_ARG
|
||||
{
|
||||
OUTYY(("P(forward-ssl-upstream:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->forwards->ssl_upstream =
|
||||
(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
view_name: VAR_NAME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
if(cfg_parser->cfg->views->name)
|
||||
yyerror("view name override, there must be one "
|
||||
"name for one view");
|
||||
free(cfg_parser->cfg->views->name);
|
||||
cfg_parser->cfg->views->name = $2;
|
||||
}
|
||||
;
|
||||
view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
|
||||
{
|
||||
OUTYY(("P(view_local_zone:%s %s)\n", $2, $3));
|
||||
if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 &&
|
||||
strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 &&
|
||||
strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0
|
||||
&& strcmp($3, "typetransparent")!=0
|
||||
&& strcmp($3, "always_transparent")!=0
|
||||
&& strcmp($3, "always_refuse")!=0
|
||||
&& strcmp($3, "always_nxdomain")!=0
|
||||
&& strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
|
||||
yyerror("local-zone type: expected static, deny, "
|
||||
"refuse, redirect, transparent, "
|
||||
"typetransparent, inform, inform_deny, "
|
||||
"always_transparent, always_refuse, "
|
||||
"always_nxdomain or nodefault");
|
||||
else if(strcmp($3, "nodefault")==0) {
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->views->
|
||||
local_zones_nodefault, $2))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
free($3);
|
||||
} else {
|
||||
if(!cfg_str2list_insert(
|
||||
&cfg_parser->cfg->views->local_zones,
|
||||
$2, $3))
|
||||
fatal_exit("out of memory adding local-zone");
|
||||
}
|
||||
}
|
||||
;
|
||||
view_local_data: VAR_LOCAL_DATA STRING_ARG
|
||||
{
|
||||
OUTYY(("P(view_local_data:%s)\n", $2));
|
||||
if(!cfg_strlist_insert(&cfg_parser->cfg->views->local_data, $2)) {
|
||||
fatal_exit("out of memory adding local-data");
|
||||
free($2);
|
||||
}
|
||||
}
|
||||
;
|
||||
view_first: VAR_VIEW_FIRST STRING_ARG
|
||||
{
|
||||
OUTYY(("P(view-first:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->views->isfirst=(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
rcstart: VAR_REMOTE_CONTROL
|
||||
{
|
||||
OUTYY(("\nP(remote-control:)\n"));
|
||||
@ -1788,6 +1933,14 @@ server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
|
||||
(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_log_identity: VAR_LOG_IDENTITY STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_log_identity:%s)\n", $2));
|
||||
free(cfg_parser->cfg->log_identity);
|
||||
cfg_parser->cfg->log_identity = $2;
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
/* parse helper routines could be here */
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "services/localzone.h"
|
||||
|
||||
/** return code that means the function ran out of memory. negative so it does
|
||||
* not conflict with DNS rcodes. */
|
||||
@ -534,7 +535,11 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||
{
|
||||
int r;
|
||||
size_t i, setstart;
|
||||
*num_rrs = 0;
|
||||
/* we now allow this function to be called multiple times for the
|
||||
* same section, incrementally updating num_rrs. The caller is
|
||||
* responsible for initializing it (which is the case in the current
|
||||
* implementation). */
|
||||
|
||||
if(s != LDNS_SECTION_ADDITIONAL) {
|
||||
if(s == LDNS_SECTION_ANSWER && qtype == LDNS_RR_TYPE_ANY)
|
||||
dnssec = 1; /* include all types in ANY answer */
|
||||
@ -581,17 +586,20 @@ static int
|
||||
insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
|
||||
sldns_buffer* buffer, struct regional* region)
|
||||
{
|
||||
uint8_t* qname = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
|
||||
size_t qname_len = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
|
||||
if(sldns_buffer_remaining(buffer) <
|
||||
qinfo->qname_len+sizeof(uint16_t)*2)
|
||||
return RETVAL_TRUNC; /* buffer too small */
|
||||
/* the query is the first name inserted into the tree */
|
||||
if(!compress_tree_store(qinfo->qname,
|
||||
dname_count_labels(qinfo->qname),
|
||||
if(!compress_tree_store(qname, dname_count_labels(qname),
|
||||
sldns_buffer_position(buffer), region, NULL, tree))
|
||||
return RETVAL_OUTMEM;
|
||||
if(sldns_buffer_current(buffer) == qinfo->qname)
|
||||
sldns_buffer_skip(buffer, (ssize_t)qinfo->qname_len);
|
||||
else sldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len);
|
||||
if(sldns_buffer_current(buffer) == qname)
|
||||
sldns_buffer_skip(buffer, (ssize_t)qname_len);
|
||||
else sldns_buffer_write(buffer, qname, qname_len);
|
||||
sldns_buffer_write_u16(buffer, qinfo->qtype);
|
||||
sldns_buffer_write_u16(buffer, qinfo->qclass);
|
||||
return RETVAL_OK;
|
||||
@ -662,6 +670,33 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
* for different roundrobins for sequential id client senders. */
|
||||
rr_offset = RRSET_ROUNDROBIN?ntohs(id):0;
|
||||
|
||||
/* "prepend" any local alias records in the answer section if this
|
||||
* response is supposed to be authoritative. Currently it should
|
||||
* be a single CNAME record (sanity-checked in worker_handle_request())
|
||||
* but it can be extended if and when we support more variations of
|
||||
* aliases. */
|
||||
if(qinfo->local_alias && (flags & BIT_AA)) {
|
||||
struct reply_info arep;
|
||||
time_t timezero = 0; /* to use the 'authoritative' TTL */
|
||||
memset(&arep, 0, sizeof(arep));
|
||||
arep.flags = rep->flags;
|
||||
arep.an_numrrsets = 1;
|
||||
arep.rrset_count = 1;
|
||||
arep.rrsets = &qinfo->local_alias->rrset;
|
||||
if((r=insert_section(&arep, 1, &ancount, buffer, 0,
|
||||
timezero, region, &tree, LDNS_SECTION_ANSWER,
|
||||
qinfo->qtype, dnssec, rr_offset)) != RETVAL_OK) {
|
||||
if(r == RETVAL_TRUNC) {
|
||||
/* create truncated message */
|
||||
sldns_buffer_write_u16_at(buffer, 6, ancount);
|
||||
LDNS_TC_SET(sldns_buffer_begin(buffer));
|
||||
sldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert answer section */
|
||||
if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
|
||||
0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
|
||||
@ -782,6 +817,15 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
|
||||
}
|
||||
if(secure && (dnssec || (qflags&BIT_AD)))
|
||||
flags |= BIT_AD;
|
||||
/* restore AA bit if we have a local alias and the response can be
|
||||
* authoritative. Also clear AD bit if set as the local data is the
|
||||
* primary answer. */
|
||||
if(qinf->local_alias &&
|
||||
(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR ||
|
||||
FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN)) {
|
||||
flags |= BIT_AA;
|
||||
flags &= ~BIT_AD;
|
||||
}
|
||||
log_assert(flags & BIT_QR); /* QR bit must be on in our replies */
|
||||
if(udpsize < LDNS_HEADER_SIZE)
|
||||
return 0;
|
||||
@ -807,13 +851,17 @@ void
|
||||
qinfo_query_encode(sldns_buffer* pkt, struct query_info* qinfo)
|
||||
{
|
||||
uint16_t flags = 0; /* QUERY, NOERROR */
|
||||
const uint8_t* qname = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
|
||||
size_t qname_len = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
|
||||
sldns_buffer_clear(pkt);
|
||||
log_assert(sldns_buffer_remaining(pkt) >= 12+255+4/*max query*/);
|
||||
sldns_buffer_skip(pkt, 2); /* id done later */
|
||||
sldns_buffer_write_u16(pkt, flags);
|
||||
sldns_buffer_write_u16(pkt, 1); /* query count */
|
||||
sldns_buffer_write(pkt, "\000\000\000\000\000\000", 6); /* counts */
|
||||
sldns_buffer_write(pkt, qinfo->qname, qinfo->qname_len);
|
||||
sldns_buffer_write(pkt, qname, qname_len);
|
||||
sldns_buffer_write_u16(pkt, qinfo->qtype);
|
||||
sldns_buffer_write_u16(pkt, qinfo->qclass);
|
||||
sldns_buffer_flip(pkt);
|
||||
@ -838,9 +886,14 @@ error_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
|
||||
sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
if(qinfo) {
|
||||
if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
const uint8_t* qname = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
|
||||
size_t qname_len = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname_len :
|
||||
qinfo->qname_len;
|
||||
if(sldns_buffer_current(buf) == qname)
|
||||
sldns_buffer_skip(buf, (ssize_t)qname_len);
|
||||
else sldns_buffer_write(buf, qname, qname_len);
|
||||
sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
}
|
||||
|
@ -1072,3 +1072,22 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
log_edns_opt_list(enum verbosity_value level, const char* info_str,
|
||||
struct edns_option* list)
|
||||
{
|
||||
if(verbosity >= level && list) {
|
||||
char str[128], *s;
|
||||
size_t slen;
|
||||
verbose(level, "%s", info_str);
|
||||
while(list) {
|
||||
s = str;
|
||||
slen = sizeof(str);
|
||||
(void)sldns_wire2str_edns_option_print(&s, &slen, list->opt_code,
|
||||
list->opt_data, list->opt_len);
|
||||
verbose(level, " %s", str);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -322,4 +322,13 @@ struct rrset_parse* msgparse_hashtable_lookup(struct msg_parse* msg,
|
||||
*/
|
||||
void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset);
|
||||
|
||||
/**
|
||||
* Log the edns options in the edns option list.
|
||||
* @param level: the verbosity level.
|
||||
* @param info_str: the informational string to be printed before the options.
|
||||
* @param list: the edns option list.
|
||||
*/
|
||||
void log_edns_opt_list(enum verbosity_value level, const char* info_str,
|
||||
struct edns_option* list);
|
||||
|
||||
#endif /* UTIL_DATA_MSGPARSE_H */
|
||||
|
@ -52,6 +52,8 @@
|
||||
#include "util/data/msgencode.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "util/module.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
|
||||
/** MAX TTL default for messages and rrsets */
|
||||
time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
|
||||
@ -76,6 +78,7 @@ parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
qinf->qname_len = msg->qname_len;
|
||||
qinf->qtype = msg->qtype;
|
||||
qinf->qclass = msg->qclass;
|
||||
qinf->local_alias = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -451,6 +454,7 @@ int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
|
||||
int ret;
|
||||
|
||||
qinf->qname = NULL;
|
||||
qinf->local_alias = NULL;
|
||||
*rep = NULL;
|
||||
if(!(msg = regional_alloc(region, sizeof(*msg)))) {
|
||||
return LDNS_RCODE_SERVFAIL;
|
||||
@ -542,6 +546,7 @@ query_info_parse(struct query_info* m, sldns_buffer* query)
|
||||
return 0; /* need qtype, qclass */
|
||||
m->qtype = sldns_buffer_read_u16(query);
|
||||
m->qclass = sldns_buffer_read_u16(query);
|
||||
m->local_alias = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -871,9 +876,12 @@ int edns_opt_append(struct edns_data* edns, struct regional* region,
|
||||
opt->next = NULL;
|
||||
opt->opt_code = code;
|
||||
opt->opt_len = len;
|
||||
opt->opt_data = regional_alloc_init(region, data, len);
|
||||
if(!opt->opt_data)
|
||||
return 0;
|
||||
opt->opt_data = NULL;
|
||||
if(len > 0) {
|
||||
opt->opt_data = regional_alloc_init(region, data, len);
|
||||
if(!opt->opt_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* append at end of list */
|
||||
prevp = &edns->opt_list;
|
||||
@ -883,13 +891,138 @@ int edns_opt_append(struct edns_data* edns, struct regional* region,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int edns_opt_inplace_reply(struct edns_data* edns, struct regional* region)
|
||||
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
uint8_t* data, struct regional* region)
|
||||
{
|
||||
(void)region;
|
||||
/* remove all edns options from the reply, because only the
|
||||
* options that we understand should be in the reply
|
||||
* (sec 6.1.2 RFC 6891) */
|
||||
edns->opt_list = NULL;
|
||||
struct edns_option** prevp;
|
||||
struct edns_option* opt;
|
||||
|
||||
/* allocate new element */
|
||||
opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
|
||||
if(!opt)
|
||||
return 0;
|
||||
opt->next = NULL;
|
||||
opt->opt_code = code;
|
||||
opt->opt_len = len;
|
||||
opt->opt_data = NULL;
|
||||
if(len > 0) {
|
||||
opt->opt_data = regional_alloc_init(region, data, len);
|
||||
if(!opt->opt_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* append at end of list */
|
||||
prevp = list;
|
||||
while(*prevp != NULL) {
|
||||
prevp = &((*prevp)->next);
|
||||
}
|
||||
*prevp = opt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int edns_opt_list_remove(struct edns_option** list, uint16_t code)
|
||||
{
|
||||
/* The list should already be allocated in a region. Freeing the
|
||||
* allocated space in a region is not possible. We just unlink the
|
||||
* required elements and they will be freed together with the region. */
|
||||
|
||||
struct edns_option* prev;
|
||||
struct edns_option* curr;
|
||||
if(!list || !(*list)) return 0;
|
||||
|
||||
/* Unlink and repoint if the element(s) are first in list */
|
||||
while(list && *list && (*list)->opt_code == code) {
|
||||
*list = (*list)->next;
|
||||
}
|
||||
|
||||
if(!list || !(*list)) return 1;
|
||||
/* Unlink elements and reattach the list */
|
||||
prev = *list;
|
||||
curr = (*list)->next;
|
||||
while(curr != NULL) {
|
||||
if(curr->opt_code == code) {
|
||||
prev->next = curr->next;
|
||||
curr = curr->next;
|
||||
} else {
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int inplace_cb_reply_call_generic(
|
||||
struct inplace_cb_reply* callback_list, enum inplace_cb_list_type type,
|
||||
struct query_info* qinfo, struct module_qstate* qstate,
|
||||
struct reply_info* rep, int rcode, struct edns_data* edns,
|
||||
struct regional* region)
|
||||
{
|
||||
struct inplace_cb_reply* cb;
|
||||
struct edns_option* opt_list_out = NULL;
|
||||
if(qstate)
|
||||
opt_list_out = qstate->edns_opts_front_out;
|
||||
for(cb=callback_list; cb; cb=cb->next) {
|
||||
fptr_ok(fptr_whitelist_inplace_cb_reply_generic(cb->cb, type));
|
||||
(void)(*cb->cb)(qinfo, qstate, rep, rcode, edns, &opt_list_out, region,
|
||||
cb->cb_arg);
|
||||
}
|
||||
edns->opt_list = opt_list_out;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
|
||||
struct module_qstate* qstate, struct reply_info* rep, int rcode,
|
||||
struct edns_data* edns, struct regional* region)
|
||||
{
|
||||
return inplace_cb_reply_call_generic(
|
||||
env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo,
|
||||
qstate, rep, rcode, edns, region);
|
||||
}
|
||||
|
||||
int inplace_cb_reply_cache_call(struct module_env* env,
|
||||
struct query_info* qinfo, struct module_qstate* qstate,
|
||||
struct reply_info* rep, int rcode, struct edns_data* edns,
|
||||
struct regional* region)
|
||||
{
|
||||
return inplace_cb_reply_call_generic(
|
||||
env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache,
|
||||
qinfo, qstate, rep, rcode, edns, region);
|
||||
}
|
||||
|
||||
int inplace_cb_reply_local_call(struct module_env* env,
|
||||
struct query_info* qinfo, struct module_qstate* qstate,
|
||||
struct reply_info* rep, int rcode, struct edns_data* edns,
|
||||
struct regional* region)
|
||||
{
|
||||
return inplace_cb_reply_call_generic(
|
||||
env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local,
|
||||
qinfo, qstate, rep, rcode, edns, region);
|
||||
}
|
||||
|
||||
int inplace_cb_reply_servfail_call(struct module_env* env,
|
||||
struct query_info* qinfo, struct module_qstate* qstate,
|
||||
struct reply_info* rep, int rcode, struct edns_data* edns,
|
||||
struct regional* region)
|
||||
{
|
||||
/* We are going to servfail. Remove any potential edns options. */
|
||||
if(qstate)
|
||||
qstate->edns_opts_front_out = NULL;
|
||||
return inplace_cb_reply_call_generic(
|
||||
env->inplace_cb_lists[inplace_cb_reply_servfail],
|
||||
inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, region);
|
||||
}
|
||||
|
||||
int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
|
||||
uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
|
||||
struct regional* region)
|
||||
{
|
||||
struct inplace_cb_query* cb = env->inplace_cb_lists[inplace_cb_query];
|
||||
for(; cb; cb=cb->next) {
|
||||
fptr_ok(fptr_whitelist_inplace_cb_query(cb->cb));
|
||||
(void)(*cb->cb)(qinfo, flags, qstate, addr, addrlen, zone, zonelen,
|
||||
region, cb->cb_arg);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1000,7 +1133,7 @@ struct edns_option* edns_opt_copy_alloc(struct edns_option* list)
|
||||
return result;
|
||||
}
|
||||
|
||||
struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code)
|
||||
struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code)
|
||||
{
|
||||
struct edns_option* p;
|
||||
for(p=list; p; p=p->next) {
|
||||
|
@ -49,8 +49,14 @@ struct alloc_cache;
|
||||
struct iovec;
|
||||
struct regional;
|
||||
struct edns_data;
|
||||
struct edns_option;
|
||||
struct inplace_cb_reply;
|
||||
struct inplace_cb_query;
|
||||
struct module_qstate;
|
||||
struct module_env;
|
||||
struct msg_parse;
|
||||
struct rrset_parse;
|
||||
struct local_rrset;
|
||||
|
||||
/** calculate the prefetch TTL as 90% of original. Calculation
|
||||
* without numerical overflow (uin32_t) */
|
||||
@ -73,6 +79,23 @@ struct query_info {
|
||||
uint16_t qtype;
|
||||
/** qclass, host byte order */
|
||||
uint16_t qclass;
|
||||
/**
|
||||
* Alias local answer(s) for the qname. If 'qname' is an alias defined
|
||||
* in a local zone, this field will be set to the corresponding local
|
||||
* RRset when the alias is determined.
|
||||
* In the initial implementation this can only be a single CNAME RR
|
||||
* (or NULL), but it could possibly be extended to be a DNAME or a
|
||||
* chain of aliases.
|
||||
* Users of this structure are responsible to initialize this field
|
||||
* to be NULL; otherwise other part of query handling code may be
|
||||
* confused.
|
||||
* Users also have to be careful about the lifetime of data. On return
|
||||
* from local zone lookup, it may point to data derived from
|
||||
* configuration that may be dynamically invalidated or data allocated
|
||||
* in an ephemeral regional allocator. A deep copy of the data may
|
||||
* have to be generated if it has to be kept during iterative
|
||||
* resolution. */
|
||||
struct local_rrset* local_alias;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -439,29 +462,133 @@ void log_query_info(enum verbosity_value v, const char* str,
|
||||
|
||||
/**
|
||||
* Append edns option to edns data structure
|
||||
* @param edns: the edns data structure to append the edns option to.
|
||||
* @param region: region to allocate the new edns option.
|
||||
* @param code: the edns option's code.
|
||||
* @param len: the edns option's length.
|
||||
* @param data: the edns option's data.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int edns_opt_append(struct edns_data* edns, struct regional* region,
|
||||
uint16_t code, size_t len, uint8_t* data);
|
||||
|
||||
/**
|
||||
* Append edns option to edns option list
|
||||
* @param list: the edns option list to append the edns option to.
|
||||
* @param code: the edns option's code.
|
||||
* @param len: the edns option's length.
|
||||
* @param data: the edns option's data.
|
||||
* @param region: region to allocate the new edns option.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
uint8_t* data, struct regional* region);
|
||||
|
||||
/**
|
||||
* Remove any option found on the edns option list that matches the code.
|
||||
* @param list: the list of edns options.
|
||||
* @param code: the opt code to remove.
|
||||
* @return true when at least one edns option was removed, false otherwise.
|
||||
*/
|
||||
int edns_opt_list_remove(struct edns_option** list, uint16_t code);
|
||||
|
||||
/**
|
||||
* Find edns option in edns list
|
||||
* @param list: list of edns options (eg. edns.opt_list)
|
||||
* @param code: opt code to find.
|
||||
* @return NULL or the edns_option element.
|
||||
*/
|
||||
struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code);
|
||||
struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code);
|
||||
|
||||
/**
|
||||
* Transform edns data structure from query structure into reply structure.
|
||||
* In place transform, for errors and cache replies.
|
||||
* @param edns: on input contains the edns from the query. On output contains
|
||||
* the edns for the answer. Add new options to the opt_list to put them
|
||||
* in the answer (allocated in the region, with edns_opt_append).
|
||||
* @param region: to allocate stuff in.
|
||||
* @return false on failure (servfail to client, or for some error encodings,
|
||||
* no EDNS options in the answer).
|
||||
* Call the registered functions in the inplace_cb_reply linked list.
|
||||
* This function is going to get called while answering with a resolved query.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query info.
|
||||
* @param qstate: module qstate.
|
||||
* @param rep: Reply info. Could be NULL.
|
||||
* @param rcode: return code.
|
||||
* @param edns: edns data of the reply.
|
||||
* @param region: region to store data.
|
||||
* @return false on failure (a callback function returned an error).
|
||||
*/
|
||||
int edns_opt_inplace_reply(struct edns_data* edns, struct regional* region);
|
||||
int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo,
|
||||
struct module_qstate* qstate, struct reply_info* rep, int rcode,
|
||||
struct edns_data* edns, struct regional* region);
|
||||
|
||||
/**
|
||||
* Call the registered functions in the inplace_cb_reply_cache linked list.
|
||||
* This function is going to get called while answering from cache.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query info.
|
||||
* @param qstate: module qstate. NULL when replying from cache.
|
||||
* @param rep: Reply info.
|
||||
* @param rcode: return code.
|
||||
* @param edns: edns data of the reply. Edns input can be found here.
|
||||
* @param region: region to store data.
|
||||
* @return false on failure (a callback function returned an error).
|
||||
*/
|
||||
int inplace_cb_reply_cache_call(struct module_env* env,
|
||||
struct query_info* qinfo, struct module_qstate* qstate,
|
||||
struct reply_info* rep, int rcode, struct edns_data* edns,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Call the registered functions in the inplace_cb_reply_local linked list.
|
||||
* This function is going to get called while answering with local data.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query info.
|
||||
* @param qstate: module qstate. NULL when replying from cache.
|
||||
* @param rep: Reply info.
|
||||
* @param rcode: return code.
|
||||
* @param edns: edns data of the reply. Edns input can be found here.
|
||||
* @param region: region to store data.
|
||||
* @return false on failure (a callback function returned an error).
|
||||
*/
|
||||
int inplace_cb_reply_local_call(struct module_env* env,
|
||||
struct query_info* qinfo, struct module_qstate* qstate,
|
||||
struct reply_info* rep, int rcode, struct edns_data* edns,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Call the registered functions in the inplace_cb_reply linked list.
|
||||
* This function is going to get called while answering with a servfail.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query info.
|
||||
* @param qstate: module qstate. Contains the edns option lists. Could be NULL.
|
||||
* @param rep: Reply info. NULL when servfail.
|
||||
* @param rcode: return code. LDNS_RCODE_SERVFAIL.
|
||||
* @param edns: edns data of the reply. Edns input can be found here if qstate
|
||||
* is NULL.
|
||||
* @param region: region to store data.
|
||||
* @return false on failure (a callback function returned an error).
|
||||
*/
|
||||
int inplace_cb_reply_servfail_call(struct module_env* env,
|
||||
struct query_info* qinfo, struct module_qstate* qstate,
|
||||
struct reply_info* rep, int rcode, struct edns_data* edns,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Call the registered functions in the inplace_cb_query linked list.
|
||||
* This function is going to get called just before sending a query to a
|
||||
* nameserver.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query info.
|
||||
* @param flags: flags of the query.
|
||||
* @param addr: to which server to send the query.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: name of the zone of the delegation point. wireformat dname.
|
||||
* This is the delegation point name for which the server is deemed
|
||||
* authoritative.
|
||||
* @param zonelen: length of zone.
|
||||
* @param qstate: module qstate.
|
||||
* @param region: region to store data.
|
||||
* @return false on failure (a callback function returned an error).
|
||||
*/
|
||||
int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo,
|
||||
uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Copy edns option list allocated to the new region
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "services/localzone.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/view.h"
|
||||
#include "dns64/dns64.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
@ -203,6 +204,7 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
|
||||
else if(fptr == &val_neg_zone_compare) return 1;
|
||||
else if(fptr == &probetree_cmp) return 1;
|
||||
else if(fptr == &replay_var_compare) return 1;
|
||||
else if(fptr == &view_cmp) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -265,11 +267,9 @@ fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr)
|
||||
/** whitelist env->send_query callbacks */
|
||||
int
|
||||
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct edns_option* opt_list, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen,
|
||||
struct module_qstate* q))
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
|
||||
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q))
|
||||
{
|
||||
if(fptr == &worker_send_query) return 1;
|
||||
else if(fptr == &libworker_send_query) return 1;
|
||||
@ -432,3 +432,34 @@ int fptr_whitelist_print_func(void (*fptr)(char*,void*))
|
||||
else if(fptr == &remote_get_opt_ssl) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_t* fptr,
|
||||
enum inplace_cb_list_type type)
|
||||
{
|
||||
#ifndef WITH_PYTHONMODULE
|
||||
(void)fptr;
|
||||
#endif
|
||||
if(type == inplace_cb_reply) {
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
if(fptr == &python_inplace_cb_reply_generic) return 1;
|
||||
#endif
|
||||
} else if(type == inplace_cb_reply_cache) {
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
if(fptr == &python_inplace_cb_reply_generic) return 1;
|
||||
#endif
|
||||
} else if(type == inplace_cb_reply_local) {
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
if(fptr == &python_inplace_cb_reply_generic) return 1;
|
||||
#endif
|
||||
} else if(type == inplace_cb_reply_servfail) {
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
if(fptr == &python_inplace_cb_reply_generic) return 1;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_t* ATTR_UNUSED(fptr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -210,11 +210,9 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr);
|
||||
* @return false if not in whitelist.
|
||||
*/
|
||||
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct edns_option*, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen,
|
||||
struct module_qstate* q));
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
|
||||
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q));
|
||||
|
||||
/**
|
||||
* Check function pointer whitelist for module_env detach_subs callback values.
|
||||
@ -335,6 +333,24 @@ int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr);
|
||||
*/
|
||||
int fptr_whitelist_print_func(void (*fptr)(char*,void*));
|
||||
|
||||
/**
|
||||
* Check function pointer whitelist for inplace_cb_reply,
|
||||
* inplace_cb_reply_cache, inplace_cb_reply_local and inplace_cb_reply_servfail
|
||||
* func values.
|
||||
* @param fptr: function pointer to check.
|
||||
* @param type: the type of the callback function.
|
||||
* @return false if not in whitelist.
|
||||
*/
|
||||
int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_t* fptr,
|
||||
enum inplace_cb_list_type type);
|
||||
|
||||
/**
|
||||
* Check function pointer whitelist for inplace_cb_query func values.
|
||||
* @param fptr: function pointer to check.
|
||||
* @return false if not in whitelist.
|
||||
*/
|
||||
int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_t* fptr);
|
||||
|
||||
/** Due to module breakage by fptr wlist, these test app declarations
|
||||
* are presented here */
|
||||
/**
|
||||
|
@ -3962,12 +3962,15 @@
|
||||
4743,
|
||||
4744,
|
||||
4745,
|
||||
4746,
|
||||
4747,
|
||||
4749,
|
||||
4750,
|
||||
4751,
|
||||
4752,
|
||||
4753,
|
||||
4754,
|
||||
4755,
|
||||
4784,
|
||||
4785,
|
||||
4789,
|
||||
@ -4498,6 +4501,7 @@
|
||||
6626,
|
||||
6627,
|
||||
6628,
|
||||
6629,
|
||||
6633,
|
||||
6634,
|
||||
6635,
|
||||
@ -4882,6 +4886,7 @@
|
||||
9024,
|
||||
9025,
|
||||
9026,
|
||||
9060,
|
||||
9080,
|
||||
9084,
|
||||
9085,
|
||||
@ -5208,6 +5213,7 @@
|
||||
18463,
|
||||
18634,
|
||||
18635,
|
||||
18668,
|
||||
18769,
|
||||
18881,
|
||||
18888,
|
||||
@ -5215,6 +5221,7 @@
|
||||
19007,
|
||||
19191,
|
||||
19194,
|
||||
19220,
|
||||
19283,
|
||||
19315,
|
||||
19398,
|
||||
@ -5378,6 +5385,7 @@
|
||||
34249,
|
||||
34378,
|
||||
34379,
|
||||
34567,
|
||||
34962,
|
||||
34963,
|
||||
34964,
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "util/module.h"
|
||||
#include "sldns/wire2str.h"
|
||||
|
||||
const char*
|
||||
strextstate(enum module_ext_state s)
|
||||
@ -69,3 +70,256 @@ strmodulevent(enum module_ev e)
|
||||
}
|
||||
return "bad_event_value";
|
||||
}
|
||||
|
||||
int
|
||||
edns_known_options_init(struct module_env* env)
|
||||
{
|
||||
env->edns_known_options_num = 0;
|
||||
env->edns_known_options = (struct edns_known_option*)calloc(
|
||||
MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
|
||||
if(!env->edns_known_options) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
edns_known_options_delete(struct module_env* env)
|
||||
{
|
||||
free(env->edns_known_options);
|
||||
env->edns_known_options = NULL;
|
||||
env->edns_known_options_num = 0;
|
||||
}
|
||||
|
||||
int
|
||||
edns_register_option(uint16_t opt_code, int bypass_cache_stage,
|
||||
int no_aggregation, struct module_env* env)
|
||||
{
|
||||
size_t i;
|
||||
if(env->worker) {
|
||||
log_err("invalid edns registration: "
|
||||
"trying to register option after module init phase");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking if we are full first is faster but it does not provide
|
||||
* the option to change the flags when the array is full.
|
||||
* It only impacts unbound initialization, leave it for now.
|
||||
*/
|
||||
/* Check if the option is already registered. */
|
||||
for(i=0; i<env->edns_known_options_num; i++)
|
||||
if(env->edns_known_options[i].opt_code == opt_code)
|
||||
break;
|
||||
/* If it is not yet registered check if we have space to add a new one. */
|
||||
if(i == env->edns_known_options_num) {
|
||||
if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
|
||||
log_err("invalid edns registration: maximum options reached");
|
||||
return 0;
|
||||
}
|
||||
env->edns_known_options_num++;
|
||||
}
|
||||
env->edns_known_options[i].opt_code = opt_code;
|
||||
env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
|
||||
env->edns_known_options[i].no_aggregation = no_aggregation;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
inplace_cb_reply_register_generic(inplace_cb_reply_func_t* cb,
|
||||
enum inplace_cb_list_type type, void* cb_arg, struct module_env* env)
|
||||
{
|
||||
struct inplace_cb_reply* callback;
|
||||
struct inplace_cb_reply** prevp;
|
||||
if(env->worker) {
|
||||
log_err("invalid edns callback registration: "
|
||||
"trying to register callback after module init phase");
|
||||
return 0;
|
||||
}
|
||||
|
||||
callback = (struct inplace_cb_reply*)calloc(1, sizeof(*callback));
|
||||
if(callback == NULL) {
|
||||
log_err("out of memory during edns callback registration.");
|
||||
return 0;
|
||||
}
|
||||
callback->next = NULL;
|
||||
callback->cb = cb;
|
||||
callback->cb_arg = cb_arg;
|
||||
|
||||
prevp = (struct inplace_cb_reply**) &env->inplace_cb_lists[type];
|
||||
/* append at end of list */
|
||||
while(*prevp != NULL)
|
||||
prevp = &((*prevp)->next);
|
||||
*prevp = callback;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
inplace_cb_reply_register(inplace_cb_reply_func_t* cb, void* cb_arg,
|
||||
struct module_env* env)
|
||||
{
|
||||
return inplace_cb_reply_register_generic(cb, inplace_cb_reply, cb_arg,
|
||||
env);
|
||||
}
|
||||
|
||||
int
|
||||
inplace_cb_reply_cache_register(inplace_cb_reply_func_t* cb, void* cb_arg,
|
||||
struct module_env* env)
|
||||
{
|
||||
return inplace_cb_reply_register_generic(cb, inplace_cb_reply_cache,
|
||||
cb_arg, env);
|
||||
}
|
||||
|
||||
int
|
||||
inplace_cb_reply_local_register(inplace_cb_reply_func_t* cb, void* cb_arg,
|
||||
struct module_env* env)
|
||||
{
|
||||
return inplace_cb_reply_register_generic(cb, inplace_cb_reply_local,
|
||||
cb_arg, env);
|
||||
}
|
||||
|
||||
int
|
||||
inplace_cb_reply_servfail_register(inplace_cb_reply_func_t* cb, void* cb_arg,
|
||||
struct module_env* env)
|
||||
{
|
||||
return inplace_cb_reply_register_generic(cb, inplace_cb_reply_servfail,
|
||||
cb_arg, env);
|
||||
}
|
||||
|
||||
static void
|
||||
inplace_cb_reply_delete_generic(struct module_env* env,
|
||||
enum inplace_cb_list_type type)
|
||||
{
|
||||
struct inplace_cb_reply* curr = env->inplace_cb_lists[type];
|
||||
struct inplace_cb_reply* tmp;
|
||||
/* delete list */
|
||||
while(curr) {
|
||||
tmp = curr->next;
|
||||
free(curr);
|
||||
curr = tmp;
|
||||
}
|
||||
/* update head pointer */
|
||||
env->inplace_cb_lists[type] = NULL;
|
||||
}
|
||||
|
||||
void inplace_cb_reply_delete(struct module_env* env)
|
||||
{
|
||||
inplace_cb_reply_delete_generic(env, inplace_cb_reply);
|
||||
}
|
||||
|
||||
void inplace_cb_reply_cache_delete(struct module_env* env)
|
||||
{
|
||||
inplace_cb_reply_delete_generic(env, inplace_cb_reply_cache);
|
||||
}
|
||||
|
||||
void inplace_cb_reply_servfail_delete(struct module_env* env)
|
||||
{
|
||||
inplace_cb_reply_delete_generic(env, inplace_cb_reply_servfail);
|
||||
}
|
||||
|
||||
int
|
||||
inplace_cb_query_register(inplace_cb_query_func_t* cb, void* cb_arg,
|
||||
struct module_env* env)
|
||||
{
|
||||
struct inplace_cb_query* callback;
|
||||
struct inplace_cb_query** prevp;
|
||||
if(env->worker) {
|
||||
log_err("invalid edns callback registration: "
|
||||
"trying to register callback after module init phase");
|
||||
return 0;
|
||||
}
|
||||
|
||||
callback = (struct inplace_cb_query*)calloc(1, sizeof(*callback));
|
||||
if(callback == NULL) {
|
||||
log_err("out of memory during edns callback registration.");
|
||||
return 0;
|
||||
}
|
||||
callback->next = NULL;
|
||||
callback->cb = cb;
|
||||
callback->cb_arg = cb_arg;
|
||||
|
||||
prevp = (struct inplace_cb_query**)
|
||||
&env->inplace_cb_lists[inplace_cb_query];
|
||||
/* append at end of list */
|
||||
while(*prevp != NULL)
|
||||
prevp = &((*prevp)->next);
|
||||
*prevp = callback;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
inplace_cb_query_delete(struct module_env* env)
|
||||
{
|
||||
struct inplace_cb_query* curr = env->inplace_cb_lists[inplace_cb_query];
|
||||
struct inplace_cb_query* tmp;
|
||||
/* delete list */
|
||||
while(curr) {
|
||||
tmp = curr->next;
|
||||
free(curr);
|
||||
curr = tmp;
|
||||
}
|
||||
/* update head pointer */
|
||||
env->inplace_cb_lists[inplace_cb_query] = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
inplace_cb_lists_delete(struct module_env* env)
|
||||
{
|
||||
inplace_cb_reply_delete(env);
|
||||
inplace_cb_reply_cache_delete(env);
|
||||
inplace_cb_reply_servfail_delete(env);
|
||||
inplace_cb_query_delete(env);
|
||||
}
|
||||
|
||||
struct edns_known_option*
|
||||
edns_option_is_known(uint16_t opt_code, struct module_env* env)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<env->edns_known_options_num; i++)
|
||||
if(env->edns_known_options[i].opt_code == opt_code)
|
||||
return env->edns_known_options + i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
|
||||
{
|
||||
size_t i;
|
||||
for(; list; list=list->next)
|
||||
for(i=0; i<env->edns_known_options_num; i++)
|
||||
if(env->edns_known_options[i].opt_code == list->opt_code &&
|
||||
env->edns_known_options[i].bypass_cache_stage == 1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
edns_unique_mesh_state(struct edns_option* list, struct module_env* env)
|
||||
{
|
||||
size_t i;
|
||||
for(; list; list=list->next)
|
||||
for(i=0; i<env->edns_known_options_num; i++)
|
||||
if(env->edns_known_options[i].opt_code == list->opt_code &&
|
||||
env->edns_known_options[i].no_aggregation == 1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
log_edns_known_options(enum verbosity_value level, struct module_env* env)
|
||||
{
|
||||
size_t i;
|
||||
char str[32], *s;
|
||||
size_t slen;
|
||||
if(env->edns_known_options_num > 0 && verbosity >= level) {
|
||||
verbose(level, "EDNS known options:");
|
||||
verbose(level, " Code: Bypass_cache_stage: Aggregate_mesh:");
|
||||
for(i=0; i<env->edns_known_options_num; i++) {
|
||||
s = str;
|
||||
slen = sizeof(str);
|
||||
(void)sldns_wire2str_edns_option_code_print(&s, &slen,
|
||||
env->edns_known_options[i].opt_code);
|
||||
verbose(level, " %-8.8s %-19s %-15s", str,
|
||||
env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
|
||||
env->edns_known_options[i].no_aggregation?"NO":"YES");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +178,115 @@ struct iter_hints;
|
||||
/** Maximum number of modules in operation */
|
||||
#define MAX_MODULE 5
|
||||
|
||||
/** Maximum number of known edns options */
|
||||
#define MAX_KNOWN_EDNS_OPTS 256
|
||||
|
||||
enum inplace_cb_list_type {
|
||||
/* Inplace callbacks for when a resolved reply is ready to be sent to the
|
||||
* front.*/
|
||||
inplace_cb_reply = 0,
|
||||
/* Inplace callbacks for when a reply is given from the cache. */
|
||||
inplace_cb_reply_cache,
|
||||
/* Inplace callbacks for when a reply is given with local data
|
||||
* (or Chaos reply). */
|
||||
inplace_cb_reply_local,
|
||||
/* Inplace callbacks for when the reply is servfail. */
|
||||
inplace_cb_reply_servfail,
|
||||
/* Inplace callbacks for when a query is ready to be sent to the back.*/
|
||||
inplace_cb_query,
|
||||
/* Total number of types. Used for array initialization.
|
||||
* Should always be last. */
|
||||
inplace_cb_types_total
|
||||
};
|
||||
|
||||
|
||||
/** Known edns option. Can be populated during modules' init. */
|
||||
struct edns_known_option {
|
||||
/** type of this edns option */
|
||||
uint16_t opt_code;
|
||||
/** whether the option needs to bypass the cache stage */
|
||||
int bypass_cache_stage;
|
||||
/** whether the option needs mesh aggregation */
|
||||
int no_aggregation;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inplace callback function called before replying.
|
||||
* Called as func(edns, qstate, opt_list_out, qinfo, reply_info, rcode,
|
||||
* region, python_callback)
|
||||
* Where:
|
||||
* qinfo: the query info.
|
||||
* qstate: the module state. NULL when calling before the query reaches the
|
||||
* mesh states.
|
||||
* rep: reply_info. Could be NULL.
|
||||
* rcode: the return code.
|
||||
* edns: the edns_data of the reply. When qstate is NULL, it is also used as
|
||||
* the edns input.
|
||||
* opt_list_out: the edns options list for the reply.
|
||||
* region: region to store data.
|
||||
* python_callback: only used for registering a python callback function.
|
||||
*/
|
||||
typedef int inplace_cb_reply_func_t(struct query_info* qinfo,
|
||||
struct module_qstate* qstate, struct reply_info* rep, int rcode,
|
||||
struct edns_data* edns, struct edns_option** opt_list_out,
|
||||
struct regional* region, void* python_callback);
|
||||
|
||||
/**
|
||||
* Inplace callback list of registered routines to be called before replying
|
||||
* with a resolved query.
|
||||
*/
|
||||
struct inplace_cb_reply {
|
||||
/** next in list */
|
||||
struct inplace_cb_reply* next;
|
||||
/**
|
||||
* Inplace callback routine for cache stage response.
|
||||
* called as cb(qinfo, qstate, qinfo, reply_info, rcode, edns,
|
||||
* opt_list_out, region, python_callback);
|
||||
* python_callback is only used for registering a python callback function.
|
||||
*/
|
||||
inplace_cb_reply_func_t* cb;
|
||||
void* cb_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inplace callback function called before sending the query to a nameserver.
|
||||
* Called as func(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region,
|
||||
* python_callback)
|
||||
* Where:
|
||||
* qinfo: query info.
|
||||
* flags: flags of the query.
|
||||
* qstate: query state.
|
||||
* addr: to which server to send the query.
|
||||
* addrlen: length of addr.
|
||||
* zone: name of the zone of the delegation point. wireformat dname.
|
||||
* This is the delegation point name for which the server is deemed
|
||||
* authoritative.
|
||||
* zonelen: length of zone.
|
||||
* region: region to store data.
|
||||
* python_callback: only used for registering a python callback function.
|
||||
*/
|
||||
typedef int inplace_cb_query_func_t(struct query_info* qinfo, uint16_t flags,
|
||||
struct module_qstate* qstate, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region,
|
||||
void* python_callback);
|
||||
|
||||
/**
|
||||
* Inplace callback list of registered routines to be called before quering a
|
||||
* nameserver.
|
||||
*/
|
||||
struct inplace_cb_query {
|
||||
/** next in list */
|
||||
struct inplace_cb_query* next;
|
||||
/**
|
||||
* Inplace callback routine for cache stage response.
|
||||
* called as cb(qinfo, flags, qstate, addr, addrlen, zone, zonelen,
|
||||
* region, python_callback);
|
||||
* python_callback is only used for registering a python callback function.
|
||||
*/
|
||||
inplace_cb_query_func_t* cb;
|
||||
void* cb_arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Module environment.
|
||||
* Services and data provided to the module.
|
||||
@ -202,10 +311,7 @@ struct module_env {
|
||||
* will cause operate() to be called with event timeout or reply.
|
||||
* The time until a timeout is calculated from roundtrip timing,
|
||||
* several UDP retries are attempted.
|
||||
* @param qname: query name. (host order)
|
||||
* @param qnamelen: length in bytes of qname, including trailing 0.
|
||||
* @param qtype: query type. (host order)
|
||||
* @param qclass: query class. (host order)
|
||||
* @param qinfo: query info.
|
||||
* @param flags: host order flags word, with opcode and CD bit.
|
||||
* @param dnssec: if set, EDNS record will have bits set.
|
||||
* If EDNS_DO bit is set, DO bit is set in EDNS records.
|
||||
@ -214,23 +320,22 @@ struct module_env {
|
||||
* EDNS, the answer is likely to be useless for this domain.
|
||||
* @param nocaps: do not use caps_for_id, use the qname as given.
|
||||
* (ignored if caps_for_id is disabled).
|
||||
* @param opt_list: set these EDNS options on the outgoing packet.
|
||||
* or NULL if none (the list is deep-copied).
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: delegation point name.
|
||||
* @param zonelen: length of zone name.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param q: wich query state to reactivate upon return.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent. Or returns an outbound entry with qsent and qstate set.
|
||||
* This outbound_entry will be used on later module invocations
|
||||
* that involve this query (timeout, error or reply).
|
||||
*/
|
||||
struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, struct edns_option* opt_list,
|
||||
struct outbound_entry* (*send_query)(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* q);
|
||||
uint8_t* zone, size_t zonelen, int ssl_upstream,
|
||||
struct module_qstate* q);
|
||||
|
||||
/**
|
||||
* Detach-subqueries.
|
||||
@ -335,6 +440,17 @@ struct module_env {
|
||||
struct iter_hints* hints;
|
||||
/** module specific data. indexed by module id. */
|
||||
void* modinfo[MAX_MODULE];
|
||||
|
||||
/* Shared linked list of inplace callback functions */
|
||||
void* inplace_cb_lists[inplace_cb_types_total];
|
||||
|
||||
/**
|
||||
* Shared array of known edns options (size MAX_KNOWN_EDNS_OPTS).
|
||||
* Filled by edns literate modules during init.
|
||||
*/
|
||||
struct edns_known_option* edns_known_options;
|
||||
/* Number of known edns options */
|
||||
size_t edns_known_options_num;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -433,6 +549,19 @@ struct module_qstate {
|
||||
struct mesh_state* mesh_info;
|
||||
/** how many seconds before expiry is this prefetched (0 if not) */
|
||||
time_t prefetch_leeway;
|
||||
|
||||
/** incoming edns options from the front end */
|
||||
struct edns_option* edns_opts_front_in;
|
||||
/** outgoing edns options to the back end */
|
||||
struct edns_option* edns_opts_back_out;
|
||||
/** incoming edns options from the back end */
|
||||
struct edns_option* edns_opts_back_in;
|
||||
/** outgoing edns options to the front end */
|
||||
struct edns_option* edns_opts_front_out;
|
||||
/** whether modules should answer from the cache */
|
||||
int no_cache_lookup;
|
||||
/** whether modules should store answer in the cache */
|
||||
int no_cache_store;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -522,4 +651,156 @@ const char* strextstate(enum module_ext_state s);
|
||||
*/
|
||||
const char* strmodulevent(enum module_ev e);
|
||||
|
||||
/**
|
||||
* Initialize the edns known options by allocating the required space.
|
||||
* @param env: the module environment.
|
||||
* @return false on failure (no memory).
|
||||
*/
|
||||
int edns_known_options_init(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Free the allocated space for the known edns options.
|
||||
* @param env: the module environment.
|
||||
*/
|
||||
void edns_known_options_delete(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Register a known edns option. Overwrite the flags if it is already
|
||||
* registered. Used before creating workers to register known edns options.
|
||||
* @param opt_code: the edns option code.
|
||||
* @param bypass_cache_stage: whether the option interacts with the cache.
|
||||
* @param no_aggregation: whether the option implies more specific
|
||||
* aggregation.
|
||||
* @param env: the module environment.
|
||||
* @return true on success, false on failure (registering more options than
|
||||
* allowed or trying to register after the environment is copied to the
|
||||
* threads.)
|
||||
*/
|
||||
int edns_register_option(uint16_t opt_code, int bypass_cache_stage,
|
||||
int no_aggregation, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Register an inplace callback function called before replying with a resolved
|
||||
* query.
|
||||
* @param cb: pointer to the callback function.
|
||||
* @param cb_arg: optional argument for the callback function.
|
||||
* @param env: the module environment.
|
||||
* @return true on success, false on failure (out of memory or trying to
|
||||
* register after the environment is copied to the threads.)
|
||||
*/
|
||||
int inplace_cb_reply_register(inplace_cb_reply_func_t* cb, void* cb_arg,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Register an inplace callback function called before replying from the cache.
|
||||
* @param cb: pointer to the callback function.
|
||||
* @param cb_arg: optional argument for the callback function.
|
||||
* @param env: the module environment.
|
||||
* @return true on success, false on failure (out of memory or trying to
|
||||
* register after the environment is copied to the threads.)
|
||||
*/
|
||||
int inplace_cb_reply_cache_register(inplace_cb_reply_func_t* cb, void* cb_arg,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Register an inplace callback function called before replying with local
|
||||
* data or Chaos reply.
|
||||
* @param cb: pointer to the callback function.
|
||||
* @param cb_arg: optional argument for the callback function.
|
||||
* @param env: the module environment.
|
||||
* @return true on success, false on failure (out of memory or trying to
|
||||
* register after the environment is copied to the threads.)
|
||||
*/
|
||||
int inplace_cb_reply_local_register(inplace_cb_reply_func_t* cb, void* cb_arg,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Register an inplace callback function called before replying with servfail.
|
||||
* @param cb: pointer to the callback function.
|
||||
* @param cb_arg: optional argument for the callback function.
|
||||
* @param env: the module environment.
|
||||
* @return true on success, false on failure (out of memory or trying to
|
||||
* register after the environment is copied to the threads.)
|
||||
*/
|
||||
int inplace_cb_reply_servfail_register(inplace_cb_reply_func_t* cb,
|
||||
void* cb_arg, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Delete the inplace_cb_reply callback linked list.
|
||||
* @param env: the module environment.
|
||||
*/
|
||||
void inplace_cb_reply_delete(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Delete the inplace_cb_reply_cache callback linked list.
|
||||
* @param env: the module environment.
|
||||
*/
|
||||
void inplace_cb_reply_cache_delete(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Delete the inplace_cb_reply_servfail callback linked list.
|
||||
* @param env: the module environment.
|
||||
*/
|
||||
void inplace_cb_reply_servfail_delete(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Register an inplace callback function called before quering a nameserver.
|
||||
* @param cb: pointer to the callback function.
|
||||
* @param cb_arg: optional argument for the callback function.
|
||||
* @param env: the module environment.
|
||||
* @return true on success, false on failure (out of memory or trying to
|
||||
* register after the environment is copied to the threads.)
|
||||
*/
|
||||
int inplace_cb_query_register(inplace_cb_query_func_t* cb, void* cb_arg,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Delete the inplace_cb_query callback linked list.
|
||||
* @param env: the module environment.
|
||||
*/
|
||||
void inplace_cb_query_delete(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Delete all the inplace callback linked lists.
|
||||
* @param env: the module environment.
|
||||
*/
|
||||
void inplace_cb_lists_delete(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Check if an edns option is known.
|
||||
* @param opt_code: the edns option code.
|
||||
* @param env: the module environment.
|
||||
* @return pointer to registered option if the edns option is known,
|
||||
* NULL otherwise.
|
||||
*/
|
||||
struct edns_known_option* edns_option_is_known(uint16_t opt_code,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Check if an edns option needs to bypass the reply from cache stage.
|
||||
* @param list: the edns options.
|
||||
* @param env: the module environment.
|
||||
* @return true if an edns option needs to bypass the cache stage,
|
||||
* false otherwise.
|
||||
*/
|
||||
int edns_bypass_cache_stage(struct edns_option* list,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Check if an edns option needs a unique mesh state.
|
||||
* @param list: the edns options.
|
||||
* @param env: the module environment.
|
||||
* @return true if an edns option needs a unique mesh state,
|
||||
* false otherwise.
|
||||
*/
|
||||
int edns_unique_mesh_state(struct edns_option* list, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Log the known edns options.
|
||||
* @param level: the desired verbosity level.
|
||||
* @param env: the module environment.
|
||||
*/
|
||||
void log_edns_known_options(enum verbosity_value level,
|
||||
struct module_env* env);
|
||||
|
||||
#endif /* UTIL_MODULE_H */
|
||||
|
@ -2334,6 +2334,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
|
||||
qinfo.qname_len = tp->namelen;
|
||||
qinfo.qtype = LDNS_RR_TYPE_DNSKEY;
|
||||
qinfo.qclass = tp->dclass;
|
||||
qinfo.local_alias = NULL;
|
||||
log_query_info(VERB_ALGO, "autotrust probe", &qinfo);
|
||||
verbose(VERB_ALGO, "retry probe set in %d seconds",
|
||||
(int)tp->autr->next_probe_time - (int)*env->now);
|
||||
|
@ -1007,6 +1007,7 @@ int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
|
||||
qinfo.qname = qname;
|
||||
qinfo.qtype = LDNS_RR_TYPE_DLV;
|
||||
qinfo.qclass = qclass;
|
||||
qinfo.local_alias = NULL;
|
||||
if(!nsec_proves_nodata(nsec, &qinfo, &wc) &&
|
||||
!val_nsec_proves_name_error(nsec, qname)) {
|
||||
/* the NSEC is not a denial for the DLV */
|
||||
|
@ -343,7 +343,7 @@ int nsec_proves_nodata(struct ub_packed_rrset_key* nsec,
|
||||
} else {
|
||||
/* See if the next owner name covers a wildcard
|
||||
* empty non-terminal. */
|
||||
while (dname_strict_subdomain_c(nm, nsec->rk.dname)) {
|
||||
while (dname_canonical_compare(nsec->rk.dname, nm) < 0) {
|
||||
/* wildcard does not apply if qname below
|
||||
* the name that exists under the '*' */
|
||||
if (dname_subdomain_c(qinfo->qname, nm))
|
||||
|
@ -1180,7 +1180,7 @@ nsec3_do_prove_nodata(struct module_env* env, struct nsec3_filter* flt,
|
||||
nsec3_has_type(rrset, rr, LDNS_RR_TYPE_NS) &&
|
||||
!nsec3_has_type(rrset, rr, LDNS_RR_TYPE_SOA)) {
|
||||
verbose(VERB_ALGO, "nsec3 nodata proof: matching "
|
||||
"wilcard is a delegation, bogus");
|
||||
"wildcard is a delegation, bogus");
|
||||
return sec_status_bogus;
|
||||
}
|
||||
/* everything is peachy keen, except for optout spans */
|
||||
|
@ -72,6 +72,9 @@
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
/** fake DSA support for unit tests */
|
||||
int fake_dsa = 0;
|
||||
|
||||
/* return size of digest if supported, or 0 otherwise */
|
||||
size_t
|
||||
nsec3_hash_algo_size_supported(int id)
|
||||
@ -192,9 +195,13 @@ dnskey_algo_id_is_supported(int id)
|
||||
case LDNS_RSAMD5:
|
||||
/* RFC 6725 deprecates RSAMD5 */
|
||||
return 0;
|
||||
#ifdef USE_DSA
|
||||
case LDNS_DSA:
|
||||
case LDNS_DSA_NSEC3:
|
||||
#ifdef USE_DSA
|
||||
return 1;
|
||||
#else
|
||||
if(fake_dsa) return 1;
|
||||
return 0;
|
||||
#endif
|
||||
case LDNS_RSASHA1:
|
||||
case LDNS_RSASHA1_NSEC3:
|
||||
@ -264,8 +271,12 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
|
||||
dsasig = DSA_SIG_new();
|
||||
if(!dsasig) return 0;
|
||||
|
||||
#ifdef HAVE_DSA_SIG_SET0
|
||||
if(!DSA_SIG_set0(dsasig, R, S)) return 0;
|
||||
#else
|
||||
dsasig->r = R;
|
||||
dsasig->s = S;
|
||||
#endif
|
||||
*sig = NULL;
|
||||
newlen = i2d_DSA_SIG(dsasig, sig);
|
||||
if(newlen < 0) {
|
||||
@ -406,7 +417,11 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
|
||||
"EVP_PKEY_assign_DSA failed");
|
||||
return 0;
|
||||
}
|
||||
#ifdef HAVE_EVP_DSS1
|
||||
*digest_type = EVP_dss1();
|
||||
#else
|
||||
*digest_type = EVP_sha1();
|
||||
#endif
|
||||
|
||||
break;
|
||||
#endif /* USE_DSA */
|
||||
@ -545,6 +560,11 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
|
||||
EVP_MD_CTX* ctx;
|
||||
int res, dofree = 0, docrypto_free = 0;
|
||||
EVP_PKEY *evp_key = NULL;
|
||||
|
||||
#ifndef USE_DSA
|
||||
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && fake_dsa)
|
||||
return sec_status_secure;
|
||||
#endif
|
||||
|
||||
if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
|
||||
verbose(VERB_QUERY, "verify: failed to setup key");
|
||||
|
@ -1291,7 +1291,7 @@ adjust_ttl(struct val_env* ve, uint32_t unow,
|
||||
*/
|
||||
if(MIN_TTL > (time_t)origttl && d->ttl > MIN_TTL) {
|
||||
verbose(VERB_QUERY, "rrset TTL larger than original and minimum"
|
||||
" TTL, adjusting TTL downwards to mimimum ttl");
|
||||
" TTL, adjusting TTL downwards to minimum ttl");
|
||||
d->ttl = MIN_TTL;
|
||||
}
|
||||
else if(MIN_TTL <= origttl && d->ttl > (time_t)origttl) {
|
||||
|
@ -219,7 +219,7 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf,
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if(subtype == VAL_CLASS_POSITIVE || subtype == VAL_CLASS_ANY) {
|
||||
if(subtype == VAL_CLASS_POSITIVE) {
|
||||
/* check for the answer rrset */
|
||||
for(i=skip; i<rep->an_numrrsets; i++) {
|
||||
if(query_dname_compare(qinf->qname,
|
||||
@ -271,6 +271,29 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf,
|
||||
signer_name, signer_len, &matchcount);
|
||||
}
|
||||
}
|
||||
} else if(subtype == VAL_CLASS_ANY) {
|
||||
/* check for one of the answer rrset that has signatures,
|
||||
* or potentially a DNAME is in use with a different qname */
|
||||
for(i=skip; i<rep->an_numrrsets; i++) {
|
||||
if(query_dname_compare(qinf->qname,
|
||||
rep->rrsets[i]->rk.dname) == 0) {
|
||||
val_find_rrset_signer(rep->rrsets[i],
|
||||
signer_name, signer_len);
|
||||
if(*signer_name)
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* no answer RRSIGs with qname, try a DNAME */
|
||||
if(skip < rep->an_numrrsets &&
|
||||
ntohs(rep->rrsets[skip]->rk.type) ==
|
||||
LDNS_RR_TYPE_DNAME) {
|
||||
val_find_rrset_signer(rep->rrsets[skip],
|
||||
signer_name, signer_len);
|
||||
if(*signer_name)
|
||||
return;
|
||||
}
|
||||
*signer_name = NULL;
|
||||
*signer_len = 0;
|
||||
} else if(subtype == VAL_CLASS_REFERRAL) {
|
||||
/* find keys for the item at skip */
|
||||
if(skip < rep->rrset_count) {
|
||||
@ -1115,6 +1138,7 @@ val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c,
|
||||
qinfo.qname_len = nmlen;
|
||||
qinfo.qtype = LDNS_RR_TYPE_DS;
|
||||
qinfo.qclass = c;
|
||||
qinfo.local_alias = NULL;
|
||||
/* do not add SOA to reply message, it is going to be used internal */
|
||||
msg = val_neg_getmsg(env->neg_cache, &qinfo, region, env->rrset_cache,
|
||||
env->scratch_buffer, *env->now, 0, topname);
|
||||
|
@ -181,6 +181,7 @@ val_init(struct module_env* env, int id)
|
||||
log_err("validator: could not apply configuration settings.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -377,6 +378,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
|
||||
ask.qname_len = namelen;
|
||||
ask.qtype = qtype;
|
||||
ask.qclass = qclass;
|
||||
ask.local_alias = NULL;
|
||||
log_query_info(VERB_ALGO, "generate request", &ask);
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
/* enable valrec flag to avoid recursion to the same validation
|
||||
@ -2087,7 +2089,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
}
|
||||
|
||||
/* store results in cache */
|
||||
if(qstate->query_flags&BIT_RD) {
|
||||
if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) {
|
||||
/* if secure, this will override cache anyway, no need
|
||||
* to check if from parentNS */
|
||||
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
|
||||
@ -2280,6 +2282,7 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
(void)outbound;
|
||||
if(event == module_event_new ||
|
||||
(event == module_event_pass && vq == NULL)) {
|
||||
|
||||
/* pass request to next module, to get it */
|
||||
verbose(VERB_ALGO, "validator: pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
@ -2288,6 +2291,7 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
if(event == module_event_moddone) {
|
||||
/* check if validation is needed */
|
||||
verbose(VERB_ALGO, "validator: nextmodule returned");
|
||||
|
||||
if(!needs_validation(qstate, qstate->return_rcode,
|
||||
qstate->return_msg)) {
|
||||
/* no need to validate this */
|
||||
|
@ -26,7 +26,7 @@ SRCS= alloc.c as112.c autotrust.c cachedb.c config_file.c configlexer.l \
|
||||
sbuffer.c slabhash.c str2wire.c timehist.c tube.c \
|
||||
ub_event_pluggable.c val_anchor.c val_kcache.c val_kentry.c \
|
||||
val_neg.c val_nsec.c val_nsec3.c val_secalgo.c val_sigcrypt.c \
|
||||
val_utils.c validator.c winsock_event.c wire2str.c
|
||||
val_utils.c validator.c view.c winsock_event.c wire2str.c
|
||||
|
||||
WARNS?= 3
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user