import unbound 1.6.0
This commit is contained in:
parent
ca95f55bca
commit
8d4ae2d561
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
testdata/*.[0-9] linguist-documentation
|
138
Makefile.in
138
Makefile.in
@ -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);
|
||||
|
12
config.h.in
12
config.h.in
@ -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
configure
vendored
77
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\\"
|
||||
|
||||
|
32
configure.ac
32
configure.ac
@ -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;
|
||||
|
337
daemon/remote.c
337
daemon/remote.c
@ -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;
|
||||
}
|
||||
|
253
daemon/worker.c
253
daemon/worker.c
@ -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
doc/CNAME-basedRedirectionDesignNotes.pdf
Normal file
BIN
doc/CNAME-basedRedirectionDesignNotes.pdf
Normal file
Binary file not shown.
174
doc/Changelog
174
doc/Changelog
@ -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
|
||||
|
@ -80,10 +80,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,10 +1,12 @@
|
||||
.. _log_handler:
|
||||
|
||||
Packet logger
|
||||
=========================
|
||||
=============
|
||||
|
||||
This example shows how to log and print details about query and response.
|
||||
As soon as the ``iterator`` has finished (event is :data:`module_event_moddone`), ``qstate.return_msg`` contains response packet or ``None``.
|
||||
As soon as the ``iterator`` has finished (event is
|
||||
:data:`module_event_moddone`), ``qstate.return_msg`` contains response packet
|
||||
or ``None``.
|
||||
This packet will be send to a client that asked for it.
|
||||
|
||||
Complete source code
|
||||
@ -14,14 +16,16 @@ Complete source code
|
||||
:language: python
|
||||
|
||||
Testing
|
||||
------------------
|
||||
-------
|
||||
Run the unbound server:
|
||||
|
||||
``root@localhost>unbound -dv -c ./test-log.conf``
|
||||
|
||||
In case you use own configuration file, don't forget to enable python module: ``module-config: "validator python iterator"`` and use valid script path: ``python-script: "./examples/log.py"``.
|
||||
In case you use own configuration file, don't forget to enable python module:
|
||||
``module-config: "validator python iterator"`` and use valid script path:
|
||||
``python-script: "./examples/log.py"``.
|
||||
|
||||
Example of output::
|
||||
Example of output::
|
||||
|
||||
[1231790168] unbound[7941:0] info: response for <f.gtld-servers.NET. AAAA IN>
|
||||
[1231790168] unbound[7941:0] info: reply from <gtld-servers.NET.> 192.5.6.31#53
|
||||
|
@ -1,12 +1,14 @@
|
||||
Response generation
|
||||
=====================
|
||||
===================
|
||||
|
||||
This example shows how to handle queries and generate response packet.
|
||||
|
||||
.. note::
|
||||
If the python module is the first module and validator module is enabled (``module-config: "python validator iterator"``),
|
||||
a return_msg security flag has to be set at least to 2. Leaving security flag untouched causes that the
|
||||
response will be refused by unbound worker as unbound will consider it as non-valid response.
|
||||
If the python module is the first module and validator module is enabled
|
||||
(``module-config: "python validator iterator"``), a return_msg security flag
|
||||
has to be set at least to 2. Leaving security flag untouched causes that the
|
||||
response will be refused by unbound worker as unbound will consider it as
|
||||
non-valid response.
|
||||
|
||||
Complete source code
|
||||
--------------------
|
||||
@ -27,20 +29,21 @@ Query for a A record ending with .localdomain
|
||||
|
||||
Dig produces the following output::
|
||||
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48426
|
||||
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;test.xxx.localdomain. IN A
|
||||
|
||||
;; ANSWER SECTION:
|
||||
test.xxx.localdomain. 10 IN A 127.0.0.1
|
||||
|
||||
;; Query time: 2 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Jan 01 12:46:02 2009
|
||||
;; MSG SIZE rcvd: 54
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48426
|
||||
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
|
||||
|
||||
As we handle (override) in python module only queries ending with "localdomain.", the unboud can still resolve host names.
|
||||
;; QUESTION SECTION:
|
||||
;test.xxx.localdomain. IN A
|
||||
|
||||
;; ANSWER SECTION:
|
||||
test.xxx.localdomain. 10 IN A 127.0.0.1
|
||||
|
||||
;; Query time: 2 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Jan 01 12:46:02 2009
|
||||
;; MSG SIZE rcvd: 54
|
||||
|
||||
As we handle (override) in the python module only queries ending with
|
||||
``localdomain.``, unboud can still resolve host names.
|
||||
|
@ -1,15 +1,19 @@
|
||||
DNS-based language dictionary
|
||||
===============================
|
||||
=============================
|
||||
|
||||
This example shows how to create a simple language dictionary based on **DNS**
|
||||
service within 15 minutes. The translation will be performed using TXT resource records.
|
||||
service within 15 minutes. The translation will be performed using TXT resource
|
||||
records.
|
||||
|
||||
Key parts
|
||||
-----------
|
||||
---------
|
||||
|
||||
Initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
On **init()** module loads dictionary from a text file containing records in ``word [tab] translation`` format.
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
On **init()** module loads dictionary from a text file containing records in
|
||||
``word [tab] translation`` format.
|
||||
|
||||
::
|
||||
|
||||
def init(id, cfg):
|
||||
@ -20,11 +24,14 @@ On **init()** module loads dictionary from a text file containing records in ``w
|
||||
The suitable file can be found at http://slovnik.zcu.cz
|
||||
|
||||
DNS query and word lookup
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Let's define the following format od DNS queries: ``word1[.]word2[.] ... wordN[.]{en,cs}[._dict_.cz.]``.
|
||||
Let's define the following format od DNS queries:
|
||||
``word1[.]word2[.] ... wordN[.]{en,cs}[._dict_.cz.]``.
|
||||
Word lookup is done by simple ``dict`` lookup from broken DNS request.
|
||||
Query name is divided into a list of labels. This list is accessible as qname_list attribute.
|
||||
Query name is divided into a list of labels. This list is accessible as
|
||||
``qname_list`` attribute.
|
||||
|
||||
::
|
||||
|
||||
aword = ' '.join(qstate.qinfo.qname_list[0:-4]) #skip last four labels
|
||||
@ -37,35 +44,40 @@ Query name is divided into a list of labels. This list is accessible as qname_li
|
||||
if (adict == "cs") and (aword in cz_dict):
|
||||
words = cz_dict[aword] # CS -> EN
|
||||
|
||||
In the first step, we get a string in the form: ``word1[space]word2[space]...word[space]``.
|
||||
In the second assignment, fourth label from the end is obtained. This label should contains *"cs"* or *"en"*.
|
||||
This label determines the direction of translation.
|
||||
|
||||
In the first step, we get a string in the form:
|
||||
``word1[space]word2[space]...word[space]``.
|
||||
In the second assignment, fourth label from the end is obtained. This label
|
||||
should contains *"cs"* or *"en"*. This label determines the direction of
|
||||
translation.
|
||||
|
||||
Forming of a DNS reply
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
DNS reply is formed only on valid match and added as TXT answer.
|
||||
|
||||
::
|
||||
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_AA)
|
||||
msg = DNSMessage(qstate.qinfo.qname_str, RR_TYPE_TXT, RR_CLASS_IN, PKT_AA)
|
||||
|
||||
for w in words:
|
||||
msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str, w.replace("\"", "\\\"")))
|
||||
for w in words:
|
||||
msg.answer.append("%s 300 IN TXT \"%s\"" % (qstate.qinfo.qname_str, w.replace("\"", "\\\"")))
|
||||
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
if not msg.set_return_msg(qstate):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
||||
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
qstate.return_rcode = RCODE_NOERROR
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
In the first step, a :class:`DNSMessage` instance is created for a given query *(type TXT)*.
|
||||
In the first step, a :class:`DNSMessage` instance is created for a given query
|
||||
*(type TXT)*.
|
||||
The fourth argument specifies the flags *(authoritative answer)*.
|
||||
In the second step, we append TXT records containing the translation *(on the right side of RR)*.
|
||||
In the second step, we append TXT records containing the translation *(on the
|
||||
right side of RR)*.
|
||||
Then, the response is finished and ``qstate.return_msg`` contains new response.
|
||||
If no error, the module sets :attr:`module_qstate.return_rcode` and :attr:`module_qstate.ext_state`.
|
||||
If no error, the module sets :attr:`module_qstate.return_rcode` and
|
||||
:attr:`module_qstate.ext_state`.
|
||||
|
||||
**Steps:**
|
||||
|
||||
@ -82,80 +94,82 @@ Run the Unbound server:
|
||||
|
||||
In case you use own configuration file, don't forget to enable Python module::
|
||||
|
||||
module-config: "validator python iterator"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
and use valid script path::
|
||||
|
||||
python-script: "./examples/dict.py"
|
||||
python-script: "./examples/dict.py"
|
||||
|
||||
The translation from english word *"a bar fly"* to Czech can be done by doing:
|
||||
|
||||
``>>>dig TXT @127.0.0.1 a.bar.fly.en._dict_.cz``
|
||||
|
||||
::
|
||||
::
|
||||
|
||||
; (1 server found)
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48691
|
||||
;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;a.bar.fly.en._dict_.cz. IN TXT
|
||||
|
||||
;; ANSWER SECTION:
|
||||
a.bar.fly.en._dict_.cz. 300 IN TXT "barov\253 povale\232"
|
||||
|
||||
;; Query time: 5 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Jan 01 17:44:18 2009
|
||||
;; MSG SIZE rcvd: 67
|
||||
|
||||
; (1 server found)
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48691
|
||||
;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;a.bar.fly.en._dict_.cz. IN TXT
|
||||
|
||||
;; ANSWER SECTION:
|
||||
a.bar.fly.en._dict_.cz. 300 IN TXT "barov\253 povale\232"
|
||||
|
||||
;; Query time: 5 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Jan 01 17:44:18 2009
|
||||
;; MSG SIZE rcvd: 67
|
||||
|
||||
``>>>dig TXT @127.0.0.1 nic.cs._dict_.cz``
|
||||
|
||||
::
|
||||
|
||||
; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 nic.cs._dict_.cz
|
||||
; (1 server found)
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58710
|
||||
;; flags: aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;nic.cs._dict_.cz. IN TXT
|
||||
|
||||
;; ANSWER SECTION:
|
||||
nic.cs._dict_.cz. 300 IN TXT "aught"
|
||||
nic.cs._dict_.cz. 300 IN TXT "naught"
|
||||
nic.cs._dict_.cz. 300 IN TXT "nihil"
|
||||
nic.cs._dict_.cz. 300 IN TXT "nix"
|
||||
nic.cs._dict_.cz. 300 IN TXT "nothing"
|
||||
nic.cs._dict_.cz. 300 IN TXT "zilch"
|
||||
|
||||
;; Query time: 0 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Jan 01 17:45:39 2009
|
||||
;; MSG SIZE rcvd: 143
|
||||
; <<>> DiG 9.5.0-P2 <<>> TXT @127.0.0.1 nic.cs._dict_.cz
|
||||
; (1 server found)
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58710
|
||||
;; flags: aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
|
||||
|
||||
Proof that the unbound still works as resolver.
|
||||
;; QUESTION SECTION:
|
||||
;nic.cs._dict_.cz. IN TXT
|
||||
|
||||
;; ANSWER SECTION:
|
||||
nic.cs._dict_.cz. 300 IN TXT "aught"
|
||||
nic.cs._dict_.cz. 300 IN TXT "naught"
|
||||
nic.cs._dict_.cz. 300 IN TXT "nihil"
|
||||
nic.cs._dict_.cz. 300 IN TXT "nix"
|
||||
nic.cs._dict_.cz. 300 IN TXT "nothing"
|
||||
nic.cs._dict_.cz. 300 IN TXT "zilch"
|
||||
|
||||
;; Query time: 0 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Jan 01 17:45:39 2009
|
||||
;; MSG SIZE rcvd: 143
|
||||
|
||||
Proof that the unbound still works as resolver.
|
||||
|
||||
``>>>dig A @127.0.0.1 www.nic.cz``
|
||||
|
||||
::
|
||||
|
||||
; (1 server found)
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19996
|
||||
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;www.nic.cz. IN A
|
||||
|
||||
;; ANSWER SECTION:
|
||||
www.nic.cz. 1662 IN A 217.31.205.50
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
...
|
||||
; (1 server found)
|
||||
;; global options: printcmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19996
|
||||
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;www.nic.cz. IN A
|
||||
|
||||
;; ANSWER SECTION:
|
||||
www.nic.cz. 1662 IN A 217.31.205.50
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
...
|
||||
|
||||
Complete source code
|
||||
--------------------
|
||||
|
191
pythonmod/doc/examples/example5.rst
Normal file
191
pythonmod/doc/examples/example5.rst
Normal file
@ -0,0 +1,191 @@
|
||||
EDNS options
|
||||
============
|
||||
|
||||
This example shows how to interact with EDNS options.
|
||||
|
||||
When quering unbound with the EDNS option ``65001`` and data ``0xc001`` we
|
||||
expect an answer with the same EDNS option code and data ``0xdeadbeef``.
|
||||
|
||||
|
||||
Key parts
|
||||
~~~~~~~~~
|
||||
|
||||
This example relies on the following functionalities:
|
||||
|
||||
|
||||
Registering EDNS options
|
||||
------------------------
|
||||
|
||||
By registering EDNS options we can tune unbound's behavior when encountering a
|
||||
query with a known EDNS option. The two available options are:
|
||||
|
||||
- ``bypass_cache_stage``: If set to ``True`` unbound will not try to answer
|
||||
from cache. Instead execution is passed to the modules
|
||||
- ``no_aggregation``: If set to ``True`` unbound will consider this query
|
||||
unique and will not aggregate it with similar queries
|
||||
|
||||
Both values default to ``False``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_edns_option(env, 65001, bypass_cache_stage=True,
|
||||
no_aggregation=True):
|
||||
log_info("python: Could not register EDNS option {}".format(65001))
|
||||
|
||||
|
||||
EDNS option lists
|
||||
-----------------
|
||||
|
||||
EDNS option lists can be found in the :class:`module_qstate` class. There are
|
||||
four available lists in total:
|
||||
|
||||
- :class:`module_qstate.edns_opts_front_in`: options that came from the client
|
||||
side. **Should not** be changed
|
||||
- :class:`module_qstate.edns_opts_back_out`: options that will be sent to the
|
||||
server side. Can be populated by edns literate modules
|
||||
- :class:`module_qstate.edns_opts_back_in`: options that came from the server
|
||||
side. **Should not** be changed
|
||||
- :class:`module_qstate.edns_opts_front_out`: options that will be sent to the
|
||||
client side. Can be populated by edns literate modules
|
||||
|
||||
Each list element has the following members:
|
||||
|
||||
- ``code``: the EDNS option code;
|
||||
- ``data``: the EDNS option data.
|
||||
|
||||
|
||||
Reading an EDNS option list
|
||||
...........................
|
||||
|
||||
The lists' contents can be accessed in python by their ``_iter`` counterpart as
|
||||
an iterator:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_front_in):
|
||||
for o in qstate.edns_opts_front_in_iter:
|
||||
log_info("python: Code: {}, Data: '{}'".format(o.code,
|
||||
"".join('{:02x}'.format(x) for x in o.data)))
|
||||
|
||||
|
||||
Writing to an EDNS option list
|
||||
..............................
|
||||
|
||||
By appending to an EDNS option list we can add new EDNS options. The new
|
||||
element is going to be allocated in :class:`module_qstate.region`. The data
|
||||
**must** be represented with a python ``bytearray``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
b = bytearray.fromhex("deadbeef")
|
||||
if not edns_opt_list_append(qstate.edns_opts_front_out,
|
||||
o.code, b, qstate.region):
|
||||
log_info("python: Could not append EDNS option {}".format(o.code))
|
||||
|
||||
We can also remove an EDNS option code from an EDNS option list.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if not edns_opt_list_remove(edns_opt_list, code):
|
||||
log_info("python: Option code {} was not found in the "
|
||||
"list.".format(code))
|
||||
|
||||
.. note:: All occurences of the EDNS option code will be removed from the list:
|
||||
|
||||
|
||||
Controlling other modules' cache behavior
|
||||
-----------------------------------------
|
||||
|
||||
During the modules' operation, some modules may interact with the cache
|
||||
(e.g., iterator). This behavior can be controlled by using the following
|
||||
:class:`module_qstate` flags:
|
||||
|
||||
- :class:`module_qstate.no_cache_lookup`: Modules *operating after* this module
|
||||
will not lookup the cache for an answer
|
||||
- :class:`module_qstate.no_cache_store`: Modules *operating after* this module
|
||||
will not store the response in the cache
|
||||
|
||||
Both values default to ``0``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
# Detect if edns option code 56001 is present from the client side. If
|
||||
# so turn on the flags for cache management.
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_front_in):
|
||||
log_info("python: searching for edns option code 65001 during NEW "
|
||||
"or PASS event ")
|
||||
for o in qstate.edns_opts_front_in_iter:
|
||||
if o.code == 65001:
|
||||
log_info("python: found edns option code 65001")
|
||||
# Instruct other modules to not lookup for an
|
||||
# answer in the cache.
|
||||
qstate.no_cache_lookup = 1
|
||||
log_info("python: enabled no_cache_lookup")
|
||||
|
||||
# Instruct other modules to not store the answer in
|
||||
# the cache.
|
||||
qstate.no_cache_store = 1
|
||||
log_info("python: enabled no_cache_store")
|
||||
|
||||
|
||||
Testing
|
||||
~~~~~~~
|
||||
|
||||
Run the Unbound server: ::
|
||||
|
||||
root@localhost$ unbound -dv -c ./test-edns.conf
|
||||
|
||||
In case you use your own configuration file, don't forget to enable the Python
|
||||
module::
|
||||
|
||||
module-config: "validator python iterator"
|
||||
|
||||
and use a valid script path::
|
||||
|
||||
python-script: "./examples/edns.py"
|
||||
|
||||
Quering with EDNS option ``65001:0xc001``:
|
||||
|
||||
::
|
||||
|
||||
root@localhost$ dig @localhost nlnetlabs.nl +ednsopt=65001:c001
|
||||
|
||||
; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost nlnetlabs.nl +ednsopt=65001:c001
|
||||
; (1 server found)
|
||||
;; global options: +cmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33450
|
||||
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 3
|
||||
|
||||
;; OPT PSEUDOSECTION:
|
||||
; EDNS: version: 0, flags:; udp: 4096
|
||||
; OPT=65001: de ad be ef ("....")
|
||||
;; QUESTION SECTION:
|
||||
;nlnetlabs.nl. IN A
|
||||
|
||||
;; ANSWER SECTION:
|
||||
nlnetlabs.nl. 10200 IN A 185.49.140.10
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
nlnetlabs.nl. 10200 IN NS anyns.pch.net.
|
||||
nlnetlabs.nl. 10200 IN NS ns.nlnetlabs.nl.
|
||||
nlnetlabs.nl. 10200 IN NS ns-ext1.sidn.nl.
|
||||
nlnetlabs.nl. 10200 IN NS sec2.authdns.ripe.net.
|
||||
|
||||
;; ADDITIONAL SECTION:
|
||||
ns.nlnetlabs.nl. 10200 IN AAAA 2a04:b900::8:0:0:60
|
||||
ns.nlnetlabs.nl. 10200 IN A 185.49.140.60
|
||||
|
||||
;; Query time: 10 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Dec 05 14:50:56 CET 2016
|
||||
;; MSG SIZE rcvd: 212
|
||||
|
||||
|
||||
Complete source code
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. literalinclude:: ../../examples/edns.py
|
||||
:language: python
|
299
pythonmod/doc/examples/example6.rst
Normal file
299
pythonmod/doc/examples/example6.rst
Normal file
@ -0,0 +1,299 @@
|
||||
Inplace callbacks
|
||||
=================
|
||||
|
||||
This example shows how to register and use inplace callback functions. These
|
||||
functions are going to be called just before unbound replies back to a client.
|
||||
They can perform certain actions without interrupting unbound's execution flow
|
||||
(e.g. add/remove EDNS options, manipulate the reply).
|
||||
|
||||
Two different scenarios will be shown:
|
||||
|
||||
- If answering from cache and the client used EDNS option code ``65002`` we
|
||||
will answer with the same code but with data ``0xdeadbeef``;
|
||||
- When answering with a SERVFAIL we also add an empty EDNS option code
|
||||
``65003``.
|
||||
|
||||
|
||||
Key parts
|
||||
~~~~~~~~~
|
||||
|
||||
This example relies on the following functionalities:
|
||||
|
||||
|
||||
Registering inplace callback functions
|
||||
--------------------------------------
|
||||
|
||||
There are four types of inplace callback functions:
|
||||
|
||||
- `inplace callback reply functions`_
|
||||
- `inplace callback reply_cache functions`_
|
||||
- `inplace callback reply_local functions`_
|
||||
- `inplace callback reply_servfail functions`_
|
||||
|
||||
|
||||
Inplace callback reply functions
|
||||
................................
|
||||
|
||||
Called when answering with a *resolved* query.
|
||||
|
||||
The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with a resolved query.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. It contains the available opt_lists; It
|
||||
SHOULD NOT be altered;
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data to be sent to the client side. It SHOULD NOT be
|
||||
altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
|
||||
We can register such function as:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply(inplace_reply_callback, env):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
Inplace callback reply_cache functions
|
||||
......................................
|
||||
|
||||
Called when answering *from cache*.
|
||||
|
||||
The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from the cache.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the EDNS
|
||||
options is accesible through edns.opt_list. It SHOULD NOT be
|
||||
altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
|
||||
We can register such function as:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply_cache(inplace_cache_callback, env):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
Inplace callback reply_local functions
|
||||
......................................
|
||||
|
||||
Called when answering with *local data* or a *Chaos(CH) reply*.
|
||||
|
||||
The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from local data.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the
|
||||
EDNS options is accesible through edns.opt_list. It
|
||||
SHOULD NOT be altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
|
||||
We can register such function as:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply_local(inplace_local_callback, env):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
Inplace callback reply_servfail functions
|
||||
.........................................
|
||||
|
||||
Called when answering with *SERVFAIL*.
|
||||
|
||||
The callback function's prototype is the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out, region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with SERVFAIL.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. If not None the relevant opt_lists are
|
||||
available here;
|
||||
:param rep: reply_info struct. None;
|
||||
:param rcode: return code for the query. LDNS_RCODE_SERVFAIL;
|
||||
:param edns: edns_data to be sent to the client side. If qstate is None
|
||||
edns.opt_list contains the EDNS options sent from the client
|
||||
side. It SHOULD NOT be altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
"""
|
||||
|
||||
.. note:: The function's name is irrelevant.
|
||||
|
||||
We can register such function as:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply_servfail(inplace_servfail_callback, env):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
Testing
|
||||
~~~~~~~
|
||||
|
||||
Run the Unbound server: ::
|
||||
|
||||
root@localhost$ unbound -dv -c ./test-inplace_callbacks.conf
|
||||
|
||||
In case you use your own configuration file, don't forget to enable the Python
|
||||
module::
|
||||
|
||||
module-config: "validator python iterator"
|
||||
|
||||
and use a valid script path ::
|
||||
|
||||
python-script: "./examples/inplace_callbacks.py"
|
||||
|
||||
On the first query for the nlnetlabs.nl A record we get no EDNS option back:
|
||||
|
||||
::
|
||||
|
||||
root@localhost$ dig @localhost nlnetlabs.nl +ednsopt=65002
|
||||
|
||||
; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost nlnetlabs.nl +ednsopt=65002
|
||||
; (1 server found)
|
||||
;; global options: +cmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48057
|
||||
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 3
|
||||
|
||||
;; OPT PSEUDOSECTION:
|
||||
; EDNS: version: 0, flags:; udp: 4096
|
||||
;; QUESTION SECTION:
|
||||
;nlnetlabs.nl. IN A
|
||||
|
||||
;; ANSWER SECTION:
|
||||
nlnetlabs.nl. 10200 IN A 185.49.140.10
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
nlnetlabs.nl. 10200 IN NS ns.nlnetlabs.nl.
|
||||
nlnetlabs.nl. 10200 IN NS sec2.authdns.ripe.net.
|
||||
nlnetlabs.nl. 10200 IN NS anyns.pch.net.
|
||||
nlnetlabs.nl. 10200 IN NS ns-ext1.sidn.nl.
|
||||
|
||||
;; ADDITIONAL SECTION:
|
||||
ns.nlnetlabs.nl. 10200 IN A 185.49.140.60
|
||||
ns.nlnetlabs.nl. 10200 IN AAAA 2a04:b900::8:0:0:60
|
||||
|
||||
;; Query time: 813 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Dec 05 16:15:32 CET 2016
|
||||
;; MSG SIZE rcvd: 204
|
||||
|
||||
When we issue the same query again we get a cached response and the expected
|
||||
``65002: 0xdeadbeef`` EDNS option:
|
||||
|
||||
::
|
||||
|
||||
root@localhost$ dig @localhost nlnetlabs.nl +ednsopt=65002
|
||||
|
||||
; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost nlnetlabs.nl +ednsopt=65002
|
||||
; (1 server found)
|
||||
;; global options: +cmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26489
|
||||
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 3
|
||||
|
||||
;; OPT PSEUDOSECTION:
|
||||
; EDNS: version: 0, flags:; udp: 4096
|
||||
; OPT=65002: de ad be ef ("....")
|
||||
;; QUESTION SECTION:
|
||||
;nlnetlabs.nl. IN A
|
||||
|
||||
;; ANSWER SECTION:
|
||||
nlnetlabs.nl. 10197 IN A 185.49.140.10
|
||||
|
||||
;; AUTHORITY SECTION:
|
||||
nlnetlabs.nl. 10197 IN NS ns.nlnetlabs.nl.
|
||||
nlnetlabs.nl. 10197 IN NS sec2.authdns.ripe.net.
|
||||
nlnetlabs.nl. 10197 IN NS anyns.pch.net.
|
||||
nlnetlabs.nl. 10197 IN NS ns-ext1.sidn.nl.
|
||||
|
||||
;; ADDITIONAL SECTION:
|
||||
ns.nlnetlabs.nl. 10197 IN AAAA 2a04:b900::8:0:0:60
|
||||
ns.nlnetlabs.nl. 10197 IN A 185.49.140.60
|
||||
|
||||
;; Query time: 0 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Dec 05 16:50:04 CET 2016
|
||||
;; MSG SIZE rcvd: 212
|
||||
|
||||
By issuing a query for a bogus domain unbound replies with SERVFAIL and an
|
||||
empty EDNS option code ``65003``. *For this example to work unbound needs to be
|
||||
validating*:
|
||||
|
||||
::
|
||||
|
||||
root@localhost$ dig @localhost bogus.nlnetlabs.nl txt
|
||||
|
||||
; <<>> DiG 9.10.3-P4-Ubuntu <<>> @localhost bogus.nlnetlabs.nl txt
|
||||
; (1 server found)
|
||||
;; global options: +cmd
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 19865
|
||||
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
|
||||
|
||||
;; OPT PSEUDOSECTION:
|
||||
; EDNS: version: 0, flags:; udp: 4096
|
||||
; OPT=65003
|
||||
;; QUESTION SECTION:
|
||||
;bogus.nlnetlabs.nl. IN TXT
|
||||
|
||||
;; Query time: 11 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Mon Dec 05 17:06:01 CET 2016
|
||||
;; MSG SIZE rcvd: 51
|
||||
|
||||
|
||||
Complete source code
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
.. literalinclude:: ../../examples/inplace_callbacks.py
|
||||
:language: python
|
@ -1,15 +1,16 @@
|
||||
.. _Tutorials:
|
||||
|
||||
==============================
|
||||
Examples
|
||||
========
|
||||
|
||||
Here you can find several tutorials which clarify the usage and capabilities of
|
||||
the Unbound scriptable interface.
|
||||
|
||||
Tutorials
|
||||
==============================
|
||||
|
||||
Here you can find several tutorials which clarify the usage and capabilities of Unbound scriptable interface.
|
||||
|
||||
`Tutorials`
|
||||
---------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:glob:
|
||||
:maxdepth: 2
|
||||
:glob:
|
||||
|
||||
example*
|
||||
example*
|
||||
|
@ -1,39 +1,44 @@
|
||||
Installation
|
||||
===================================
|
||||
============
|
||||
|
||||
**Prerequisites**
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Python 2.4 or higher, SWIG 1.3 or higher, GNU make
|
||||
|
||||
**Download**
|
||||
Download
|
||||
--------
|
||||
|
||||
You can download the source codes `here`_.
|
||||
The latest release is 1.1.1, Jan 15, 2009.
|
||||
|
||||
.. _here: unbound-1.1.1-py.tar.gz
|
||||
|
||||
**Compiling**
|
||||
Compiling
|
||||
---------
|
||||
|
||||
After downloading, you can compile the Unbound library by doing::
|
||||
|
||||
> tar -xzf unbound-1.1.1-py.tar.gz
|
||||
> cd unbound-1.1.1
|
||||
> ./configure --with-pythonmodule
|
||||
> make
|
||||
> tar -xzf unbound-1.1.1-py.tar.gz
|
||||
> cd unbound-1.1.1
|
||||
> ./configure --with-pythonmodule
|
||||
> make
|
||||
|
||||
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 extension module by::
|
||||
|
||||
> cd pythonmod
|
||||
> make sudo # or "make test" or "make suexec"
|
||||
> cd pythonmod
|
||||
> make sudo # or "make test" or "make suexec"
|
||||
|
||||
This will start unbound server with language dictionary service (see :ref:`Tutorials`).
|
||||
This will start unbound server with language dictionary service
|
||||
(see :ref:`Tutorials`).
|
||||
In order to test this service, type::
|
||||
|
||||
|
||||
> dig TXT @127.0.0.1 aught.en._dict_.cz
|
||||
|
||||
Dig should print this message (czech equivalent of aught)::
|
||||
@ -44,16 +49,17 @@ Dig should print this message (czech equivalent of aught)::
|
||||
;; Got answer:
|
||||
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30085
|
||||
;; flags: aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
|
||||
|
||||
|
||||
;; QUESTION SECTION:
|
||||
;aught.en._dict_.cz. IN TXT
|
||||
|
||||
;aught.en._dict_.cz. IN TXT
|
||||
|
||||
;; ANSWER SECTION:
|
||||
aught.en._dict_.cz. 300 IN TXT "nic"
|
||||
|
||||
aught.en._dict_.cz. 300 IN TXT "nic"
|
||||
|
||||
;; Query time: 11 msec
|
||||
;; SERVER: 127.0.0.1#53(127.0.0.1)
|
||||
;; WHEN: Thu Jan 10 16:45:58 2009
|
||||
;; MSG SIZE rcvd: 52
|
||||
|
||||
The ``pythonmod/examples`` directory contains simple applications written in Python.
|
||||
The ``pythonmod/examples`` directory contains simple applications written in
|
||||
Python.
|
||||
|
@ -7,25 +7,26 @@ Network
|
||||
.. function:: ntohs(netshort)
|
||||
|
||||
This subroutine converts values between the host and network byte order.
|
||||
Specifically, **ntohs()** converts 16-bit quantities from network byte order to host byte order.
|
||||
|
||||
Specifically, **ntohs()** converts 16-bit quantities from network byte order
|
||||
to host byte order.
|
||||
|
||||
:param netshort: 16-bit short addr
|
||||
:rtype: converted addr
|
||||
|
||||
|
||||
|
||||
|
||||
Cache
|
||||
-----
|
||||
|
||||
.. function:: storeQueryInCache(qstate, qinfo, msgrep, is_referral)
|
||||
|
||||
Store pending query in local cache.
|
||||
|
||||
|
||||
:param qstate: :class:`module_qstate`
|
||||
:param qinfo: :class:`query_info`
|
||||
:param msgrep: :class:`reply_info`
|
||||
:param is_referal: integer
|
||||
:rtype: boolean
|
||||
|
||||
|
||||
.. function:: invalidateQueryInCache(qstate, qinfo)
|
||||
|
||||
Invalidate record in local cache.
|
||||
@ -34,6 +35,111 @@ Cache
|
||||
:param qinfo: :class:`query_info`
|
||||
|
||||
|
||||
EDNS options
|
||||
------------
|
||||
|
||||
.. function:: register_edns_option(env, code, bypass_cache_stage=False, no_aggregation=False)
|
||||
|
||||
Register EDNS option code.
|
||||
|
||||
:param env: :class:`module_env`
|
||||
:param code: option code(integer)
|
||||
:param bypass_cache_stage: whether to bypass the cache response stage
|
||||
:param no_aggregation: whether this query should be unique
|
||||
:return: ``1`` if successful, ``0`` otherwise
|
||||
:rtype: integer
|
||||
|
||||
.. function:: edns_opt_list_find(list, code)
|
||||
|
||||
Find the EDNS option code in the EDNS option list.
|
||||
|
||||
:param list: linked list of :class:`edns_option`
|
||||
:param code: option code (integer)
|
||||
:return: the edns option if found or None
|
||||
:rtype: :class:`edns_option` or None
|
||||
|
||||
.. function:: edns_opt_list_remove(list, code);
|
||||
|
||||
Remove an ENDS option code from the list.
|
||||
.. note:: All :class:`edns_option` with the code will be removed
|
||||
|
||||
:param list: linked list of :class:`edns_option`
|
||||
:param code: option code (integer)
|
||||
:return: ``1`` if at least one :class:`edns_option` was removed, ``0`` otherwise
|
||||
:rtype: integer
|
||||
|
||||
.. function:: edns_opt_list_append(list, code, data, region)
|
||||
|
||||
Append given EDNS option code with data to the list.
|
||||
|
||||
:param list: linked list of :class:`edns_option`
|
||||
:param code: option code (integer)
|
||||
:param data: EDNS data. **Must** be a :class:`bytearray`
|
||||
:param region: :class:`regional`
|
||||
|
||||
.. function:: edns_opt_list_is_empty(list)
|
||||
|
||||
Check if an EDNS option list is empty.
|
||||
|
||||
:param list: linked list of :class:`edns_option`
|
||||
:return: ``1`` if list is empty, ``0`` otherwise
|
||||
:rtype: integer
|
||||
|
||||
|
||||
Inplace callbacks
|
||||
-----------------
|
||||
|
||||
.. function:: inplace_cb_reply(qinfo, qstate, rep, rcode, edns, opt_list_out, region)
|
||||
|
||||
Function prototype for callback functions used in
|
||||
`register_inplace_cb_reply`_, `register_inplace_cb_reply_cache`_,
|
||||
`register_inplace_cb_reply_local` and `register_inplace_cb_reply_servfail`.
|
||||
|
||||
:param qinfo: :class:`query_info`
|
||||
:param qstate: :class:`module_qstate`
|
||||
:param rep: :class:`reply_info`
|
||||
:param rcode: return code (integer), check ``RCODE_`` constants.
|
||||
:param edns: :class:`edns_data`
|
||||
:param opt_list_out: :class:`edns_option`. EDNS option list to append options to.
|
||||
:param region: :class:`regional`
|
||||
|
||||
.. function:: register_inplace_cb_reply(py_cb, env)
|
||||
|
||||
Register py_cb as an inplace reply callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: register_inplace_cb_reply_cache(py_cb, env)
|
||||
|
||||
Register py_cb as an inplace reply_cache callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: register_inplace_cb_reply_local(py_cb, env)
|
||||
|
||||
Register py_cb as an inplace reply_local callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
.. function:: register_inplace_cb_reply_servfail(py_cb, env)
|
||||
|
||||
Register py_cb as an inplace reply_servfail callback function.
|
||||
|
||||
:param py_cb: Python function that follows `inplace_cb_reply`_'s prototype. **Must** be callable.
|
||||
:param env: :class:`module_env`
|
||||
:return: True on success, False otherwise
|
||||
:rtype: boolean
|
||||
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
@ -71,50 +177,51 @@ Logging
|
||||
:param msg: string desc to accompany the hexdump.
|
||||
:param data: data to dump in hex format.
|
||||
:param length: length of data.
|
||||
|
||||
|
||||
.. function:: log_dns_msg(str, qinfo, reply)
|
||||
|
||||
Log DNS message.
|
||||
|
||||
|
||||
:param str: string message
|
||||
:param qinfo: :class:`query_info`
|
||||
:param reply: :class:`reply_info`
|
||||
|
||||
|
||||
.. function:: log_query_info(verbosity_value, str, qinf)
|
||||
|
||||
Log query information.
|
||||
|
||||
|
||||
:param verbosity_value: see constants
|
||||
:param str: string message
|
||||
:param qinf: :class:`query_info`
|
||||
|
||||
|
||||
.. function:: regional_log_stats(r)
|
||||
|
||||
Log regional statistics.
|
||||
|
||||
|
||||
:param r: :class:`regional`
|
||||
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
.. function:: strextstate(module_ext_state)
|
||||
|
||||
Debug utility, module external qstate to string.
|
||||
|
||||
|
||||
:param module_ext_state: the state value.
|
||||
:rtype: descriptive string.
|
||||
|
||||
.. function:: strmodulevent(module_event)
|
||||
|
||||
Debug utility, module event to string.
|
||||
|
||||
|
||||
:param module_event: the module event value.
|
||||
:rtype: descriptive string.
|
||||
|
||||
|
||||
.. function:: ldns_rr_type2str(atype)
|
||||
|
||||
Convert RR type to string.
|
||||
|
||||
|
||||
.. function:: ldns_rr_class2str(aclass)
|
||||
|
||||
Convert RR class to string.
|
||||
|
@ -6,55 +6,94 @@ module_qstate
|
||||
|
||||
.. class:: module_qstate
|
||||
|
||||
Module state, per query.
|
||||
|
||||
This class provides these data attributes:
|
||||
|
||||
.. attribute:: qinfo
|
||||
|
||||
(:class:`query_info`) Informations about query being answered. Name, RR type, RR class.
|
||||
|
||||
.. attribute:: query_flags
|
||||
|
||||
(uint16) Flags for query. See QF_BIT\_ predefined constants.
|
||||
|
||||
.. attribute:: is_priming
|
||||
|
||||
If this is a (stub or root) priming query (with hints).
|
||||
|
||||
.. attribute:: reply
|
||||
|
||||
comm_reply contains server replies.
|
||||
|
||||
.. attribute:: return_msg
|
||||
|
||||
(:class:`dns_msg`) The reply message, with message for client and calling module (read-only attribute).
|
||||
Note that if you want to create of modify return_msg you should use :class:`DNSMessage`.
|
||||
|
||||
.. attribute:: return_rcode
|
||||
|
||||
The rcode, in case of error, instead of a reply message. Determines whether the return_msg contains reply.
|
||||
|
||||
.. attribute:: region
|
||||
|
||||
Region for this query. Cleared when query process finishes.
|
||||
|
||||
.. attribute:: curmod
|
||||
|
||||
Which module is executing.
|
||||
|
||||
.. attribute:: ext_state[]
|
||||
|
||||
Module states.
|
||||
|
||||
.. attribute:: env
|
||||
|
||||
Environment for this query.
|
||||
|
||||
.. attribute:: mesh_info
|
||||
|
||||
Mesh related information for this query.
|
||||
Module state, per query.
|
||||
|
||||
This class provides these data attributes:
|
||||
|
||||
.. attribute:: qinfo
|
||||
|
||||
(:class:`query_info`) Informations about query being answered. Name, RR type, RR class.
|
||||
|
||||
.. attribute:: query_flags
|
||||
|
||||
(uint16) Flags for query. See QF_BIT\_ predefined constants.
|
||||
|
||||
.. attribute:: is_priming
|
||||
|
||||
If this is a (stub or root) priming query (with hints).
|
||||
|
||||
.. attribute:: reply
|
||||
|
||||
comm_reply contains server replies.
|
||||
|
||||
.. attribute:: return_msg
|
||||
|
||||
(:class:`dns_msg`) The reply message, with message for client and calling module (read-only attribute).
|
||||
Note that if you want to create of modify return_msg you should use :class:`DNSMessage`.
|
||||
|
||||
.. attribute:: return_rcode
|
||||
|
||||
The rcode, in case of error, instead of a reply message. Determines whether the return_msg contains reply.
|
||||
|
||||
.. attribute:: region
|
||||
|
||||
Region for this query. Cleared when query process finishes.
|
||||
|
||||
.. attribute:: curmod
|
||||
|
||||
Which module is executing.
|
||||
|
||||
.. attribute:: ext_state[]
|
||||
|
||||
Module states.
|
||||
|
||||
.. attribute:: env
|
||||
|
||||
Environment for this query.
|
||||
|
||||
.. attribute:: mesh_info
|
||||
|
||||
Mesh related information for this query.
|
||||
|
||||
.. attribute:: edns_opts_front_in
|
||||
|
||||
Incoming EDNS options from the front end.
|
||||
|
||||
.. attribute:: edns_opts_front_in_iter
|
||||
|
||||
Iterator for `edns_opts_front_in`.
|
||||
|
||||
.. attribute:: edns_opts_back_out
|
||||
|
||||
Outgoing EDNS options to the back end.
|
||||
|
||||
.. attribute:: edns_opts_back_out_iter
|
||||
|
||||
Iterator for `edns_opts_back_out`.
|
||||
|
||||
.. attribute:: edns_opts_back_in
|
||||
|
||||
Incoming EDNS options from the back end.
|
||||
|
||||
.. attribute:: edns_opts_back_in_iter
|
||||
|
||||
Iterator for `ends_opts_back_in`.
|
||||
|
||||
.. attribute:: edns_opts_front_out
|
||||
|
||||
Outgoing EDNS options to the front end.
|
||||
|
||||
.. attribute:: edns_opts_front_out_iter
|
||||
|
||||
Iterator for `edns_opts_front_out`.
|
||||
|
||||
.. attribute:: no_cache_lookup
|
||||
|
||||
Flag to indicate whether modules should answer from the cache.
|
||||
|
||||
.. attribute:: no_cache_store
|
||||
|
||||
Flag to indicate whether modules should store answer in the cache.
|
||||
|
||||
query_info
|
||||
----------------
|
||||
@ -94,7 +133,57 @@ query_info
|
||||
.. attribute:: qclass_str
|
||||
|
||||
The ``qclass`` in display presentation format (string).
|
||||
|
||||
|
||||
edns_data
|
||||
---------
|
||||
|
||||
.. class:: edns_data
|
||||
|
||||
This class represents the EDNS information parsed/encoded from/to a packet. It provides these data attributes:
|
||||
|
||||
.. attribute:: edns_present
|
||||
|
||||
If EDNS OPT record is present.
|
||||
|
||||
.. attribute:: ext_rcode
|
||||
|
||||
Extended RCODE.
|
||||
|
||||
.. attribute:: edns_version
|
||||
|
||||
The EDNS version number.
|
||||
|
||||
.. attribute:: bits
|
||||
|
||||
The EDNS bits field from ttl (host order): Z.
|
||||
|
||||
.. attribute:: udp_size
|
||||
|
||||
UDP reassembly size.
|
||||
|
||||
.. attribute:: opt_list
|
||||
|
||||
The EDNS option list.
|
||||
|
||||
.. attribute:: opt_list_iter
|
||||
|
||||
Iterator for `opt_list`.
|
||||
|
||||
edns_option
|
||||
-----------
|
||||
|
||||
.. class:: edns_option
|
||||
|
||||
This class represents an EDNS option (code, data) found in EDNS option lists. It provides these data attributes:
|
||||
|
||||
.. attribute:: code
|
||||
|
||||
The EDNS option code.
|
||||
|
||||
.. attribute:: data
|
||||
|
||||
The EDNS option data.
|
||||
|
||||
reply_info
|
||||
--------------------
|
||||
|
||||
|
194
pythonmod/examples/edns.py
Normal file
194
pythonmod/examples/edns.py
Normal file
@ -0,0 +1,194 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
edns.py: python module showcasing EDNS option functionality.
|
||||
|
||||
Copyright (c) 2016, NLnet Labs.
|
||||
|
||||
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 organization 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 REGENTS 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.
|
||||
'''
|
||||
#Try:
|
||||
# - dig @localhost nlnetlabs.nl +ednsopt=65001:c001
|
||||
# This query will always reach the modules stage as EDNS option 65001 is
|
||||
# registered to bypass the cache response stage. It will also be handled
|
||||
# as a unique query because of the no_aggregation flag. This means that
|
||||
# it will not be aggregated with other queries for the same qinfo.
|
||||
# For demonstration purposes when option 65001 with hexdata 'c001' is
|
||||
# sent from the client side this module will reply with the same code and
|
||||
# data 'deadbeef'.
|
||||
|
||||
# Useful functions:
|
||||
# edns_opt_list_is_empty(edns_opt_list):
|
||||
# Check if the option list is empty.
|
||||
# Return True if empty, False otherwise.
|
||||
#
|
||||
# edns_opt_list_append(edns_opt_list, code, data_bytearray, region):
|
||||
# Append the EDNS option with code and data_bytearray to the given
|
||||
# edns_opt_list.
|
||||
# NOTE: data_bytearray MUST be a Python bytearray.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# edns_opt_list_remove(edns_opt_list, code):
|
||||
# Remove all occurences of the given EDNS option code from the
|
||||
# edns_opt_list.
|
||||
# Return True when at least one EDNS option was removed, False otherwise.
|
||||
#
|
||||
# register_edns_option(env, code, bypass_cache_stage=True,
|
||||
# no_aggregation=True):
|
||||
# Register EDNS option code as a known EDNS option.
|
||||
# bypass_cache_stage:
|
||||
# bypasses answering from cache and allows the query to reach the
|
||||
# modules for further EDNS handling.
|
||||
# no_aggregation:
|
||||
# makes every query with the said EDNS option code unique.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# Examples on how to use the functions are given in this file.
|
||||
|
||||
|
||||
def init_standard(id, env):
|
||||
"""New version of the init function.
|
||||
The function's signature is the same as the C counterpart and allows for
|
||||
extra functionality during init.
|
||||
..note:: This function is preferred by unbound over the old init function.
|
||||
..note:: The previously accesible configuration options can now be found in
|
||||
env.cgf.
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
|
||||
# Register EDNS option 65001 as a known EDNS option.
|
||||
if not register_edns_option(env, 65001, bypass_cache_stage=True,
|
||||
no_aggregation=True):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def init(id, cfg):
|
||||
"""Previous version init function.
|
||||
..note:: This function is still supported for backwards compatibility when
|
||||
the init_standard function is missing. When init_standard is
|
||||
present this function SHOULD be ommited to avoid confusion to the
|
||||
reader.
|
||||
"""
|
||||
return True
|
||||
|
||||
|
||||
def deinit(id): return True
|
||||
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
# Detect if EDNS option code 56001 is present from the client side. If
|
||||
# so turn on the flags for cache management.
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_front_in):
|
||||
log_info("python: searching for EDNS option code 65001 during NEW "
|
||||
"or PASS event ")
|
||||
for o in qstate.edns_opts_front_in_iter:
|
||||
if o.code == 65001:
|
||||
log_info("python: found EDNS option code 65001")
|
||||
# Instruct other modules to not lookup for an
|
||||
# answer in the cache.
|
||||
qstate.no_cache_lookup = 1
|
||||
log_info("python: enabled no_cache_lookup")
|
||||
|
||||
# Instruct other modules to not store the answer in
|
||||
# the cache.
|
||||
qstate.no_cache_store = 1
|
||||
log_info("python: enabled no_cache_store")
|
||||
|
||||
#Pass on the query
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
elif event == MODULE_EVENT_MODDONE:
|
||||
# If the client sent EDNS option code 65001 and data 'c001' reply
|
||||
# with the same code and data 'deadbeef'.
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_front_in):
|
||||
log_info("python: searching for EDNS option code 65001 during "
|
||||
"MODDONE")
|
||||
for o in qstate.edns_opts_front_in_iter:
|
||||
if o.code == 65001 and o.data == bytearray.fromhex("c001"):
|
||||
b = bytearray.fromhex("deadbeef")
|
||||
if not edns_opt_list_append(qstate.edns_opts_front_out,
|
||||
o.code, b, qstate.region):
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return False
|
||||
|
||||
# List every EDNS option in all lists.
|
||||
# The available lists are:
|
||||
# - qstate.edns_opts_front_in: EDNS options that came from the
|
||||
# client side. SHOULD NOT be changed;
|
||||
#
|
||||
# - qstate.edns_opts_back_out: EDNS options that will be sent to the
|
||||
# server side. Can be populated by
|
||||
# EDNS literate modules;
|
||||
#
|
||||
# - qstate.edns_opts_back_in: EDNS options that came from the
|
||||
# server side. SHOULD NOT be changed;
|
||||
#
|
||||
# - qstate.edns_opts_front_out: EDNS options that will be sent to the
|
||||
# client side. Can be populated by
|
||||
# EDNS literate modules;
|
||||
#
|
||||
# The lists' contents can be accessed in python by their _iter
|
||||
# counterpart as an iterator.
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_front_in):
|
||||
log_info("python: EDNS options in edns_opts_front_in:")
|
||||
for o in qstate.edns_opts_front_in_iter:
|
||||
log_info("python: Code: {}, Data: '{}'".format(o.code,
|
||||
"".join('{:02x}'.format(x) for x in o.data)))
|
||||
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_back_out):
|
||||
log_info("python: EDNS options in edns_opts_back_out:")
|
||||
for o in qstate.edns_opts_back_out_iter:
|
||||
log_info("python: Code: {}, Data: '{}'".format(o.code,
|
||||
"".join('{:02x}'.format(x) for x in o.data)))
|
||||
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_back_in):
|
||||
log_info("python: EDNS options in edns_opts_back_in:")
|
||||
for o in qstate.edns_opts_back_in_iter:
|
||||
log_info("python: Code: {}, Data: '{}'".format(o.code,
|
||||
"".join('{:02x}'.format(x) for x in o.data)))
|
||||
|
||||
if not edns_opt_list_is_empty(qstate.edns_opts_front_out):
|
||||
log_info("python: EDNS options in edns_opts_front_out:")
|
||||
for o in qstate.edns_opts_front_out_iter:
|
||||
log_info("python: Code: {}, Data: '{}'".format(o.code,
|
||||
"".join('{:02x}'.format(x) for x in o.data)))
|
||||
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: Unknown event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
244
pythonmod/examples/inplace_callbacks.py
Normal file
244
pythonmod/examples/inplace_callbacks.py
Normal file
@ -0,0 +1,244 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
inplace_callbacks.py: python module showcasing inplace callback function
|
||||
registration and functionality.
|
||||
|
||||
Copyright (c) 2016, NLnet Labs.
|
||||
|
||||
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 organization 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 REGENTS 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.
|
||||
'''
|
||||
#Try:
|
||||
# - dig @localhost nlnetlabs.nl +ednsopt=65002:
|
||||
# This query *could* be answered from cache. If so, unbound will reply
|
||||
# with the same EDNS option 65002, but with hexdata 'deadbeef' as data.
|
||||
#
|
||||
# - dig @localhost bogus.nlnetlabs.nl txt:
|
||||
# This query returns SERVFAIL as the txt record of bogus.nlnetlabs.nl is
|
||||
# intentionally bogus. The reply will contain an empty EDNS option
|
||||
# with option code 65003.
|
||||
# (unbound needs to be validating for this example to work)
|
||||
|
||||
# Useful functions:
|
||||
# register_inplace_cb_reply(inplace_reply_callback, env):
|
||||
# Register the reply_callback function as an inplace callback function
|
||||
# when answering with a resolved query.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# register_inplace_cb_reply_cache(inplace_reply_cache_callback, env):
|
||||
# Register the reply_cache_callback function as an inplace callback
|
||||
# function when answering from cache.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# register_inplace_cb_reply_local(inplace_reply_local_callback, env):
|
||||
# Register the reply_local_callback function as an inplace callback
|
||||
# function when answering from local data or chaos reply.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# register_inplace_cb_reply_servfail(inplace_reply_servfail_callback, env):
|
||||
# Register the reply_servfail_callback function as an inplace callback
|
||||
# function when answering with servfail.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# Examples on how to use the functions are given in this file.
|
||||
|
||||
|
||||
def inplace_reply_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with a resolved query.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. It contains the available opt_lists; It
|
||||
SHOULD NOT be altered;
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data to be sent to the client side. It SHOULD NOT be
|
||||
altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
"""
|
||||
log_info("python: called back while replying.")
|
||||
return True
|
||||
|
||||
|
||||
def inplace_cache_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from the cache.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the EDNS
|
||||
options is accesible through edns.opt_list. It SHOULD NOT be
|
||||
altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demostration purposes we want to see if EDNS option 65002 is present
|
||||
and reply with a new value.
|
||||
"""
|
||||
log_info("python: called back while answering from cache.")
|
||||
# Inspect the incoming EDNS options.
|
||||
if not edns_opt_list_is_empty(edns.opt_list):
|
||||
log_info("python: available EDNS options:")
|
||||
for o in edns.opt_list_iter:
|
||||
log_info("python: Code: {}, Data: '{}'".format(o.code,
|
||||
"".join('{:02x}'.format(x) for x in o.data)))
|
||||
if o.code == 65002:
|
||||
log_info("python: *found option code 65002*")
|
||||
|
||||
# add to opt_list
|
||||
# Data MUST be represented in a bytearray.
|
||||
b = bytearray.fromhex("deadbeef")
|
||||
if edns_opt_list_append(opt_list_out, o.code, b, region):
|
||||
log_info("python: *added new option code 65002*")
|
||||
else:
|
||||
log_info("python: *failed to add new option code 65002*")
|
||||
return False
|
||||
break
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def inplace_local_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering from local data.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. None;
|
||||
:param rep: reply_info struct;
|
||||
:param rcode: return code for the query;
|
||||
:param edns: edns_data sent from the client side. The list with the
|
||||
EDNS options is accesible through edns.opt_list. It
|
||||
SHOULD NOT be altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
"""
|
||||
log_info("python: called back while replying with local data or chaos"
|
||||
" reply.")
|
||||
return True
|
||||
|
||||
|
||||
def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
region):
|
||||
"""Function that will be registered as an inplace callback function.
|
||||
It will be called when answering with SERVFAIL.
|
||||
:param qinfo: query_info struct;
|
||||
:param qstate: module qstate. If not None the relevant opt_lists are
|
||||
available here;
|
||||
:param rep: reply_info struct. None;
|
||||
:param rcode: return code for the query. LDNS_RCODE_SERVFAIL;
|
||||
:param edns: edns_data to be sent to the client side. If qstate is None
|
||||
edns.opt_list contains the EDNS options sent from the client
|
||||
side. It SHOULD NOT be altered;
|
||||
:param opt_list_out: the list with the EDNS options that will be sent as a
|
||||
reply. It can be populated with EDNS options;
|
||||
:param region: region to allocate temporary data. Needs to be used when we
|
||||
want to append a new option to opt_list_out.
|
||||
:return: True on success, False on failure.
|
||||
|
||||
For demostration purposes we want to reply with an empty EDNS code '65003'.
|
||||
"""
|
||||
log_info("python: called back while servfail.")
|
||||
b = bytearray.fromhex("")
|
||||
edns_opt_list_append(opt_list_out, 65003, b, region)
|
||||
return True
|
||||
|
||||
|
||||
def init_standard(id, env):
|
||||
"""New version of the init function.
|
||||
The function's signature is the same as the C counterpart and allows for
|
||||
extra functionality during init.
|
||||
..note:: This function is preferred by unbound over the old init function.
|
||||
..note:: The previously accesible configuration options can now be found in
|
||||
env.cgf.
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
|
||||
# Register the inplace_reply_callback function as an inplace callback
|
||||
# function when answering a resolved query.
|
||||
if not register_inplace_cb_reply(inplace_reply_callback, env):
|
||||
return False
|
||||
|
||||
# Register the inplace_cache_callback function as an inplace callback
|
||||
# function when answering from cache.
|
||||
if not register_inplace_cb_reply_cache(inplace_cache_callback, env):
|
||||
return False
|
||||
|
||||
# Register the inplace_local_callback function as an inplace callback
|
||||
# function when answering from local data.
|
||||
if not register_inplace_cb_reply_local(inplace_local_callback, env):
|
||||
return False
|
||||
|
||||
# Register the inplace_servfail_callback function as an inplace callback
|
||||
# function when answering with SERVFAIL.
|
||||
if not register_inplace_cb_reply_servfail(inplace_servfail_callback, env):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def init(id, cfg):
|
||||
"""Previous version init function.
|
||||
..note:: This function is still supported for backwards compatibility when
|
||||
the init_standard function is missing. When init_standard is
|
||||
present this function SHOULD be ommited to avoid confusion to the
|
||||
reader.
|
||||
"""
|
||||
return True
|
||||
|
||||
|
||||
def deinit(id): return True
|
||||
|
||||
|
||||
def inform_super(id, qstate, superqstate, qdata): return True
|
||||
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
if (event == MODULE_EVENT_NEW) or (event == MODULE_EVENT_PASS):
|
||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||
return True
|
||||
|
||||
elif event == MODULE_EVENT_MODDONE:
|
||||
qstate.ext_state[id] = MODULE_FINISHED
|
||||
return True
|
||||
|
||||
log_err("pythonmod: Unknown event")
|
||||
qstate.ext_state[id] = MODULE_ERROR
|
||||
return True
|
@ -1,7 +1,6 @@
|
||||
/*
|
||||
* interface.i: unbound python module
|
||||
*/
|
||||
|
||||
%module unboundmodule
|
||||
%{
|
||||
/**
|
||||
@ -34,10 +33,10 @@
|
||||
#include "sldns/pkthdr.h"
|
||||
%}
|
||||
|
||||
%include "stdint.i" // uint_16_t can be known type now
|
||||
%include "stdint.i" /* uint_16_t can be known type now */
|
||||
|
||||
%inline %{
|
||||
//converts [len][data][len][data][0] string to a List of labels (PyBytes)
|
||||
/* converts [len][data][len][data][0] string to a List of labels (PyBytes) */
|
||||
PyObject* GetNameAsLabelList(const char* name, int len) {
|
||||
PyObject* list;
|
||||
int cnt=0, i;
|
||||
@ -202,13 +201,16 @@ struct packed_rrset_key {
|
||||
char* dname;
|
||||
size_t dname_len;
|
||||
uint32_t flags;
|
||||
uint16_t type; //rrset type in network format
|
||||
uint16_t rrset_class; //rrset class in network format
|
||||
uint16_t type; /* rrset type in network format */
|
||||
uint16_t rrset_class; /* rrset class in network format */
|
||||
%mutable;
|
||||
};
|
||||
|
||||
//This subroutine converts values between the host and network byte order.
|
||||
//Specifically, ntohs() converts 16-bit quantities from network byte order to host byte order.
|
||||
/**
|
||||
* This subroutine converts values between the host and network byte order.
|
||||
* Specifically, ntohs() converts 16-bit quantities from network byte order to
|
||||
* host byte order.
|
||||
*/
|
||||
uint16_t ntohs(uint16_t netshort);
|
||||
|
||||
%inline %{
|
||||
@ -269,17 +271,24 @@ struct lruhash_entry {
|
||||
%ignore packed_rrset_data::rr_data;
|
||||
|
||||
struct packed_rrset_data {
|
||||
uint32_t ttl; //TTL (in seconds like time())
|
||||
/* TTL (in seconds like time()) */
|
||||
uint32_t ttl;
|
||||
|
||||
size_t count; //number of rrs
|
||||
size_t rrsig_count; //number of rrsigs
|
||||
/* number of rrs */
|
||||
size_t count;
|
||||
/* number of rrsigs */
|
||||
size_t rrsig_count;
|
||||
|
||||
enum rrset_trust trust;
|
||||
enum sec_status security;
|
||||
|
||||
size_t* rr_len; //length of every rr's rdata
|
||||
uint32_t *rr_ttl; //ttl of every rr
|
||||
uint8_t** rr_data; //array of pointers to every rr's rdata; The rr_data[i] rdata is stored in uncompressed wireformat.
|
||||
/* length of every rr's rdata */
|
||||
size_t* rr_len;
|
||||
/* ttl of every rr */
|
||||
uint32_t *rr_ttl;
|
||||
/* array of pointers to every rr's rdata. The rr_data[i] rdata is stored in
|
||||
* uncompressed wireformat. */
|
||||
uint8_t** rr_data;
|
||||
};
|
||||
|
||||
%pythoncode %{
|
||||
@ -359,10 +368,10 @@ struct reply_info {
|
||||
size_t an_numrrsets;
|
||||
size_t ns_numrrsets;
|
||||
size_t ar_numrrsets;
|
||||
size_t rrset_count; // an_numrrsets + ns_numrrsets + ar_numrrsets
|
||||
size_t rrset_count; /* an_numrrsets + ns_numrrsets + ar_numrrsets */
|
||||
|
||||
struct ub_packed_rrset_key** rrsets;
|
||||
struct rrset_ref ref[1]; //?
|
||||
struct rrset_ref ref[1]; /* ? */
|
||||
};
|
||||
|
||||
struct rrset_ref {
|
||||
@ -396,11 +405,11 @@ struct dns_msg {
|
||||
|
||||
struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) {
|
||||
if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) {
|
||||
//printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key);
|
||||
/* printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key); */
|
||||
return &(r->ref[idx]);
|
||||
// return &(r->ref[idx]);
|
||||
/* return &(r->ref[idx]); */
|
||||
}
|
||||
//printf("_rrset_ref_get: NULL\n");
|
||||
/* printf("_rrset_ref_get: NULL\n"); */
|
||||
return NULL;
|
||||
}
|
||||
%}
|
||||
@ -479,30 +488,166 @@ struct comm_reply {
|
||||
if _newclass:family = _swig_property(_family_get)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure edns_option
|
||||
* ************************************************************************************ */
|
||||
/* Rename the members to follow the python convention of marking them as
|
||||
* private. Access to the opt_code and opt_data members is given by the later
|
||||
* python defined code and data members respectively. */
|
||||
%rename(_next) edns_option::next;
|
||||
%rename(_opt_code) edns_option::opt_code;
|
||||
%rename(_opt_len) edns_option::opt_len;
|
||||
%rename(_opt_data) edns_option::opt_data;
|
||||
struct edns_option {
|
||||
struct edns_option* next;
|
||||
uint16_t opt_code;
|
||||
size_t opt_len;
|
||||
uint8_t* opt_data;
|
||||
};
|
||||
|
||||
%inline %{
|
||||
PyObject* _edns_option_opt_code_get(struct edns_option* option) {
|
||||
uint16_t opt_code = option->opt_code;
|
||||
return PyInt_FromLong(opt_code);
|
||||
}
|
||||
|
||||
PyObject* _edns_option_opt_data_get(struct edns_option* option) {
|
||||
return PyByteArray_FromStringAndSize((uint8_t*)option->opt_data,
|
||||
option->opt_len);
|
||||
}
|
||||
%}
|
||||
%extend edns_option {
|
||||
%pythoncode %{
|
||||
def _opt_code_get(self): return _edns_option_opt_code_get(self)
|
||||
__swig_getmethods__["code"] = _opt_code_get
|
||||
if _newclass: opt_code = _swig_property(_opt_code_get)
|
||||
|
||||
def _opt_data_get(self): return _edns_option_opt_data_get(self)
|
||||
__swig_getmethods__["data"] = _opt_data_get
|
||||
if _newclass: opt_data = _swig_property(_opt_data_get)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure edns_data
|
||||
* ************************************************************************************ */
|
||||
/* This is ignored because we will pass a double pointer of this to Python
|
||||
* with custom getmethods. This is done to bypass Swig's behavior to pass NULL
|
||||
* pointers as None. */
|
||||
%ignore edns_data::opt_list;
|
||||
struct edns_data {
|
||||
int edns_present;
|
||||
uint8_t ext_rcode;
|
||||
uint8_t edns_version;
|
||||
uint16_t bits;
|
||||
uint16_t udp_size;
|
||||
struct edns_option* opt_list;
|
||||
};
|
||||
%inline %{
|
||||
struct edns_option** _edns_data_opt_list_get(struct edns_data* edns) {
|
||||
return &edns->opt_list;
|
||||
}
|
||||
%}
|
||||
%extend edns_data {
|
||||
%pythoncode %{
|
||||
def _opt_list_iter(self): return EdnsOptsListIter(self.opt_list)
|
||||
__swig_getmethods__["opt_list_iter"] = _opt_list_iter
|
||||
if _newclass:opt_list_iter = _swig_property(_opt_list_iter)
|
||||
def _opt_list(self): return _edns_data_opt_list_get(self)
|
||||
__swig_getmethods__["opt_list"] = _opt_list
|
||||
if _newclass:opt_list = _swig_property(_opt_list)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure module_env
|
||||
* ************************************************************************************ */
|
||||
struct module_env {
|
||||
struct config_file* cfg;
|
||||
struct slabhash* msg_cache;
|
||||
struct rrset_cache* rrset_cache;
|
||||
struct infra_cache* infra_cache;
|
||||
struct key_cache* key_cache;
|
||||
|
||||
/* --- services --- */
|
||||
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, int ssl_upstream,
|
||||
struct module_qstate* q);
|
||||
void (*detach_subs)(struct module_qstate* qstate);
|
||||
int (*attach_sub)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime,
|
||||
int valrec, struct module_qstate** newq);
|
||||
void (*kill_sub)(struct module_qstate* newq);
|
||||
int (*detect_cycle)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, uint16_t flags, int prime,
|
||||
int valrec);
|
||||
|
||||
struct regional* scratch;
|
||||
struct sldns_buffer* scratch_buffer;
|
||||
struct worker* worker;
|
||||
struct mesh_area* mesh;
|
||||
struct alloc_cache* alloc;
|
||||
struct ub_randstate* rnd;
|
||||
time_t* now;
|
||||
struct timeval* now_tv;
|
||||
int need_to_validate;
|
||||
struct val_anchors* anchors;
|
||||
struct val_neg_cache* neg_cache;
|
||||
struct comm_timer* probe_timer;
|
||||
struct iter_forwards* fwds;
|
||||
struct iter_hints* hints;
|
||||
void* modinfo[MAX_MODULE];
|
||||
|
||||
void* inplace_cb_lists[inplace_cb_types_total];
|
||||
struct edns_known_option* edns_known_options;
|
||||
size_t edns_known_options_num;
|
||||
};
|
||||
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure module_qstate
|
||||
* ************************************************************************************ */
|
||||
%ignore module_qstate::ext_state;
|
||||
%ignore module_qstate::minfo;
|
||||
|
||||
/* These are ignored because we will pass a double pointer of them to Python
|
||||
* with custom getmethods. This is done to bypass Swig's behavior to pass NULL
|
||||
* pointers as None. */
|
||||
%ignore module_qstate::edns_opts_front_in;
|
||||
%ignore module_qstate::edns_opts_back_out;
|
||||
%ignore module_qstate::edns_opts_back_in;
|
||||
%ignore module_qstate::edns_opts_front_out;
|
||||
|
||||
/* Query state */
|
||||
struct module_qstate {
|
||||
struct query_info qinfo;
|
||||
uint16_t query_flags; //See QF_BIT_xx constants
|
||||
int is_priming;
|
||||
uint16_t query_flags; /* See QF_BIT_xx constants */
|
||||
int is_priming;
|
||||
int is_valrec;
|
||||
|
||||
struct comm_reply* reply;
|
||||
struct dns_msg* return_msg;
|
||||
int return_rcode;
|
||||
int return_rcode;
|
||||
struct regional* region; /* unwrapped */
|
||||
|
||||
int curmod;
|
||||
int curmod;
|
||||
|
||||
enum module_ext_state ext_state[MAX_MODULE];
|
||||
void* minfo[MAX_MODULE];
|
||||
enum module_ext_state ext_state[MAX_MODULE];
|
||||
void* minfo[MAX_MODULE];
|
||||
time_t prefetch_leeway;
|
||||
|
||||
struct module_env* env; /* unwrapped */
|
||||
struct mesh_state* mesh_info;
|
||||
|
||||
struct edns_option* edns_opts_front_in;
|
||||
struct edns_option* edns_opts_back_out;
|
||||
struct edns_option* edns_opts_back_in;
|
||||
struct edns_option* edns_opts_front_out;
|
||||
int no_cache_lookup;
|
||||
int no_cache_store;
|
||||
};
|
||||
|
||||
%constant int MODULE_COUNT = MAX_MODULE;
|
||||
@ -540,6 +685,25 @@ struct module_qstate {
|
||||
def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index)
|
||||
def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value)
|
||||
def __len__(self): return _unboundmodule.MODULE_COUNT
|
||||
|
||||
class EdnsOptsListIter:
|
||||
def __init__(self, obj):
|
||||
self._current = obj
|
||||
self._temp = None
|
||||
def __iter__(self): return self
|
||||
def __next__(self):
|
||||
"""Python 3 compatibility"""
|
||||
return self._get_next()
|
||||
def next(self):
|
||||
"""Python 2 compatibility"""
|
||||
return self._get_next()
|
||||
def _get_next(self):
|
||||
if not edns_opt_list_is_empty(self._current):
|
||||
self._temp = self._current
|
||||
self._current = _p_p_edns_option_get_next(self._current)
|
||||
return _dereference_edns_option(self._temp)
|
||||
else:
|
||||
raise StopIteration
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
@ -549,12 +713,42 @@ struct module_qstate {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
|
||||
if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
|
||||
q->ext_state[idx] = state;
|
||||
}
|
||||
}
|
||||
|
||||
int edns_opt_list_is_empty(struct edns_option** opt) {
|
||||
if (!opt || !(*opt)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct edns_option* _dereference_edns_option(struct edns_option** opt) {
|
||||
if (!opt) return NULL;
|
||||
return *opt;
|
||||
}
|
||||
|
||||
struct edns_option** _p_p_edns_option_get_next(struct edns_option** opt) {
|
||||
return &(*opt)->next;
|
||||
}
|
||||
|
||||
struct edns_option** _edns_opts_front_in_get(struct module_qstate* q) {
|
||||
return &q->edns_opts_front_in;
|
||||
}
|
||||
|
||||
struct edns_option** _edns_opts_back_out_get(struct module_qstate* q) {
|
||||
return &q->edns_opts_back_out;
|
||||
}
|
||||
|
||||
struct edns_option** _edns_opts_back_in_get(struct module_qstate* q) {
|
||||
return &q->edns_opts_back_in;
|
||||
}
|
||||
|
||||
struct edns_option** _edns_opts_front_out_get(struct module_qstate* q) {
|
||||
return &q->edns_opts_front_out;
|
||||
}
|
||||
%}
|
||||
|
||||
%extend module_qstate {
|
||||
@ -566,6 +760,32 @@ struct module_qstate {
|
||||
def __ext_state_get(self): return ExtState(self)
|
||||
__swig_getmethods__["ext_state"] = __ext_state_get
|
||||
if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set)
|
||||
|
||||
def _edns_opts_front_in_iter(self): return EdnsOptsListIter(self.edns_opts_front_in)
|
||||
__swig_getmethods__["edns_opts_front_in_iter"] = _edns_opts_front_in_iter
|
||||
if _newclass:edns_opts_front_in_iter = _swig_property(_edns_opts_front_in_iter)
|
||||
def _edns_opts_back_out_iter(self): return EdnsOptsListIter(self.edns_opts_back_out)
|
||||
__swig_getmethods__["edns_opts_back_out_iter"] = _edns_opts_back_out_iter
|
||||
if _newclass:edns_opts_back_out_iter = _swig_property(_edns_opts_back_out_iter)
|
||||
def _edns_opts_back_in_iter(self): return EdnsOptsListIter(self.edns_opts_back_in)
|
||||
__swig_getmethods__["edns_opts_back_in_iter"] = _edns_opts_back_in_iter
|
||||
if _newclass:edns_opts_back_in_iter = _swig_property(_edns_opts_back_in_iter)
|
||||
def _edns_opts_front_out_iter(self): return EdnsOptsListIter(self.edns_opts_front_out)
|
||||
__swig_getmethods__["edns_opts_front_out_iter"] = _edns_opts_front_out_iter
|
||||
if _newclass:edns_opts_front_out_iter = _swig_property(_edns_opts_front_out_iter)
|
||||
|
||||
def _edns_opts_front_in(self): return _edns_opts_front_in_get(self)
|
||||
__swig_getmethods__["edns_opts_front_in"] = _edns_opts_front_in
|
||||
if _newclass:edns_opts_front_in = _swig_property(_edns_opts_front_in)
|
||||
def _edns_opts_back_out(self): return _edns_opts_back_out_get(self)
|
||||
__swig_getmethods__["edns_opts_back_out"] = _edns_opts_back_out
|
||||
if _newclass:edns_opts_back_out = _swig_property(_edns_opts_back_out)
|
||||
def _edns_opts_back_in(self): return _edns_opts_back_in_get(self)
|
||||
__swig_getmethods__["edns_opts_back_in"] = _edns_opts_back_in
|
||||
if _newclass:edns_opts_back_in = _swig_property(_edns_opts_back_in)
|
||||
def _edns_opts_front_out(self): return _edns_opts_front_out_get(self)
|
||||
__swig_getmethods__["edns_opts_front_out"] = _edns_opts_front_out
|
||||
if _newclass:edns_opts_front_out = _swig_property(_edns_opts_front_out)
|
||||
%}
|
||||
}
|
||||
|
||||
@ -1037,8 +1257,9 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
|
||||
/* ************************************************************************************ *
|
||||
Functions
|
||||
* ************************************************************************************ */
|
||||
|
||||
// Various debuging functions
|
||||
/******************************
|
||||
* Various debuging functions *
|
||||
******************************/
|
||||
void verbose(enum verbosity_value level, const char* format, ...);
|
||||
void log_info(const char* format, ...);
|
||||
void log_err(const char* format, ...);
|
||||
@ -1048,24 +1269,166 @@ void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* r
|
||||
void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf);
|
||||
void regional_log_stats(struct regional *r);
|
||||
|
||||
// Free allocated memory from marked sources returning corresponding types
|
||||
/***************************************************************************
|
||||
* Free allocated memory from marked sources returning corresponding types *
|
||||
***************************************************************************/
|
||||
%typemap(newfree, noblock = 1) char * {
|
||||
free($1);
|
||||
}
|
||||
|
||||
// Mark as source returning newly allocated memory
|
||||
/***************************************************
|
||||
* Mark as source returning newly allocated memory *
|
||||
***************************************************/
|
||||
%newobject sldns_wire2str_type;
|
||||
%newobject sldns_wire2str_class;
|
||||
|
||||
// LDNS functions
|
||||
/******************
|
||||
* LDNS functions *
|
||||
******************/
|
||||
char *sldns_wire2str_type(const uint16_t atype);
|
||||
char *sldns_wire2str_class(const uint16_t aclass);
|
||||
|
||||
// Functions from pythonmod_utils
|
||||
/**********************************
|
||||
* Functions from pythonmod_utils *
|
||||
**********************************/
|
||||
int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral);
|
||||
void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo);
|
||||
|
||||
// Module conversion functions
|
||||
/*******************************
|
||||
* Module conversion functions *
|
||||
*******************************/
|
||||
const char* strextstate(enum module_ext_state s);
|
||||
const char* strmodulevent(enum module_ev e);
|
||||
|
||||
/**************************
|
||||
* Edns related functions *
|
||||
**************************/
|
||||
struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code);
|
||||
int edns_register_option(uint16_t opt_code, int bypass_cache_stage,
|
||||
int no_aggregation, struct module_env* env);
|
||||
|
||||
%pythoncode %{
|
||||
def register_edns_option(env, code, bypass_cache_stage=False,
|
||||
no_aggregation=False):
|
||||
"""Wrapper function to provide keyword attributes."""
|
||||
return edns_register_option(code, bypass_cache_stage,
|
||||
no_aggregation, env)
|
||||
%}
|
||||
|
||||
/******************************
|
||||
* Callback related functions *
|
||||
******************************/
|
||||
/* typemap to check if argument is callable */
|
||||
%typemap(in) PyObject *py_cb {
|
||||
if (!PyCallable_Check($input)) {
|
||||
SWIG_exception_fail(SWIG_TypeError, "Need a callable object!");
|
||||
return NULL;
|
||||
}
|
||||
$1 = $input;
|
||||
}
|
||||
/* typemap to get content/size from a bytearray */
|
||||
%typemap(in) (size_t len, uint8_t* py_bytearray_data) {
|
||||
if (!PyByteArray_CheckExact($input)) {
|
||||
SWIG_exception_fail(SWIG_TypeError, "Expected bytearray!");
|
||||
return NULL;
|
||||
}
|
||||
$2 = PyByteArray_AsString($input);
|
||||
$1 = PyByteArray_Size($input);
|
||||
}
|
||||
|
||||
int edns_opt_list_remove(struct edns_option** list, uint16_t code);
|
||||
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
uint8_t* py_bytearray_data, struct regional* region);
|
||||
|
||||
%{
|
||||
/* This function is called by unbound in order to call the python
|
||||
* callback function. */
|
||||
int python_inplace_cb_reply_generic(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)
|
||||
{
|
||||
PyObject *func, *py_edns, *py_qstate, *py_opt_list_out, *py_qinfo;
|
||||
PyObject *py_rep, *py_region;
|
||||
PyObject *result;
|
||||
int res = 0;
|
||||
|
||||
func = (PyObject *) python_callback;
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
py_edns = SWIG_NewPointerObj((void*) edns, SWIGTYPE_p_edns_data, 0);
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate,
|
||||
SWIGTYPE_p_module_qstate, 0);
|
||||
py_opt_list_out = SWIG_NewPointerObj((void*) opt_list_out,
|
||||
SWIGTYPE_p_p_edns_option, 0);
|
||||
py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
|
||||
py_rep = SWIG_NewPointerObj((void*) rep, SWIGTYPE_p_reply_info, 0);
|
||||
py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
|
||||
result = PyObject_CallFunction(func, "OOOiOOO", py_qinfo, py_qstate,
|
||||
py_rep, rcode, py_edns, py_opt_list_out, py_region);
|
||||
Py_XDECREF(py_edns);
|
||||
Py_XDECREF(py_qstate);
|
||||
Py_XDECREF(py_opt_list_out);
|
||||
Py_XDECREF(py_qinfo);
|
||||
Py_XDECREF(py_rep);
|
||||
Py_XDECREF(py_region);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
Py_XDECREF(result);
|
||||
PyGILState_Release(gstate);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Swig implementations for Python */
|
||||
static int register_inplace_cb_reply(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
{
|
||||
int ret = inplace_cb_reply_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
static int register_inplace_cb_reply_cache(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
{
|
||||
int ret = inplace_cb_reply_cache_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
static int register_inplace_cb_reply_local(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
{
|
||||
int ret = inplace_cb_reply_local_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
static int register_inplace_cb_reply_servfail(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
{
|
||||
int ret = inplace_cb_reply_servfail_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
%}
|
||||
/* C declarations */
|
||||
int inplace_cb_reply_register(
|
||||
inplace_cb_reply_func_t* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_cache_register(
|
||||
inplace_cb_reply_func_t* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_local_register(
|
||||
inplace_cb_reply_func_t* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_servfail_register(
|
||||
inplace_cb_reply_func_t* cb, void* cb_arg, struct module_env* env);
|
||||
|
||||
/* Swig declarations */
|
||||
static int register_inplace_cb_reply(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
static int register_inplace_cb_reply_cache(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
static int register_inplace_cb_reply_local(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
static int register_inplace_cb_reply_servfail(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
|
@ -112,8 +112,10 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
{
|
||||
/* Initialize module */
|
||||
FILE* script_py = NULL;
|
||||
PyObject* py_cfg, *res;
|
||||
PyObject* py_init_arg, *res;
|
||||
PyGILState_STATE gil;
|
||||
int init_standard = 1;
|
||||
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
|
||||
if (!pe)
|
||||
{
|
||||
@ -156,10 +158,10 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
PyRun_SimpleString("import sys \n");
|
||||
PyRun_SimpleString("sys.path.append('.') \n");
|
||||
if(env->cfg->directory && env->cfg->directory[0]) {
|
||||
char wdir[1524];
|
||||
snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
|
||||
env->cfg->directory);
|
||||
PyRun_SimpleString(wdir);
|
||||
char wdir[1524];
|
||||
snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
|
||||
env->cfg->directory);
|
||||
PyRun_SimpleString(wdir);
|
||||
}
|
||||
PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
|
||||
PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
|
||||
@ -198,11 +200,15 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
|
||||
fclose(script_py);
|
||||
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL)
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init_standard")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function init is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
init_standard = 0;
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function init is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL)
|
||||
{
|
||||
@ -223,16 +229,28 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
py_cfg = SWIG_NewPointerObj((void*) env->cfg, SWIGTYPE_p_config_file, 0);
|
||||
res = PyObject_CallFunction(pe->func_init, "iO", id, py_cfg);
|
||||
if (init_standard)
|
||||
{
|
||||
py_init_arg = SWIG_NewPointerObj((void*) env, SWIGTYPE_p_module_env, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
py_init_arg = SWIG_NewPointerObj((void*) env->cfg,
|
||||
SWIGTYPE_p_config_file, 0);
|
||||
}
|
||||
res = PyObject_CallFunction(pe->func_init, "iO", id, py_init_arg);
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function init");
|
||||
PyErr_Print();
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_init_arg);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_cfg);
|
||||
Py_XDECREF(py_init_arg);
|
||||
PyGILState_Release(gil);
|
||||
|
||||
return 1;
|
||||
|
@ -55,14 +55,22 @@ int pythonmod_init(struct module_env* env, int id);
|
||||
void pythonmod_deinit(struct module_env* env, int id);
|
||||
|
||||
/** python module operate on a query */
|
||||
void pythonmod_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound);
|
||||
void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
|
||||
/** python module */
|
||||
void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_qstate* super);
|
||||
void pythonmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
|
||||
/** python module cleanup query state */
|
||||
void pythonmod_clear(struct module_qstate* qstate, int id);
|
||||
|
||||
/** python module alloc size routine */
|
||||
size_t pythonmod_get_mem(struct module_env* env, int id);
|
||||
|
||||
/** Declared here for fptr_wlist access. The definition is in interface.i. */
|
||||
int python_inplace_cb_reply_generic(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);
|
||||
#endif /* PYTHONMOD_H */
|
||||
|
17
pythonmod/test-edns.conf
Normal file
17
pythonmod/test-edns.conf
Normal file
@ -0,0 +1,17 @@
|
||||
# Example configuration file for edns.py
|
||||
server:
|
||||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/edns.py"
|
17
pythonmod/test-inplace_callbacks.py
Normal file
17
pythonmod/test-inplace_callbacks.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Example configuration file for edns.py
|
||||
server:
|
||||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
do-daemonize: no
|
||||
access-control: 0.0.0.0/0 allow
|
||||
chroot: ""
|
||||
username: ""
|
||||
directory: ""
|
||||
logfile: ""
|
||||
pidfile: "unbound.pid"
|
||||
module-config: "validator python iterator"
|
||||
|
||||
# Python config section
|
||||
python:
|
||||
# Script file to load
|
||||
python-script: "./examples/inplace_callbacks.py"
|
9
services/cache/dns.c
vendored
9
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),
|
||||
@ -1402,7 +1476,7 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
|
||||
log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
|
||||
}
|
||||
|
||||
enum localzone_type
|
||||
static enum localzone_type
|
||||
lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
|
||||
uint8_t *tagactions, size_t tagactionssize, enum localzone_type lzt,
|
||||
struct comm_reply* repinfo, struct rbtree_t* override_tree, int* tag,
|
||||
@ -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.
|
||||
|
199
services/mesh.c
199
services/mesh.c
@ -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
services/view.c
Normal file
207
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
services/view.h
Normal file
135
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;
|
||||
|
@ -420,8 +420,14 @@ read_builtin_cert(void)
|
||||
{
|
||||
const char* builtin_cert = get_builtin_cert();
|
||||
STACK_OF(X509)* sk;
|
||||
BIO *bio = BIO_new_mem_buf((void*)builtin_cert,
|
||||
(int)strlen(builtin_cert));
|
||||
BIO *bio;
|
||||
char* d = strdup(builtin_cert); /* to avoid const warnings in the
|
||||
changed prototype of BIO_new_mem_buf */
|
||||
if(!d) {
|
||||
if(verb) printf("out of memory\n");
|
||||
exit(0);
|
||||
}
|
||||
bio = BIO_new_mem_buf(d, (int)strlen(d));
|
||||
if(!bio) {
|
||||
if(verb) printf("out of memory\n");
|
||||
exit(0);
|
||||
@ -432,6 +438,7 @@ read_builtin_cert(void)
|
||||
exit(0);
|
||||
}
|
||||
BIO_free(bio);
|
||||
free(d);
|
||||
return sk;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -225,8 +223,8 @@ struct order_id {
|
||||
|
||||
int order_lock_cmp(const void* e1, const void* e2)
|
||||
{
|
||||
struct order_id* o1 = (struct order_id*)e1;
|
||||
struct order_id* o2 = (struct order_id*)e2;
|
||||
const struct order_id* o1 = e1;
|
||||
const struct order_id* o2 = e2;
|
||||
if(o1->thr < o2->thr) return -1;
|
||||
if(o1->thr > o2->thr) return 1;
|
||||
if(o1->instance < o2->instance) return -1;
|
||||
@ -237,7 +235,7 @@ int order_lock_cmp(const void* e1, const void* e2)
|
||||
int
|
||||
codeline_cmp(const void* a, const void* b)
|
||||
{
|
||||
return strcmp((const char*)a, (const char*)b);
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
|
@ -470,7 +470,7 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* perform asyncronous calls */
|
||||
/* perform asynchronous calls */
|
||||
num_wait = argc;
|
||||
for(i=0; i<argc; i++) {
|
||||
lookups[i].name = argv[i];
|
||||
|
@ -1036,13 +1036,13 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
}
|
||||
|
||||
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 ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), struct edns_option* opt_list,
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(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* ATTR_UNUSED(buff))
|
||||
size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
sldns_buffer* ATTR_UNUSED(buff), struct module_env* ATTR_UNUSED(env))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
@ -1050,7 +1050,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
char z[256];
|
||||
log_assert(pend);
|
||||
log_nametypeclass(VERB_OPS, "pending serviced query",
|
||||
qname, qtype, qclass);
|
||||
qinfo->qname, qinfo->qtype, qinfo->qclass);
|
||||
dname_str(zone, z);
|
||||
verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s",
|
||||
z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
|
||||
@ -1065,9 +1065,9 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
sldns_buffer_write_u16(pend->buffer, 0); /* ancount */
|
||||
sldns_buffer_write_u16(pend->buffer, 0); /* nscount */
|
||||
sldns_buffer_write_u16(pend->buffer, 0); /* arcount */
|
||||
sldns_buffer_write(pend->buffer, qname, qnamelen);
|
||||
sldns_buffer_write_u16(pend->buffer, qtype);
|
||||
sldns_buffer_write_u16(pend->buffer, qclass);
|
||||
sldns_buffer_write(pend->buffer, qinfo->qname, qinfo->qname_len);
|
||||
sldns_buffer_write_u16(pend->buffer, qinfo->qtype);
|
||||
sldns_buffer_write_u16(pend->buffer, qinfo->qclass);
|
||||
sldns_buffer_flip(pend->buffer);
|
||||
if(1) {
|
||||
/* add edns */
|
||||
@ -1077,7 +1077,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns.bits = 0;
|
||||
edns.opt_list = opt_list;
|
||||
edns.opt_list = qstate->edns_opts_back_out;
|
||||
if(dnssec)
|
||||
edns.bits = EDNS_DO;
|
||||
attach_edns_record(pend->buffer, &edns);
|
||||
@ -1086,7 +1086,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
pend->addrlen = addrlen;
|
||||
pend->zone = memdup(zone, zonelen);
|
||||
pend->zonelen = zonelen;
|
||||
pend->qtype = (int)qtype;
|
||||
pend->qtype = (int)qinfo->qtype;
|
||||
log_assert(pend->zone);
|
||||
pend->callback = callback;
|
||||
pend->cb_arg = callback_arg;
|
||||
|
@ -236,6 +236,7 @@ printstats(rbtree_t* tree)
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
rbtree_t* tree = 0;
|
||||
log_init(NULL, 0, 0);
|
||||
if(argc != 2) {
|
||||
usage();
|
||||
}
|
||||
|
@ -487,6 +487,7 @@ qlist_parse_line(sldns_buffer* buf, char* p)
|
||||
qinfo.qname = sldns_str2wire_dname(nm, &qinfo.qname_len);
|
||||
if(!qinfo.qname)
|
||||
return 0;
|
||||
qinfo.local_alias = NULL;
|
||||
qinfo_query_encode(buf, &qinfo);
|
||||
sldns_buffer_write_u16_at(buf, 0, 0); /* zero ID */
|
||||
if(rec) LDNS_RD_SET(sldns_buffer_begin(buf));
|
||||
|
@ -128,6 +128,9 @@ write_q(int fd, int udp, SSL* ssl, sldns_buffer* buf, uint16_t id,
|
||||
qinfo.qtype = sldns_get_rr_type_by_name(strtype);
|
||||
qinfo.qclass = sldns_get_rr_class_by_name(strclass);
|
||||
|
||||
/* clear local alias */
|
||||
qinfo.local_alias = NULL;
|
||||
|
||||
/* make query */
|
||||
qinfo_query_encode(buf, &qinfo);
|
||||
sldns_buffer_write_u16_at(buf, 0, id);
|
||||
|
BIN
testdata/04-checkconf.tpkg
vendored
BIN
testdata/04-checkconf.tpkg
vendored
Binary file not shown.
BIN
testdata/09-unbound-control.tpkg
vendored
BIN
testdata/09-unbound-control.tpkg
vendored
Binary file not shown.
491
testdata/local_cname.rpl
vendored
Normal file
491
testdata/local_cname.rpl
vendored
Normal file
@ -0,0 +1,491 @@
|
||||
; config options
|
||||
server:
|
||||
# put unbound.conf config options here.
|
||||
|
||||
access-control: 127.0.0.1/32 allow_snoop #allow queries with RD bit
|
||||
|
||||
# DNSSEC trust anchor taken from a real world example. Used for
|
||||
# DNSSEC-signed CNAME target.
|
||||
trust-anchor: "infoblox.com. 172800 IN DNSKEY 257 3 5 AwEAAerW6xQkJIb5wxm48RoHD/LE8r/GzmdIGOam0lQczIth+I9ctltV dDJXz5BH8j4TOaOH1gBRCXhsPDyPom/eLEkdUuXNuhV6QnWGHOtz1fuY EO+kBqaI79jR0K31OmevR/H/F3C8gi4T6//6G9qsftvcl6m7+V1vI2+c cgxiiOlMrZZb4YAhue1+tRw57f3aVOSNtcrONO/Jffgb9jbDTKRi33oT fDznyPa1lCWMbuybr/LaCU0LP6fG4BII/FDWFi5rQxMHygWfscdYX06c eGUzHqiuNNGL8Jze6johni71T/hJGtLMozkY7qxOLfWBXOu9kr1MBQh5 6hfibOZMZJM="
|
||||
# Use a fixed and faked date for DNSSEC validation to avoid run-time
|
||||
# re-signing test signatures.
|
||||
val-override-date: "20161001003725"
|
||||
|
||||
define-tag: "cname cname2 nx servfail sec ambiguous"
|
||||
access-control-tag: 127.0.0.1/32 "cname cname2 nx servfail sec"
|
||||
|
||||
# Basic case: one CNAME whose target exists.
|
||||
local-zone: example.com static
|
||||
local-zone-tag: example.com "cname"
|
||||
access-control-tag: 127.0.0.1/32 "cname"
|
||||
access-control-tag-action: 127.0.0.1/32 "cname" redirect
|
||||
access-control-tag-data: 127.0.0.1/32 "cname" "CNAME example.org."
|
||||
|
||||
# Similar to the above, but different original query name.
|
||||
local-zone: another.example.com static
|
||||
local-zone-tag: another.example.com "cname2"
|
||||
access-control-tag: 127.0.0.1/32 "cname2"
|
||||
access-control-tag-action: 127.0.0.1/32 "cname2" redirect
|
||||
access-control-tag-data: 127.0.0.1/32 "cname2" "CNAME example.org."
|
||||
|
||||
# CNAME target is expected to be nonexistent.
|
||||
local-zone: nx.example.com static
|
||||
local-zone-tag: nx.example.com "nx"
|
||||
access-control-tag: 127.0.0.1/32 "nx"
|
||||
access-control-tag-action: 127.0.0.1/32 "nx" redirect
|
||||
access-control-tag-data: 127.0.0.1/32 "nx" "CNAME nx.example.org."
|
||||
|
||||
# Resolution of this CNAME target will result in SERVFAIL.
|
||||
local-zone: servfail.example.com static
|
||||
local-zone-tag: servfail.example.com "servfail"
|
||||
access-control-tag-action: 127.0.0.1/32 "servfail" redirect
|
||||
access-control-tag-data: 127.0.0.1/32 "servfail" "CNAME servfail.example.org."
|
||||
|
||||
# CNAME target is supposed to be DNSSEC-signed.
|
||||
local-zone: sec.example.com static
|
||||
local-zone-tag: sec.example.com "sec"
|
||||
access-control-tag-action: 127.0.0.1/32 "sec" redirect
|
||||
access-control-tag-data: 127.0.0.1/32 "sec" "CNAME www.infoblox.com."
|
||||
|
||||
# Test setup for non-tag based redirect
|
||||
local-zone: example.net redirect
|
||||
local-data: "example.net. IN CNAME cname.example.org."
|
||||
|
||||
### template zone and tag intended to be used for tests with CNAME and
|
||||
### other data.
|
||||
##local-zone: ambiguous.example.com redirect
|
||||
##@LOCALDATA1@
|
||||
##@LOCALDATA2@
|
||||
##local-zone-tag: ambiguous.example.com "ambiguous"
|
||||
##access-control-tag-action: 127.0.0.1/32 "ambiguous" redirect
|
||||
##@TAGDATA1@
|
||||
##@TAGDATA2@
|
||||
|
||||
|
||||
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
|
||||
# send the queries to the test server (see the 10.0.10.3 entries below)
|
||||
forward-zone:
|
||||
name: "."
|
||||
forward-addr: 10.0.10.3
|
||||
CONFIG_END
|
||||
|
||||
; short one-line description of scenario:
|
||||
SCENARIO_BEGIN Test local-data CNAME aliases
|
||||
|
||||
; Specification of the answers that the upstream server provides to unbound
|
||||
RANGE_BEGIN 0 1000
|
||||
ADDRESS 10.0.10.3
|
||||
; put entries here with answers to specific qname, qtype
|
||||
|
||||
; infoblox.com
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
infoblox.com. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
infoblox.com. 172800 IN DNSKEY 256 3 5 AwEAAbi2VnVHFm5rO2EiawNWhTTRPPzaA+VEdpGOc+CtwIZq86C4Ndbp 0M7XTi0wru0Pgh54oGZ3ty9WllYEnVfoA1rcGwFJmAln7KKAuQP+dlGE yHPJYduAjG/JFA6Qq0zj18AmWgks+qvethASMm3PtihQkNytjmQWjiL6 6h8cQwFP
|
||||
infoblox.com. 172800 IN DNSKEY 257 3 5 AwEAAerW6xQkJIb5wxm48RoHD/LE8r/GzmdIGOam0lQczIth+I9ctltV dDJXz5BH8j4TOaOH1gBRCXhsPDyPom/eLEkdUuXNuhV6QnWGHOtz1fuY EO+kBqaI79jR0K31OmevR/H/F3C8gi4T6//6G9qsftvcl6m7+V1vI2+c cgxiiOlMrZZb4YAhue1+tRw57f3aVOSNtcrONO/Jffgb9jbDTKRi33oT fDznyPa1lCWMbuybr/LaCU0LP6fG4BII/FDWFi5rQxMHygWfscdYX06c eGUzHqiuNNGL8Jze6johni71T/hJGtLMozkY7qxOLfWBXOu9kr1MBQh5 6hfibOZMZJM=
|
||||
infoblox.com. 172800 IN RRSIG DNSKEY 5 2 172800 20161004003725 20160930000830 31651 infoblox.com. Ds7LZY2W59fq9cWgqi3W6so1NGFa7JdjO8zlhK3hGu2a2WG1W/rVftom rCf0gdI5q4BZJnq2o0SdLd/U7he1uWz8ATntEETiNs9/8G7myNK17wQu AN/+3gol+qT4DX0CA3Boz7Z+xFQbTwnnJJvGASa/1jPMIYU8DiyNx3Pe SSh9lbyU/4YI0mshn5ZC2HCFChxr+aVJxk4UHjaPfHhWwVu9oM4IbEfn KD9x4ltKjjy0pXMYqVlNs9+tG2nXdwr/6Q4G+yfRBAcW+cWeW5w4igxf xYFq4Y5gkZetGOReoNODZ9YC9WvcxBo+qY/iUN2k+lEFq+oL8+DthAGH uA1krw==
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.infoblox.com. IN A
|
||||
SECTION ANSWER
|
||||
www.infoblox.com. 3600 IN A 161.47.10.70
|
||||
www.infoblox.com. 3600 IN RRSIG A 5 3 3600 20161003223322 20160929221122 14916 infoblox.com. WbO9ydRAoRTPvdK18atTdLEkkMGoOjuwbcb6vVI0d6Sea3xkcBMNmtst Wdzr+pKEJqO2bfm167X6uhcOHanHZRnirlTnEbuTdsP0HCiIEGQD5iHg UNH2FJSKGNYBmgZKJpuLhDca7oqtkl8EyGA+UEt6Rtq6aW8V0wpkhPHi Pug='
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; example.org
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.org. IN A
|
||||
SECTION ANSWER
|
||||
example.org. IN A 192.0.2.1
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
cname.example.org. IN A
|
||||
SECTION ANSWER
|
||||
cname.example.org. IN A 192.0.2.2
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.org. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.org. IN SOA ns.example.org. hostmaster.example.org. 2016101900 28800 7200 604800 3600
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NXDOMAIN
|
||||
SECTION QUESTION
|
||||
nx.example.org. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.org. IN SOA ns.example.org. hostmaster.example.org. 2016101900 28800 7200 604800 3600
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; for norec query
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.org. IN NS
|
||||
SECTION ANSWER
|
||||
example.org. IN NS ns.example.
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR SERVFAIL
|
||||
SECTION QUESTION
|
||||
servfail.example.org. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; end of entries with answers from upstream server
|
||||
RANGE_END
|
||||
; Steps where queries are sent, one at a time, to unbound.
|
||||
; QUERY is what the downstream client sends to unbound.
|
||||
; CHECK_ANSWER contains the response from unbound.
|
||||
|
||||
|
||||
; Basic case: both exact and subdomain matches result in the same CNAME
|
||||
STEP 10 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
example.com. IN CNAME
|
||||
ENTRY_END
|
||||
|
||||
; For type-CNAME queries, the CNAME itself will be returned
|
||||
STEP 20 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN CNAME
|
||||
SECTION ANSWER
|
||||
example.com. IN CNAME example.org.
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 30 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
alias.example.com. IN CNAME
|
||||
ENTRY_END
|
||||
|
||||
; For type-CNAME queries, the CNAME itself will be returned
|
||||
STEP 40 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
alias.example.com. IN CNAME
|
||||
SECTION ANSWER
|
||||
alias.example.com. IN CNAME example.org.
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; Basic case: both exact and subdomain matches result in the same CNAME
|
||||
; For other types, a complete CNAME chain will have to be returned
|
||||
STEP 50 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 60 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
SECTION ANSWER
|
||||
example.com. IN CNAME example.org.
|
||||
example.org. IN A 192.0.2.1
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 70 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
alias.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 80 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
alias.example.com. IN A
|
||||
SECTION ANSWER
|
||||
alias.example.com. IN CNAME example.org.
|
||||
example.org. IN A 192.0.2.1
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; Basic case: both exact and subdomain matches result in the same CNAME.
|
||||
; The result is the same for non-recursive query as long as a
|
||||
; complete chain is cached.
|
||||
STEP 90 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 100 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
SECTION ANSWER
|
||||
example.com. IN CNAME example.org.
|
||||
example.org. IN A 192.0.2.1
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 110 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY
|
||||
SECTION QUESTION
|
||||
alias.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 120 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
alias.example.com. IN A
|
||||
SECTION ANSWER
|
||||
alias.example.com. IN CNAME example.org.
|
||||
example.org. IN A 192.0.2.1
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; Similar to the above, but these are local-zone redirect, instead of
|
||||
; tag-based policies.
|
||||
STEP 130 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
example.net. IN CNAME
|
||||
ENTRY_END
|
||||
|
||||
; For type-CNAME queries, the CNAME itself will be returned
|
||||
STEP 140 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.net. IN CNAME
|
||||
SECTION ANSWER
|
||||
example.net. IN CNAME cname.example.org.
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 150 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
alias.example.net. IN CNAME
|
||||
ENTRY_END
|
||||
|
||||
; For type-CNAME queries, the CNAME itself will be returned
|
||||
STEP 160 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
alias.example.net. IN CNAME
|
||||
SECTION ANSWER
|
||||
alias.example.net. IN CNAME cname.example.org.
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 170 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
example.net. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 180 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.net. IN A
|
||||
SECTION ANSWER
|
||||
example.net. IN CNAME cname.example.org.
|
||||
cname.example.org. IN A 192.0.2.2
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
STEP 190 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
alias.example.net. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 200 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
alias.example.net. IN A
|
||||
SECTION ANSWER
|
||||
alias.example.net. IN CNAME cname.example.org.
|
||||
cname.example.org. IN A 192.0.2.2
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
|
||||
; Relatively minor cases follow
|
||||
|
||||
; query type doesn't exist for the CNAME target. The original query
|
||||
; succeeds with an "incomplete" chain only containing the CNAME.
|
||||
STEP 210 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
example.com. IN AAAA
|
||||
ENTRY_END
|
||||
|
||||
STEP 220 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
example.com. IN CNAME example.org.
|
||||
SECTION AUTHORITY
|
||||
example.org. 3600 IN SOA ns.example.org. hostmaster.example.org. 2016101900 28800 7200 604800 3600
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; The CNAME target name doesn't exist. NXDOMAIN with the CNAME will
|
||||
; be returned.
|
||||
STEP 230 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
nx.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 240 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
nx.example.com. IN A
|
||||
SECTION ANSWER
|
||||
nx.example.com. IN CNAME nx.example.org.
|
||||
SECTION AUTHORITY
|
||||
example.org. 3600 IN SOA ns.example.org. hostmaster.example.org. 2016101900 28800 7200 604800 3600
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; Resolution for the CNAME target will result in SERVFAIL. It will
|
||||
; be forwarded to the original query. The answer section should be
|
||||
; empty.
|
||||
STEP 250 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
servfail.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 260 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA SERVFAIL
|
||||
SECTION QUESTION
|
||||
servfail.example.com. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
; The CNAME target is DNSSEC-signed and it's validated. If the original
|
||||
; query enabled the DNSSEC, the RRSIGs will be included in the answer,
|
||||
; but the response should have the AD bit off
|
||||
STEP 270 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
sec.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 280 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD DO RA AA NOERROR
|
||||
SECTION QUESTION
|
||||
sec.example.com. IN A
|
||||
SECTION ANSWER
|
||||
sec.example.com. IN CNAME www.infoblox.com.
|
||||
www.infoblox.com. 3600 IN A 161.47.10.70
|
||||
www.infoblox.com. 3600 IN RRSIG A 5 3 3600 20161003223322 20160929221122 14916 infoblox.com. WbO9ydRAoRTPvdK18atTdLEkkMGoOjuwbcb6vVI0d6Sea3xkcBMNmtst Wdzr+pKEJqO2bfm167X6uhcOHanHZRnirlTnEbuTdsP0HCiIEGQD5iHg UNH2FJSKGNYBmgZKJpuLhDca7oqtkl8EyGA+UEt6Rtq6aW8V0wpkhPHi Pug='
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
|
||||
SCENARIO_END
|
110
testdata/stop_nxdomain_minimised.rpl
vendored
Normal file
110
testdata/stop_nxdomain_minimised.rpl
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
harden-below-nxdomain: yes
|
||||
qname-minimisation: yes
|
||||
trust-anchor: ". IN DNSKEY 257 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3"
|
||||
val-override-date: "20070916134226"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
stub-zone:
|
||||
name: "anotherexample.local."
|
||||
stub-addr: 10.20.30.40
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test stop cache search on nxdomain for QNAME minimised query
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
. 3600 IN DNSKEY 257 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30900 (ksk), size = 512b}
|
||||
. 3600 IN RRSIG DNSKEY 5 0 3600 20070926134150 20070829134150 30900 . BlVcSh8xSgm7ne+XVCJwNHQKjk5kTJgG4Fa3sOSfp3YUjb2YclmVWyIw7XEHl0/C6CN5gdy18idnM6vT6Hy42A== ;{id = 30900}
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
local. IN A
|
||||
SECTION AUTHORITY
|
||||
. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400
|
||||
. 86400 IN RRSIG SOA 5 0 86400 20070926134150 20070829134150 30900 . bOYbFZZp7vWWC2oxV+kph+YXjoQj2f6QJktlgmzRI7oReFX9jy/LibTPQi/sW0SGHpLaj3G5p4IfIlBibne4DA== ;{id = 30900}
|
||||
. 86400 IN NSEC ac. NS SOA RRSIG NSEC DNSKEY
|
||||
. 86400 IN RRSIG NSEC 5 0 86400 20070926134150 20070829134150 30900 . U+/m5+FmczzkosEx1aTP7MK/F3PpcKWct8CzM1jhjwNe2RlnW7qFe0IH8SLzD/elvxDTQMpJSMlKOhUUdapB8g== ;{id = 30900}
|
||||
lk. 86400 IN NSEC lr. NS DS RRSIG NSEC
|
||||
lk. 86400 IN RRSIG NSEC 5 1 86400 20070926134150 20070829134150 30900 . j6Pw5Eu9vGHDJcckTSWa8YD1b7FV7c/Z8aVkLfJCH+iPcaa40/LSp784+t2PnAAXL8fgriNL6jF/ve1rti3ANQ== ;{id = 30900}
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 10.20.30.40
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
anotherexample.local. IN TXT
|
||||
SECTION ANSWER
|
||||
anotherexample.local. 86400 IN TXT "should not resolve this"
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
example.local. IN TXT
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
example.local. IN TXT
|
||||
SECTION AUTHORITY
|
||||
. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400
|
||||
ENTRY_END
|
||||
|
||||
STEP 20 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
anotherexample.local. IN TXT
|
||||
ENTRY_END
|
||||
|
||||
; query should be answered using NXDOMAIN for local in cache
|
||||
STEP 30 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
anotherexample.local. IN TXT
|
||||
SECTION AUTHORITY
|
||||
. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2010111601 1800 900 604800 86400
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
2
testdata/val_cnamewctonodata.rpl
vendored
2
testdata/val_cnamewctonodata.rpl
vendored
@ -11,7 +11,7 @@ stub-zone:
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test validator with wilcard cname to nodata
|
||||
SCENARIO_BEGIN Test validator with wildcard cname to nodata
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
|
1
testdata/val_ds_sha2.crpl
vendored
1
testdata/val_ds_sha2.crpl
vendored
@ -4,6 +4,7 @@ server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
val-override-date: "20070916134226"
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
fake-dsa: yes
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
|
1
testdata/val_ds_sha2_downgrade.crpl
vendored
1
testdata/val_ds_sha2_downgrade.crpl
vendored
@ -4,6 +4,7 @@ server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
val-override-date: "20070916134226"
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
fake-dsa: yes
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
|
4
testdata/val_nodata_failsig.rpl
vendored
4
testdata/val_nodata_failsig.rpl
vendored
@ -130,8 +130,10 @@ SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
; SOA record is missing in reply.
|
||||
; Denies A, note this is the end of the NSEC chain.
|
||||
; this RRSIG is failed, we set to 0 base64 data to make this easy to detect
|
||||
www.example.com. IN NSEC example.com. RRSIG NSEC
|
||||
www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDA8yqBITvLruoQjn/eqjYjwCwySAhUAk5/f3H1HKMsvM+spmmswwFtndyY= ;{id = 2854}
|
||||
;www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFDA8yqBITvLruoQjn/eqjYjwCwySAhUAk5/f3H1HKMsvM+spmmswwFtndyY= ;{id = 2854}
|
||||
www.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926135752 20070829135752 2854 example.com.
|
||||
; Denies wildcard
|
||||
example.com. IN NSEC ns.example.com. NS SOA RRSIG NSEC DNSKEY
|
||||
example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. MCwCFGlz/gvGdVxEo3Kpr+MijEGCZgwaAhRU7qbF13vmCVgR8dFw7LQFKopV6w== ;{id = 2854}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user