$(srcdir)/services/modstack.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_kcache.h \
$(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_sigcrypt.h \
$(srcdir)/sldns/sbuffer.h
-edns-subnet.lo edns-subnet.o: $(srcdir)/edns-subnet/edns-subnet.c config.h $(srcdir)/edns-subnet/edns-subnet.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
-subnet-whitelist.lo subnet-whitelist.o: $(srcdir)/edns-subnet/subnet-whitelist.c config.h $(srcdir)/edns-subnet/subnet-whitelist.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
-subnetmod.lo subnetmod.o: $(srcdir)/edns-subnet/subnetmod.c config.h $(srcdir)/edns-subnet/subnetmod.h \
- $(srcdir)/util/config_file.h $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h
-addrtree.lo addrtree.o: $(srcdir)/edns-subnet/addrtree.c config.h $(srcdir)/edns-subnet/addrtree.h \
- $(srcdir)/util/config_file.h
listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h \
$(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/services/outside_network.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \
$(srcdir)/validator/val_utils.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 $(srcdir)/edns-subnet/subnetmod.h
+ $(srcdir)/util/netevent.h
outside_network.lo outside_network.o: $(srcdir)/services/outside_network.c config.h \
$(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h \
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/infra.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/edns-subnet/edns-subnet.h
-
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/dnstap/dnstap.h
alloc.lo alloc.o: $(srcdir)/util/alloc.c config.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/regional.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/module.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/tube.h \
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
$(srcdir)/util/data/dname.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 $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/sldns/parseutil.h \
- $(srcdir)/sldns/wire2str.h \
-
+ $(srcdir)/sldns/wire2str.h
random.lo random.o: $(srcdir)/util/random.c config.h $(srcdir)/util/random.h $(srcdir)/util/log.h
rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/netevent.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
$(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/services/modstack.h \
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kcache.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h \
-
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h
val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/validator/val_anchor.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/autotrust.h \
val_kentry.lo val_kentry.o: $(srcdir)/validator/val_kentry.c config.h $(srcdir)/validator/val_kentry.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
-
-val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h \
- $(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
- $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_utils.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h
-val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/validator.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kentry.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/validator/val_nsec.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h
+val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h $(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/log.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/services/cache/dns.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h
+val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h $(srcdir)/validator/val_nsec3.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/validator.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kentry.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/validator/val_nsec.h $(srcdir)/sldns/sbuffer.h
val_nsec.lo val_nsec.o: $(srcdir)/validator/val_nsec.c config.h $(srcdir)/validator/val_nsec.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/validator/val_utils.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/dname.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h
val_secalgo.lo val_secalgo.o: $(srcdir)/validator/val_secalgo.c config.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_secalgo.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
- $(srcdir)/sldns/sbuffer.h \
-
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/sbuffer.h
val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.h \
$(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_secalgo.h $(srcdir)/validator/validator.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h $(srcdir)/util/data/dname.h $(srcdir)/util/rbtree.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/sldns/keyraw.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
-
+ $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/validator/val_utils.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h
+edns-subnet.lo edns-subnet.o: $(srcdir)/edns-subnet/edns-subnet.c config.h
+subnetmod.lo subnetmod.o: $(srcdir)/edns-subnet/subnetmod.c config.h
+addrtree.lo addrtree.o: $(srcdir)/edns-subnet/addrtree.c config.h $(srcdir)/util/log.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/edns-subnet/addrtree.h
+subnet-whitelist.lo subnet-whitelist.o: $(srcdir)/edns-subnet/subnet-whitelist.c config.h
dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.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)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/testcode/checklocks.h
-dnstap.lo dnstap.o: $(srcdir)/dnstap/dnstap.c config.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/dnstap/dnstap.pb-c.h
-dnstap.pb-c.lo dnstap.pb-c.o: $(srcdir)/dnstap/dnstap.pb-c.c $(srcdir)/dnstap/dnstap.pb-c.h
unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/unitmain.h \
$(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
unitlruhash.lo unitlruhash.o: $(srcdir)/testcode/unitlruhash.c config.h $(srcdir)/testcode/unitmain.h \
$(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/storage/slabhash.h
-unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
+unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
$(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
$(srcdir)/util/config_file.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/alloc.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/testcode/readhex.h \
$(srcdir)/testcode/testpkts.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
-unitvandergaast.lo unitvandergaast.o: $(srcdir)/testcode/unitvandergaast.c \
- config.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \
- $(srcdir)/edns-subnet/addrtree.h
unitneg.lo unitneg.o: $(srcdir)/testcode/unitneg.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/data/dname.h $(srcdir)/testcode/unitmain.h $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h \
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
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
+unitvandergaast.lo unitvandergaast.o: $(srcdir)/testcode/unitvandergaast.c config.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
-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 $(srcdir)/util/netevent.h $(srcdir)/util/alloc.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 \
+ $(srcdir)/util/netevent.h $(srcdir)/util/alloc.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)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h \
+ $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
+ $(srcdir)/sldns/wire2str.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 \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.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)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
- $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h \
- $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/sldns/wire2str.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 $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/netevent.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)/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
-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 $(srcdir)/util/alloc.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/daemon.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 \
+ $(srcdir)/util/alloc.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/daemon.h \
$(srcdir)/services/modstack.h $(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.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/rtt.h $(srcdir)/validator/val_kcache.h
unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \
$(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/remote.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.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/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/mini_event.h \
- $(srcdir)/util/rbtree.h
+ $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.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/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
$(srcdir)/util/random.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/netevent.h $(srcdir)/util/alloc.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/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)/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 \
+ $(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)/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 \
$(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/libunbound/libworker.h
testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/testpkts.h \
$(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h \
- $(srcdir)/daemon/remote.h \
- $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c $(srcdir)/util/log.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
+ $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c \
+ $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/netevent.h $(srcdir)/util/alloc.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/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)/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 \
+ $(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)/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 \
$(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound.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
-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 $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/netevent.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 \
+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 \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.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)/edns-subnet/edns-subnet.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 \
$(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/services/localzone.h \
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.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 $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/worker.h \
- $(srcdir)/sldns/sbuffer.h $(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)/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)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.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 \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
+ $(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)/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)/util/storage/dnstree.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 \
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h \
-
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
perf.lo perf.o: $(srcdir)/testcode/perf.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
$(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
delayer.lo delayer.o: $(srcdir)/testcode/delayer.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
$(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
-unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h \
- $(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h
+unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h $(srcdir)/util/log.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h
unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/sldns/rrdef.h \
-
-petal.lo petal.o: $(srcdir)/testcode/petal.c config.h \
-
+ $(srcdir)/sldns/rrdef.h
+petal.lo petal.o: $(srcdir)/testcode/petal.c config.h
pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.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/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/netevent.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)/util/config_file.h $(srcdir)/util/winsock_event.h
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/winsock_event.h
w_inst.lo w_inst.o: $(srcdir)/winrc/w_inst.c config.h $(srcdir)/winrc/w_inst.h $(srcdir)/winrc/win_svc.h
unbound-service-install.lo unbound-service-install.o: $(srcdir)/winrc/unbound-service-install.c config.h \
$(srcdir)/winrc/w_inst.h
$(srcdir)/winrc/w_inst.h
anchor-update.lo anchor-update.o: $(srcdir)/winrc/anchor-update.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/wire2str.h
-keyraw.lo keyraw.o: $(srcdir)/sldns/keyraw.c config.h $(srcdir)/sldns/keyraw.h \
- $(srcdir)/sldns/rrdef.h \
-
+keyraw.lo keyraw.o: $(srcdir)/sldns/keyraw.c config.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/rrdef.h
sbuffer.lo sbuffer.o: $(srcdir)/sldns/sbuffer.c config.h $(srcdir)/sldns/sbuffer.h
wire2str.lo wire2str.o: $(srcdir)/sldns/wire2str.c config.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/keyraw.h \
-
+ $(srcdir)/sldns/keyraw.h
parse.lo parse.o: $(srcdir)/sldns/parse.c config.h $(srcdir)/sldns/parse.h $(srcdir)/sldns/parseutil.h \
$(srcdir)/sldns/sbuffer.h
parseutil.lo parseutil.o: $(srcdir)/sldns/parseutil.c config.h $(srcdir)/sldns/parseutil.h
strlcat.lo strlcat.o: $(srcdir)/compat/strlcat.c config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
strptime.lo strptime.o: $(srcdir)/compat/strptime.c config.h
-getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h \
-
+getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
--- /dev/null
+/* arc4_lock.c - global lock for arc4random
+*
+ * Copyright (c) 2014, 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.
+ */
+#include "config.h"
+#define LOCKRET(func) func
+#include "util/locks.h"
+
+void _ARC4_LOCK(void);
+void _ARC4_UNLOCK(void);
+
+#ifdef THREADS_DISABLED
+void _ARC4_LOCK(void)
+{
+}
+
+void _ARC4_UNLOCK(void)
+{
+}
+#else /* !THREADS_DISABLED */
+
+static lock_quick_t arc4lock;
+static int arc4lockinit = 0;
+
+void _ARC4_LOCK(void)
+{
+ if(!arc4lockinit) {
+ arc4lockinit = 1;
+ lock_quick_init(&arc4lock);
+ }
+ lock_quick_lock(&arc4lock);
+}
+
+void _ARC4_UNLOCK(void)
+{
+ lock_quick_unlock(&arc4lock);
+}
+#endif /* THREADS_DISABLED */
--- /dev/null
+/* $OpenBSD: arc4random.c,v 1.41 2014/07/12 13:24:54 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+
+/*
+ * ChaCha based random number generator for OpenBSD.
+ */
+
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#ifndef UB_ON_WINDOWS
+#include <sys/mman.h>
+#endif
+
+#define KEYSTREAM_ONLY
+#include "chacha_private.h"
+
+#define arc4_min(a, b) ((a) < (b) ? (a) : (b))
+#ifdef __GNUC__
+#define inline __inline
+#else /* !__GNUC__ */
+#define inline
+#endif /* !__GNUC__ */
+
+#define KEYSZ 32
+#define IVSZ 8
+#define BLOCKSZ 64
+#define RSBUFSZ (16*BLOCKSZ)
+
+/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
+static struct {
+ size_t rs_have; /* valid bytes at end of rs_buf */
+ size_t rs_count; /* bytes till reseed */
+} *rs;
+
+/* Preserved in fork children. */
+static struct {
+ chacha_ctx rs_chacha; /* chacha context for random keystream */
+ u_char rs_buf[RSBUFSZ]; /* keystream blocks */
+} *rsx;
+
+static inline void _rs_rekey(u_char *dat, size_t datlen);
+
+static inline void
+_rs_init(u_char *buf, size_t n)
+{
+ if (n < KEYSZ + IVSZ)
+ return;
+
+ if (rs == NULL) {
+#ifndef UB_ON_WINDOWS
+ if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+ abort();
+#ifdef MAP_INHERIT_ZERO
+ if (minherit(rs, sizeof(*rs), MAP_INHERIT_ZERO) == -1)
+ abort();
+#endif
+#else /* WINDOWS */
+ rs = malloc(sizeof(*rs));
+ if(!rs)
+ abort();
+#endif
+ }
+ if (rsx == NULL) {
+#ifndef UB_ON_WINDOWS
+ if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+ abort();
+#else /* WINDOWS */
+ rsx = malloc(sizeof(*rsx));
+ if(!rsx)
+ abort();
+#endif
+ }
+
+ chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
+ chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
+}
+
+static void
+_rs_stir(void)
+{
+ u_char rnd[KEYSZ + IVSZ];
+
+ if (getentropy(rnd, sizeof rnd) == -1) {
+#ifdef SIGKILL
+ raise(SIGKILL);
+#else
+ exit(9); /* windows */
+#endif
+ }
+
+ if (!rs)
+ _rs_init(rnd, sizeof(rnd));
+ else
+ _rs_rekey(rnd, sizeof(rnd));
+ explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
+
+ /* invalidate rs_buf */
+ rs->rs_have = 0;
+ memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
+
+ rs->rs_count = 1600000;
+}
+
+static inline void
+_rs_stir_if_needed(size_t len)
+{
+#ifndef MAP_INHERIT_ZERO
+ static pid_t _rs_pid = 0;
+ pid_t pid = getpid();
+
+ /* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */
+ if (_rs_pid == 0 || _rs_pid != pid) {
+ _rs_pid = pid;
+ if (rs)
+ rs->rs_count = 0;
+ }
+#endif
+ if (!rs || rs->rs_count <= len)
+ _rs_stir();
+ if (rs->rs_count <= len)
+ rs->rs_count = 0;
+ else
+ rs->rs_count -= len;
+}
+
+static inline void
+_rs_rekey(u_char *dat, size_t datlen)
+{
+#ifndef KEYSTREAM_ONLY
+ memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
+#endif
+ /* fill rs_buf with the keystream */
+ chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
+ rsx->rs_buf, sizeof(rsx->rs_buf));
+ /* mix in optional user provided data */
+ if (dat) {
+ size_t i, m;
+
+ m = arc4_min(datlen, KEYSZ + IVSZ);
+ for (i = 0; i < m; i++)
+ rsx->rs_buf[i] ^= dat[i];
+ }
+ /* immediately reinit for backtracking resistance */
+ _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
+ memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
+ rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
+}
+
+static inline void
+_rs_random_buf(void *_buf, size_t n)
+{
+ u_char *buf = (u_char *)_buf;
+ u_char *keystream;
+ size_t m;
+
+ _rs_stir_if_needed(n);
+ while (n > 0) {
+ if (rs->rs_have > 0) {
+ m = arc4_min(n, rs->rs_have);
+ keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
+ - rs->rs_have;
+ memcpy(buf, keystream, m);
+ memset(keystream, 0, m);
+ buf += m;
+ n -= m;
+ rs->rs_have -= m;
+ }
+ if (rs->rs_have == 0)
+ _rs_rekey(NULL, 0);
+ }
+}
+
+static inline void
+_rs_random_u32(uint32_t *val)
+{
+ u_char *keystream;
+ _rs_stir_if_needed(sizeof(*val));
+ if (rs->rs_have < sizeof(*val))
+ _rs_rekey(NULL, 0);
+ keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
+ memcpy(val, keystream, sizeof(*val));
+ memset(keystream, 0, sizeof(*val));
+ rs->rs_have -= sizeof(*val);
+}
+
+uint32_t
+arc4random(void)
+{
+ uint32_t val;
+
+ _ARC4_LOCK();
+ _rs_random_u32(&val);
+ _ARC4_UNLOCK();
+ return val;
+}
+
+void
+arc4random_buf(void *buf, size_t n)
+{
+ _ARC4_LOCK();
+ _rs_random_buf(buf, n);
+ _ARC4_UNLOCK();
+}
--- /dev/null
+/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <stdlib.h>
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound). This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+uint32_t
+arc4random_uniform(uint32_t upper_bound)
+{
+ uint32_t r, min;
+
+ if (upper_bound < 2)
+ return 0;
+
+ /* 2**32 % x == (2**32 - x) % x */
+ min = -upper_bound % upper_bound;
+
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = arc4random();
+ if (r >= min)
+ break;
+ }
+
+ return r % upper_bound;
+}
--- /dev/null
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
+typedef struct
+{
+ u32 input[16]; /* could be compressed */
+} chacha_ctx;
+
+#define U8C(v) (v##U)
+#define U32C(v) (v##U)
+
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+
+#define ROTL32(v, n) \
+ (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define U8TO32_LITTLE(p) \
+ (((u32)((p)[0]) ) | \
+ ((u32)((p)[1]) << 8) | \
+ ((u32)((p)[2]) << 16) | \
+ ((u32)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ (p)[2] = U8V((v) >> 16); \
+ (p)[3] = U8V((v) >> 24); \
+ } while (0)
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+static void
+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ATTR_UNUSED(ivbits))
+{
+ const char *constants;
+
+ x->input[4] = U8TO32_LITTLE(k + 0);
+ x->input[5] = U8TO32_LITTLE(k + 4);
+ x->input[6] = U8TO32_LITTLE(k + 8);
+ x->input[7] = U8TO32_LITTLE(k + 12);
+ if (kbits == 256) { /* recommended */
+ k += 16;
+ constants = sigma;
+ } else { /* kbits == 128 */
+ constants = tau;
+ }
+ x->input[8] = U8TO32_LITTLE(k + 0);
+ x->input[9] = U8TO32_LITTLE(k + 4);
+ x->input[10] = U8TO32_LITTLE(k + 8);
+ x->input[11] = U8TO32_LITTLE(k + 12);
+ x->input[0] = U8TO32_LITTLE(constants + 0);
+ x->input[1] = U8TO32_LITTLE(constants + 4);
+ x->input[2] = U8TO32_LITTLE(constants + 8);
+ x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *x,const u8 *iv)
+{
+ x->input[12] = 0;
+ x->input[13] = 0;
+ x->input[14] = U8TO32_LITTLE(iv + 0);
+ x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+static void
+chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
+{
+ u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+ u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+ u8 *ctarget = NULL;
+ u8 tmp[64];
+ u_int i;
+
+ if (!bytes) return;
+
+ j0 = x->input[0];
+ j1 = x->input[1];
+ j2 = x->input[2];
+ j3 = x->input[3];
+ j4 = x->input[4];
+ j5 = x->input[5];
+ j6 = x->input[6];
+ j7 = x->input[7];
+ j8 = x->input[8];
+ j9 = x->input[9];
+ j10 = x->input[10];
+ j11 = x->input[11];
+ j12 = x->input[12];
+ j13 = x->input[13];
+ j14 = x->input[14];
+ j15 = x->input[15];
+
+ for (;;) {
+ if (bytes < 64) {
+ for (i = 0;i < bytes;++i) tmp[i] = m[i];
+ m = tmp;
+ ctarget = c;
+ c = tmp;
+ }
+ x0 = j0;
+ x1 = j1;
+ x2 = j2;
+ x3 = j3;
+ x4 = j4;
+ x5 = j5;
+ x6 = j6;
+ x7 = j7;
+ x8 = j8;
+ x9 = j9;
+ x10 = j10;
+ x11 = j11;
+ x12 = j12;
+ x13 = j13;
+ x14 = j14;
+ x15 = j15;
+ for (i = 20;i > 0;i -= 2) {
+ QUARTERROUND( x0, x4, x8,x12)
+ QUARTERROUND( x1, x5, x9,x13)
+ QUARTERROUND( x2, x6,x10,x14)
+ QUARTERROUND( x3, x7,x11,x15)
+ QUARTERROUND( x0, x5,x10,x15)
+ QUARTERROUND( x1, x6,x11,x12)
+ QUARTERROUND( x2, x7, x8,x13)
+ QUARTERROUND( x3, x4, x9,x14)
+ }
+ x0 = PLUS(x0,j0);
+ x1 = PLUS(x1,j1);
+ x2 = PLUS(x2,j2);
+ x3 = PLUS(x3,j3);
+ x4 = PLUS(x4,j4);
+ x5 = PLUS(x5,j5);
+ x6 = PLUS(x6,j6);
+ x7 = PLUS(x7,j7);
+ x8 = PLUS(x8,j8);
+ x9 = PLUS(x9,j9);
+ x10 = PLUS(x10,j10);
+ x11 = PLUS(x11,j11);
+ x12 = PLUS(x12,j12);
+ x13 = PLUS(x13,j13);
+ x14 = PLUS(x14,j14);
+ x15 = PLUS(x15,j15);
+
+#ifndef KEYSTREAM_ONLY
+ x0 = XOR(x0,U8TO32_LITTLE(m + 0));
+ x1 = XOR(x1,U8TO32_LITTLE(m + 4));
+ x2 = XOR(x2,U8TO32_LITTLE(m + 8));
+ x3 = XOR(x3,U8TO32_LITTLE(m + 12));
+ x4 = XOR(x4,U8TO32_LITTLE(m + 16));
+ x5 = XOR(x5,U8TO32_LITTLE(m + 20));
+ x6 = XOR(x6,U8TO32_LITTLE(m + 24));
+ x7 = XOR(x7,U8TO32_LITTLE(m + 28));
+ x8 = XOR(x8,U8TO32_LITTLE(m + 32));
+ x9 = XOR(x9,U8TO32_LITTLE(m + 36));
+ x10 = XOR(x10,U8TO32_LITTLE(m + 40));
+ x11 = XOR(x11,U8TO32_LITTLE(m + 44));
+ x12 = XOR(x12,U8TO32_LITTLE(m + 48));
+ x13 = XOR(x13,U8TO32_LITTLE(m + 52));
+ x14 = XOR(x14,U8TO32_LITTLE(m + 56));
+ x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+#endif
+
+ j12 = PLUSONE(j12);
+ if (!j12) {
+ j13 = PLUSONE(j13);
+ /* stopping at 2^70 bytes per nonce is user's responsibility */
+ }
+
+ U32TO8_LITTLE(c + 0,x0);
+ U32TO8_LITTLE(c + 4,x1);
+ U32TO8_LITTLE(c + 8,x2);
+ U32TO8_LITTLE(c + 12,x3);
+ U32TO8_LITTLE(c + 16,x4);
+ U32TO8_LITTLE(c + 20,x5);
+ U32TO8_LITTLE(c + 24,x6);
+ U32TO8_LITTLE(c + 28,x7);
+ U32TO8_LITTLE(c + 32,x8);
+ U32TO8_LITTLE(c + 36,x9);
+ U32TO8_LITTLE(c + 40,x10);
+ U32TO8_LITTLE(c + 44,x11);
+ U32TO8_LITTLE(c + 48,x12);
+ U32TO8_LITTLE(c + 52,x13);
+ U32TO8_LITTLE(c + 56,x14);
+ U32TO8_LITTLE(c + 60,x15);
+
+ if (bytes <= 64) {
+ if (bytes < 64) {
+ for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+ }
+ x->input[12] = j12;
+ x->input[13] = j13;
+ return;
+ }
+ bytes -= 64;
+ c += 64;
+#ifndef KEYSTREAM_ONLY
+ m += 64;
+#endif
+ }
+}
--- /dev/null
+/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
+/*
+ * Public domain.
+ * Written by Matthew Dempsky.
+ */
+#include "config.h"
+#include <string.h>
+
+__attribute__((weak)) void
+__explicit_bzero_hook(void *ATTR_UNUSED(buf), size_t ATTR_UNUSED(len))
+{
+}
+
+void
+explicit_bzero(void *buf, size_t len)
+{
+#ifdef UB_ON_WINDOWS
+ SecureZeroMemory(buf, len);
+#endif
+ memset(buf, 0, len);
+ __explicit_bzero_hook(buf, len);
+}
--- /dev/null
+/* $OpenBSD: getentropy_linux.c,v 1.20 2014/07/12 15:43:49 beck Exp $ */
+
+/*
+ * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+ * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+
+/*
+#define _POSIX_C_SOURCE 199309L
+#define _GNU_SOURCE 1
+*/
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+#include <sys/statvfs.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <openssl/sha.h>
+
+#include <linux/types.h>
+#include <linux/random.h>
+#include <linux/sysctl.h>
+#ifdef HAVE_GETAUXVAL
+#include <sys/auxv.h>
+#endif
+#include <sys/vfs.h>
+
+#define REPEAT 5
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+ do { \
+ if ((a)) \
+ HD(errno); \
+ else \
+ HD(b); \
+ } while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int getentropy(void *buf, size_t len);
+
+#ifdef CAN_REFERENCE_MAIN
+extern int main(int, char *argv[]);
+#endif
+static int gotdata(char *buf, size_t len);
+#ifdef SYS_getrandom
+static int getentropy_getrandom(void *buf, size_t len);
+#endif
+static int getentropy_urandom(void *buf, size_t len);
+#ifdef SYS__sysctl
+static int getentropy_sysctl(void *buf, size_t len);
+#endif
+static int getentropy_fallback(void *buf, size_t len);
+
+int
+getentropy(void *buf, size_t len)
+{
+ int ret = -1;
+
+ if (len > 256) {
+ errno = EIO;
+ return -1;
+ }
+
+#ifdef SYS_getrandom
+ /*
+ * Try descriptor-less getrandom()
+ */
+ ret = getentropy_getrandom(buf, len);
+ if (ret != -1)
+ return (ret);
+ if (errno != ENOSYS)
+ return (-1);
+#endif
+
+ /*
+ * Try to get entropy with /dev/urandom
+ *
+ * This can fail if the process is inside a chroot or if file
+ * descriptors are exhausted.
+ */
+ ret = getentropy_urandom(buf, len);
+ if (ret != -1)
+ return (ret);
+
+#ifdef SYS__sysctl
+ /*
+ * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
+ * sysctl is a failsafe API, so it guarantees a result. This
+ * should work inside a chroot, or when file descriptors are
+ * exhuasted.
+ *
+ * However this can fail if the Linux kernel removes support
+ * for sysctl. Starting in 2007, there have been efforts to
+ * deprecate the sysctl API/ABI, and push callers towards use
+ * of the chroot-unavailable fd-using /proc mechanism --
+ * essentially the same problems as /dev/urandom.
+ *
+ * Numerous setbacks have been encountered in their deprecation
+ * schedule, so as of June 2014 the kernel ABI still exists on
+ * most Linux architectures. The sysctl() stub in libc is missing
+ * on some systems. There are also reports that some kernels
+ * spew messages to the console.
+ */
+ ret = getentropy_sysctl(buf, len);
+ if (ret != -1)
+ return (ret);
+#endif /* SYS__sysctl */
+
+ /*
+ * Entropy collection via /dev/urandom and sysctl have failed.
+ *
+ * No other API exists for collecting entropy. See the large
+ * comment block above.
+ *
+ * We have very few options:
+ * - Even syslog_r is unsafe to call at this low level, so
+ * there is no way to alert the user or program.
+ * - Cannot call abort() because some systems have unsafe
+ * corefiles.
+ * - Could raise(SIGKILL) resulting in silent program termination.
+ * - Return EIO, to hint that arc4random's stir function
+ * should raise(SIGKILL)
+ * - Do the best under the circumstances....
+ *
+ * This code path exists to bring light to the issue that Linux
+ * does not provide a failsafe API for entropy collection.
+ *
+ * We hope this demonstrates that Linux should either retain their
+ * sysctl ABI, or consider providing a new failsafe API which
+ * works in a chroot or when file descriptors are exhausted.
+ */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+ raise(SIGKILL);
+#endif
+ ret = getentropy_fallback(buf, len);
+ if (ret != -1)
+ return (ret);
+
+ errno = EIO;
+ return (ret);
+}
+
+/*
+ * Basic sanity checking; wish we could do better.
+ */
+static int
+gotdata(char *buf, size_t len)
+{
+ char any_set = 0;
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ any_set |= buf[i];
+ if (any_set == 0)
+ return -1;
+ return 0;
+}
+
+#ifdef SYS_getrandom
+static int
+getentropy_getrandom(void *buf, size_t len)
+{
+ int pre_errno = errno;
+ int ret;
+ if (len > 256)
+ return (-1);
+ do {
+ ret = syscall(SYS_getrandom, buf, len, 0);
+ } while (ret == -1 && errno == EINTR);
+
+ if (ret != (int)len)
+ return (-1);
+ errno = pre_errno;
+ return (0);
+}
+#endif
+
+static int
+getentropy_urandom(void *buf, size_t len)
+{
+ struct stat st;
+ size_t i;
+ int fd, cnt, flags;
+ int save_errno = errno;
+
+start:
+
+ flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+ flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
+ fd = open("/dev/urandom", flags, 0);
+ if (fd == -1) {
+ if (errno == EINTR)
+ goto start;
+ goto nodevrandom;
+ }
+#ifndef O_CLOEXEC
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+ /* Lightly verify that the device node looks sane */
+ if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+ close(fd);
+ goto nodevrandom;
+ }
+ if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
+ close(fd);
+ goto nodevrandom;
+ }
+ for (i = 0; i < len; ) {
+ size_t wanted = len - i;
+ ssize_t ret = read(fd, (char*)buf + i, wanted);
+
+ if (ret == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ close(fd);
+ goto nodevrandom;
+ }
+ i += ret;
+ }
+ close(fd);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return 0; /* satisfied */
+ }
+nodevrandom:
+ errno = EIO;
+ return -1;
+}
+
+#ifdef SYS__sysctl
+static int
+getentropy_sysctl(void *buf, size_t len)
+{
+ static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
+ size_t i;
+ int save_errno = errno;
+
+ for (i = 0; i < len; ) {
+ size_t chunk = min(len - i, 16);
+
+ /* SYS__sysctl because some systems already removed sysctl() */
+ struct __sysctl_args args = {
+ .name = mib,
+ .nlen = 3,
+ .oldval = (char *)buf + i,
+ .oldlenp = &chunk,
+ };
+ if (syscall(SYS__sysctl, &args) != 0)
+ goto sysctlfailed;
+ i += chunk;
+ }
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return (0); /* satisfied */
+ }
+sysctlfailed:
+ errno = EIO;
+ return -1;
+}
+#endif /* SYS__sysctl */
+
+static int cl[] = {
+ CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+ CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+ CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+ CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+ CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+ CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+ uint8_t results[SHA512_DIGEST_LENGTH];
+ int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+ static int cnt;
+ struct timespec ts;
+ struct timeval tv;
+ struct rusage ru;
+ sigset_t sigset;
+ struct stat st;
+ SHA512_CTX ctx;
+ static pid_t lastpid;
+ pid_t pid;
+ size_t i, ii, m;
+ char *p;
+
+ pid = getpid();
+ if (lastpid == pid) {
+ faster = 1;
+ repeat = 2;
+ } else {
+ faster = 0;
+ lastpid = pid;
+ repeat = REPEAT;
+ }
+ for (i = 0; i < len; ) {
+ int j;
+ SHA512_Init(&ctx);
+ for (j = 0; j < repeat; j++) {
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (int)tv.tv_sec;
+ cnt += (int)tv.tv_usec;
+ }
+
+ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+ HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
+ HX((pid = getpid()) == -1, pid);
+ HX((pid = getsid(pid)) == -1, pid);
+ HX((pid = getppid()) == -1, pid);
+ HX((pid = getpgid(0)) == -1, pid);
+ HX((e = getpriority(0, 0)) == -1, e);
+
+ if (!faster) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+ (void) nanosleep(&ts, NULL);
+ }
+
+ HX(sigpending(&sigset) == -1, sigset);
+ HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+ sigset);
+
+#ifdef CAN_REFERENCE_MAIN
+ HF(main); /* an addr in program */
+#endif
+ HF(getentropy); /* an addr in this library */
+ HF(printf); /* an addr in libc */
+ p = (char *)&p;
+ HD(p); /* an addr on stack */
+ p = (char *)&errno;
+ HD(p); /* the addr of errno */
+
+ if (i == 0) {
+ struct sockaddr_storage ss;
+ struct statvfs stvfs;
+ struct termios tios;
+ struct statfs stfs;
+ socklen_t ssl;
+ off_t off;
+
+ /*
+ * Prime-sized mappings encourage fragmentation;
+ * thus exposing some address entropy.
+ */
+ struct mm {
+ size_t npg;
+ void *p;
+ } mm[] = {
+ { 17, MAP_FAILED }, { 3, MAP_FAILED },
+ { 11, MAP_FAILED }, { 2, MAP_FAILED },
+ { 5, MAP_FAILED }, { 3, MAP_FAILED },
+ { 7, MAP_FAILED }, { 1, MAP_FAILED },
+ { 57, MAP_FAILED }, { 3, MAP_FAILED },
+ { 131, MAP_FAILED }, { 1, MAP_FAILED },
+ };
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ HX(mm[m].p = mmap(NULL,
+ mm[m].npg * pgs,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANON, -1,
+ (off_t)0), mm[m].p);
+ if (mm[m].p != MAP_FAILED) {
+ size_t mo;
+
+ /* Touch some memory... */
+ p = mm[m].p;
+ mo = cnt %
+ (mm[m].npg * pgs - 1);
+ p[mo] = 1;
+ cnt += (int)((long)(mm[m].p)
+ / pgs);
+ }
+
+ /* Check cnts and times... */
+ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+ ii++) {
+ HX((e = clock_gettime(cl[ii],
+ &ts)) == -1, ts);
+ if (e != -1)
+ cnt += (int)ts.tv_nsec;
+ }
+
+ HX((e = getrusage(RUSAGE_SELF,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (int)ru.ru_utime.tv_sec;
+ cnt += (int)ru.ru_utime.tv_usec;
+ }
+ }
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ if (mm[m].p != MAP_FAILED)
+ munmap(mm[m].p, mm[m].npg * pgs);
+ mm[m].p = MAP_FAILED;
+ }
+
+ HX(stat(".", &st) == -1, st);
+ HX(statvfs(".", &stvfs) == -1, stvfs);
+ HX(statfs(".", &stfs) == -1, stfs);
+
+ HX(stat("/", &st) == -1, st);
+ HX(statvfs("/", &stvfs) == -1, stvfs);
+ HX(statfs("/", &stfs) == -1, stfs);
+
+ HX((e = fstat(0, &st)) == -1, st);
+ if (e == -1) {
+ if (S_ISREG(st.st_mode) ||
+ S_ISFIFO(st.st_mode) ||
+ S_ISSOCK(st.st_mode)) {
+ HX(fstatvfs(0, &stvfs) == -1,
+ stvfs);
+ HX(fstatfs(0, &stfs) == -1,
+ stfs);
+ HX((off = lseek(0, (off_t)0,
+ SEEK_CUR)) < 0, off);
+ }
+ if (S_ISCHR(st.st_mode)) {
+ HX(tcgetattr(0, &tios) == -1,
+ tios);
+ } else if (S_ISSOCK(st.st_mode)) {
+ memset(&ss, 0, sizeof ss);
+ ssl = sizeof(ss);
+ HX(getpeername(0,
+ (void *)&ss, &ssl) == -1,
+ ss);
+ }
+ }
+
+ HX((e = getrusage(RUSAGE_CHILDREN,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (int)ru.ru_utime.tv_sec;
+ cnt += (int)ru.ru_utime.tv_usec;
+ }
+ } else {
+ /* Subsequent hashes absorb previous result */
+ HD(results);
+ }
+
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (int)tv.tv_sec;
+ cnt += (int)tv.tv_usec;
+ }
+
+ HD(cnt);
+ }
+#ifdef HAVE_GETAUXVAL
+# ifdef AT_RANDOM
+ /* Not as random as you think but we take what we are given */
+ p = (char *) getauxval(AT_RANDOM);
+ if (p)
+ HR(p, 16);
+# endif
+# ifdef AT_SYSINFO_EHDR
+ p = (char *) getauxval(AT_SYSINFO_EHDR);
+ if (p)
+ HR(p, pgs);
+# endif
+# ifdef AT_BASE
+ p = (char *) getauxval(AT_BASE);
+ if (p)
+ HD(p);
+# endif
+#endif /* HAVE_GETAUXVAL */
+
+ SHA512_Final(results, &ctx);
+ memcpy((char*)buf + i, results, min(sizeof(results), len - i));
+ i += min(sizeof(results), len - i);
+ }
+ memset(results, 0, sizeof results);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return 0; /* satisfied */
+ }
+ errno = EIO;
+ return -1;
+}
--- /dev/null
+/* $OpenBSD: getentropy_osx.c,v 1.3 2014/07/12 14:48:00 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+ * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/statvfs.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <mach/mach_time.h>
+#include <mach/mach_host.h>
+#include <mach/host_info.h>
+#include <sys/socketvar.h>
+#include <sys/vmmeter.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp_var.h>
+#include <netinet/udp_var.h>
+#include <CommonCrypto/CommonDigest.h>
+#define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c)))
+#define SHA512_Init(xxx) (CC_SHA512_Init((xxx)))
+#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy)))
+#define SHA512_CTX CC_SHA512_CTX
+#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
+
+#define REPEAT 5
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+ do { \
+ if ((a)) \
+ HD(errno); \
+ else \
+ HD(b); \
+ } while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int getentropy(void *buf, size_t len);
+
+#ifdef CAN_REFERENCE_MAIN
+extern int main(int, char *argv[]);
+#endif
+static int gotdata(char *buf, size_t len);
+static int getentropy_urandom(void *buf, size_t len);
+static int getentropy_fallback(void *buf, size_t len);
+
+int
+getentropy(void *buf, size_t len)
+{
+ int ret = -1;
+
+ if (len > 256) {
+ errno = EIO;
+ return -1;
+ }
+
+ /*
+ * Try to get entropy with /dev/urandom
+ *
+ * This can fail if the process is inside a chroot or if file
+ * descriptors are exhausted.
+ */
+ ret = getentropy_urandom(buf, len);
+ if (ret != -1)
+ return (ret);
+
+ /*
+ * Entropy collection via /dev/urandom and sysctl have failed.
+ *
+ * No other API exists for collecting entropy, and we have
+ * no failsafe way to get it on OSX that is not sensitive
+ * to resource exhaustion.
+ *
+ * We have very few options:
+ * - Even syslog_r is unsafe to call at this low level, so
+ * there is no way to alert the user or program.
+ * - Cannot call abort() because some systems have unsafe
+ * corefiles.
+ * - Could raise(SIGKILL) resulting in silent program termination.
+ * - Return EIO, to hint that arc4random's stir function
+ * should raise(SIGKILL)
+ * - Do the best under the circumstances....
+ *
+ * This code path exists to bring light to the issue that OSX
+ * does not provide a failsafe API for entropy collection.
+ *
+ * We hope this demonstrates that OSX should consider
+ * providing a new failsafe API which works in a chroot or
+ * when file descriptors are exhausted.
+ */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+ raise(SIGKILL);
+#endif
+ ret = getentropy_fallback(buf, len);
+ if (ret != -1)
+ return (ret);
+
+ errno = EIO;
+ return (ret);
+}
+
+/*
+ * Basic sanity checking; wish we could do better.
+ */
+static int
+gotdata(char *buf, size_t len)
+{
+ char any_set = 0;
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ any_set |= buf[i];
+ if (any_set == 0)
+ return -1;
+ return 0;
+}
+
+static int
+getentropy_urandom(void *buf, size_t len)
+{
+ struct stat st;
+ size_t i;
+ int fd, flags;
+ int save_errno = errno;
+
+start:
+
+ flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+ flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
+ fd = open("/dev/urandom", flags, 0);
+ if (fd == -1) {
+ if (errno == EINTR)
+ goto start;
+ goto nodevrandom;
+ }
+#ifndef O_CLOEXEC
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+ /* Lightly verify that the device node looks sane */
+ if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+ close(fd);
+ goto nodevrandom;
+ }
+ for (i = 0; i < len; ) {
+ size_t wanted = len - i;
+ ssize_t ret = read(fd, (char*)buf + i, wanted);
+
+ if (ret == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ close(fd);
+ goto nodevrandom;
+ }
+ i += ret;
+ }
+ close(fd);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return 0; /* satisfied */
+ }
+nodevrandom:
+ errno = EIO;
+ return -1;
+}
+
+static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
+static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
+static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
+static int kmib[] = { CTL_KERN, KERN_USRSTACK };
+static int hwmib[] = { CTL_HW, HW_USERMEM };
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+ uint8_t results[SHA512_DIGEST_LENGTH];
+ int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+ static int cnt;
+ struct timespec ts;
+ struct timeval tv;
+ struct rusage ru;
+ sigset_t sigset;
+ struct stat st;
+ SHA512_CTX ctx;
+ static pid_t lastpid;
+ pid_t pid;
+ size_t i, ii, m;
+ char *p;
+ struct tcpstat tcpstat;
+ struct udpstat udpstat;
+ struct ipstat ipstat;
+ u_int64_t mach_time;
+ unsigned int idata;
+ void *addr;
+
+ pid = getpid();
+ if (lastpid == pid) {
+ faster = 1;
+ repeat = 2;
+ } else {
+ faster = 0;
+ lastpid = pid;
+ repeat = REPEAT;
+ }
+ for (i = 0; i < len; ) {
+ int j;
+ SHA512_Init(&ctx);
+ for (j = 0; j < repeat; j++) {
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (int)tv.tv_sec;
+ cnt += (int)tv.tv_usec;
+ }
+
+ mach_time = mach_absolute_time();
+ HD(mach_time);
+
+ ii = sizeof(addr);
+ HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
+ &addr, &ii, NULL, 0) == -1, addr);
+
+ ii = sizeof(idata);
+ HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
+ &idata, &ii, NULL, 0) == -1, idata);
+
+ ii = sizeof(tcpstat);
+ HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
+ &tcpstat, &ii, NULL, 0) == -1, tcpstat);
+
+ ii = sizeof(udpstat);
+ HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
+ &udpstat, &ii, NULL, 0) == -1, udpstat);
+
+ ii = sizeof(ipstat);
+ HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
+ &ipstat, &ii, NULL, 0) == -1, ipstat);
+
+ HX((pid = getpid()) == -1, pid);
+ HX((pid = getsid(pid)) == -1, pid);
+ HX((pid = getppid()) == -1, pid);
+ HX((pid = getpgid(0)) == -1, pid);
+ HX((e = getpriority(0, 0)) == -1, e);
+
+ if (!faster) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+ (void) nanosleep(&ts, NULL);
+ }
+
+ HX(sigpending(&sigset) == -1, sigset);
+ HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+ sigset);
+
+#ifdef CAN_REFERENCE_MAIN
+ HF(main); /* an addr in program */
+#endif
+ HF(getentropy); /* an addr in this library */
+ HF(printf); /* an addr in libc */
+ p = (char *)&p;
+ HD(p); /* an addr on stack */
+ p = (char *)&errno;
+ HD(p); /* the addr of errno */
+
+ if (i == 0) {
+ struct sockaddr_storage ss;
+ struct statvfs stvfs;
+ struct termios tios;
+ struct statfs stfs;
+ socklen_t ssl;
+ off_t off;
+
+ /*
+ * Prime-sized mappings encourage fragmentation;
+ * thus exposing some address entropy.
+ */
+ struct mm {
+ size_t npg;
+ void *p;
+ } mm[] = {
+ { 17, MAP_FAILED }, { 3, MAP_FAILED },
+ { 11, MAP_FAILED }, { 2, MAP_FAILED },
+ { 5, MAP_FAILED }, { 3, MAP_FAILED },
+ { 7, MAP_FAILED }, { 1, MAP_FAILED },
+ { 57, MAP_FAILED }, { 3, MAP_FAILED },
+ { 131, MAP_FAILED }, { 1, MAP_FAILED },
+ };
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ HX(mm[m].p = mmap(NULL,
+ mm[m].npg * pgs,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANON, -1,
+ (off_t)0), mm[m].p);
+ if (mm[m].p != MAP_FAILED) {
+ size_t mo;
+
+ /* Touch some memory... */
+ p = mm[m].p;
+ mo = cnt %
+ (mm[m].npg * pgs - 1);
+ p[mo] = 1;
+ cnt += (int)((long)(mm[m].p)
+ / pgs);
+ }
+
+ /* Check cnts and times... */
+ mach_time = mach_absolute_time();
+ HD(mach_time);
+ cnt += (int)mach_time;
+
+ HX((e = getrusage(RUSAGE_SELF,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (int)ru.ru_utime.tv_sec;
+ cnt += (int)ru.ru_utime.tv_usec;
+ }
+ }
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ if (mm[m].p != MAP_FAILED)
+ munmap(mm[m].p, mm[m].npg * pgs);
+ mm[m].p = MAP_FAILED;
+ }
+
+ HX(stat(".", &st) == -1, st);
+ HX(statvfs(".", &stvfs) == -1, stvfs);
+ HX(statfs(".", &stfs) == -1, stfs);
+
+ HX(stat("/", &st) == -1, st);
+ HX(statvfs("/", &stvfs) == -1, stvfs);
+ HX(statfs("/", &stfs) == -1, stfs);
+
+ HX((e = fstat(0, &st)) == -1, st);
+ if (e == -1) {
+ if (S_ISREG(st.st_mode) ||
+ S_ISFIFO(st.st_mode) ||
+ S_ISSOCK(st.st_mode)) {
+ HX(fstatvfs(0, &stvfs) == -1,
+ stvfs);
+ HX(fstatfs(0, &stfs) == -1,
+ stfs);
+ HX((off = lseek(0, (off_t)0,
+ SEEK_CUR)) < 0, off);
+ }
+ if (S_ISCHR(st.st_mode)) {
+ HX(tcgetattr(0, &tios) == -1,
+ tios);
+ } else if (S_ISSOCK(st.st_mode)) {
+ memset(&ss, 0, sizeof ss);
+ ssl = sizeof(ss);
+ HX(getpeername(0,
+ (void *)&ss, &ssl) == -1,
+ ss);
+ }
+ }
+
+ HX((e = getrusage(RUSAGE_CHILDREN,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (int)ru.ru_utime.tv_sec;
+ cnt += (int)ru.ru_utime.tv_usec;
+ }
+ } else {
+ /* Subsequent hashes absorb previous result */
+ HD(results);
+ }
+
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (int)tv.tv_sec;
+ cnt += (int)tv.tv_usec;
+ }
+
+ HD(cnt);
+ }
+
+ SHA512_Final(results, &ctx);
+ memcpy((char*)buf + i, results, min(sizeof(results), len - i));
+ i += min(sizeof(results), len - i);
+ }
+ memset(results, 0, sizeof results);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return 0; /* satisfied */
+ }
+ errno = EIO;
+ return -1;
+}
--- /dev/null
+/* $OpenBSD: getentropy_solaris.c,v 1.3 2014/07/12 14:46:31 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
+ * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/statvfs.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/sha2.h>
+#define SHA512_Init SHA512Init
+#define SHA512_Update SHA512Update
+#define SHA512_Final SHA512Final
+
+#include <sys/vfs.h>
+#include <sys/statfs.h>
+#include <sys/loadavg.h>
+
+#define REPEAT 5
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+ do { \
+ if ((a)) \
+ HD(errno); \
+ else \
+ HD(b); \
+ } while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int getentropy(void *buf, size_t len);
+
+#ifdef CAN_REFERENCE_MAIN
+extern int main(int, char *argv[]);
+#endif
+static int gotdata(char *buf, size_t len);
+static int getentropy_urandom(void *buf, size_t len, const char *path,
+ int devfscheck);
+static int getentropy_fallback(void *buf, size_t len);
+
+int
+getentropy(void *buf, size_t len)
+{
+ int ret = -1;
+
+ if (len > 256) {
+ errno = EIO;
+ return -1;
+ }
+
+ /*
+ * Try to get entropy with /dev/urandom
+ *
+ * Solaris provides /dev/urandom as a symbolic link to
+ * /devices/pseudo/random@0:urandom which is provided by
+ * a devfs filesystem. Best practice is to use O_NOFOLLOW,
+ * so we must try the unpublished name directly.
+ *
+ * This can fail if the process is inside a chroot which lacks
+ * the devfs mount, or if file descriptors are exhausted.
+ */
+ ret = getentropy_urandom(buf, len,
+ "/devices/pseudo/random@0:urandom", 1);
+ if (ret != -1)
+ return (ret);
+
+ /*
+ * Unfortunately, chroot spaces on Solaris are sometimes setup
+ * with direct device node of the well-known /dev/urandom name
+ * (perhaps to avoid dragging all of devfs into the space).
+ *
+ * This can fail if the process is inside a chroot or if file
+ * descriptors are exhausted.
+ */
+ ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
+ if (ret != -1)
+ return (ret);
+
+ /*
+ * Entropy collection via /dev/urandom has failed.
+ *
+ * No other API exists for collecting entropy, and we have
+ * no failsafe way to get it on Solaris that is not sensitive
+ * to resource exhaustion.
+ *
+ * We have very few options:
+ * - Even syslog_r is unsafe to call at this low level, so
+ * there is no way to alert the user or program.
+ * - Cannot call abort() because some systems have unsafe
+ * corefiles.
+ * - Could raise(SIGKILL) resulting in silent program termination.
+ * - Return EIO, to hint that arc4random's stir function
+ * should raise(SIGKILL)
+ * - Do the best under the circumstances....
+ *
+ * This code path exists to bring light to the issue that Solaris
+ * does not provide a failsafe API for entropy collection.
+ *
+ * We hope this demonstrates that Solaris should consider
+ * providing a new failsafe API which works in a chroot or
+ * when file descriptors are exhausted.
+ */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+ raise(SIGKILL);
+#endif
+ ret = getentropy_fallback(buf, len);
+ if (ret != -1)
+ return (ret);
+
+ errno = EIO;
+ return (ret);
+}
+
+/*
+ * Basic sanity checking; wish we could do better.
+ */
+static int
+gotdata(char *buf, size_t len)
+{
+ char any_set = 0;
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ any_set |= buf[i];
+ if (any_set == 0)
+ return -1;
+ return 0;
+}
+
+static int
+getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
+{
+ struct stat st;
+ size_t i;
+ int fd, flags;
+ int save_errno = errno;
+
+start:
+
+ flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+ flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
+ fd = open(path, flags, 0);
+ if (fd == -1) {
+ if (errno == EINTR)
+ goto start;
+ goto nodevrandom;
+ }
+#ifndef O_CLOEXEC
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+ /* Lightly verify that the device node looks sane */
+ if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) ||
+ (devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) {
+ close(fd);
+ goto nodevrandom;
+ }
+ for (i = 0; i < len; ) {
+ size_t wanted = len - i;
+ ssize_t ret = read(fd, (char*)buf + i, wanted);
+
+ if (ret == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ close(fd);
+ goto nodevrandom;
+ }
+ i += ret;
+ }
+ close(fd);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return 0; /* satisfied */
+ }
+nodevrandom:
+ errno = EIO;
+ return -1;
+}
+
+static const int cl[] = {
+ CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+ CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+ CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+ CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+ CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+ CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+ uint8_t results[SHA512_DIGEST_LENGTH];
+ int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+ static int cnt;
+ struct timespec ts;
+ struct timeval tv;
+ double loadavg[3];
+ struct rusage ru;
+ sigset_t sigset;
+ struct stat st;
+ SHA512_CTX ctx;
+ static pid_t lastpid;
+ pid_t pid;
+ size_t i, ii, m;
+ char *p;
+
+ pid = getpid();
+ if (lastpid == pid) {
+ faster = 1;
+ repeat = 2;
+ } else {
+ faster = 0;
+ lastpid = pid;
+ repeat = REPEAT;
+ }
+ for (i = 0; i < len; ) {
+ int j;
+ SHA512_Init(&ctx);
+ for (j = 0; j < repeat; j++) {
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (int)tv.tv_sec;
+ cnt += (int)tv.tv_usec;
+ }
+
+ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+ HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
+ HX((pid = getpid()) == -1, pid);
+ HX((pid = getsid(pid)) == -1, pid);
+ HX((pid = getppid()) == -1, pid);
+ HX((pid = getpgid(0)) == -1, pid);
+ HX((e = getpriority(0, 0)) == -1, e);
+ HX((getloadavg(loadavg, 3) == -1), loadavg);
+
+ if (!faster) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1;
+ (void) nanosleep(&ts, NULL);
+ }
+
+ HX(sigpending(&sigset) == -1, sigset);
+ HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+ sigset);
+
+#ifdef CAN_REFERENCE_MAIN
+ HF(main); /* an addr in program */
+#endif
+ HF(getentropy); /* an addr in this library */
+ HF(printf); /* an addr in libc */
+ p = (char *)&p;
+ HD(p); /* an addr on stack */
+ p = (char *)&errno;
+ HD(p); /* the addr of errno */
+
+ if (i == 0) {
+ struct sockaddr_storage ss;
+ struct statvfs stvfs;
+ struct termios tios;
+ socklen_t ssl;
+ off_t off;
+
+ /*
+ * Prime-sized mappings encourage fragmentation;
+ * thus exposing some address entropy.
+ */
+ struct mm {
+ size_t npg;
+ void *p;
+ } mm[] = {
+ { 17, MAP_FAILED }, { 3, MAP_FAILED },
+ { 11, MAP_FAILED }, { 2, MAP_FAILED },
+ { 5, MAP_FAILED }, { 3, MAP_FAILED },
+ { 7, MAP_FAILED }, { 1, MAP_FAILED },
+ { 57, MAP_FAILED }, { 3, MAP_FAILED },
+ { 131, MAP_FAILED }, { 1, MAP_FAILED },
+ };
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ HX(mm[m].p = mmap(NULL,
+ mm[m].npg * pgs,
+ PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANON, -1,
+ (off_t)0), mm[m].p);
+ if (mm[m].p != MAP_FAILED) {
+ size_t mo;
+
+ /* Touch some memory... */
+ p = mm[m].p;
+ mo = cnt %
+ (mm[m].npg * pgs - 1);
+ p[mo] = 1;
+ cnt += (int)((long)(mm[m].p)
+ / pgs);
+ }
+
+ /* Check cnts and times... */
+ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+ ii++) {
+ HX((e = clock_gettime(cl[ii],
+ &ts)) == -1, ts);
+ if (e != -1)
+ cnt += (int)ts.tv_nsec;
+ }
+
+ HX((e = getrusage(RUSAGE_SELF,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (int)ru.ru_utime.tv_sec;
+ cnt += (int)ru.ru_utime.tv_usec;
+ }
+ }
+
+ for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+ if (mm[m].p != MAP_FAILED)
+ munmap(mm[m].p, mm[m].npg * pgs);
+ mm[m].p = MAP_FAILED;
+ }
+
+ HX(stat(".", &st) == -1, st);
+ HX(statvfs(".", &stvfs) == -1, stvfs);
+
+ HX(stat("/", &st) == -1, st);
+ HX(statvfs("/", &stvfs) == -1, stvfs);
+
+ HX((e = fstat(0, &st)) == -1, st);
+ if (e == -1) {
+ if (S_ISREG(st.st_mode) ||
+ S_ISFIFO(st.st_mode) ||
+ S_ISSOCK(st.st_mode)) {
+ HX(fstatvfs(0, &stvfs) == -1,
+ stvfs);
+ HX((off = lseek(0, (off_t)0,
+ SEEK_CUR)) < 0, off);
+ }
+ if (S_ISCHR(st.st_mode)) {
+ HX(tcgetattr(0, &tios) == -1,
+ tios);
+ } else if (S_ISSOCK(st.st_mode)) {
+ memset(&ss, 0, sizeof ss);
+ ssl = sizeof(ss);
+ HX(getpeername(0,
+ (void *)&ss, &ssl) == -1,
+ ss);
+ }
+ }
+
+ HX((e = getrusage(RUSAGE_CHILDREN,
+ &ru)) == -1, ru);
+ if (e != -1) {
+ cnt += (int)ru.ru_utime.tv_sec;
+ cnt += (int)ru.ru_utime.tv_usec;
+ }
+ } else {
+ /* Subsequent hashes absorb previous result */
+ HD(results);
+ }
+
+ HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+ if (e != -1) {
+ cnt += (int)tv.tv_sec;
+ cnt += (int)tv.tv_usec;
+ }
+
+ HD(cnt);
+ }
+ SHA512_Final(results, &ctx);
+ memcpy((char*)buf + i, results, min(sizeof(results), len - i));
+ i += min(sizeof(results), len - i);
+ }
+ memset(results, 0, sizeof results);
+ if (gotdata(buf, len) == 0) {
+ errno = save_errno;
+ return 0; /* satisfied */
+ }
+ errno = EIO;
+ return -1;
+}
--- /dev/null
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
+ * Copyright (c) 2014, Bob Beck <beck@obtuse.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <windows.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <wincrypt.h>
+#include <process.h>
+
+int getentropy(void *buf, size_t len);
+
+/*
+ * On Windows, CryptGenRandom is supposed to be a well-seeded
+ * cryptographically strong random number generator.
+ */
+int
+getentropy(void *buf, size_t len)
+{
+ HCRYPTPROV provider;
+
+ if (len > 256) {
+ errno = EIO;
+ return -1;
+ }
+
+ if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT) == 0)
+ goto fail;
+ if (CryptGenRandom(provider, len, buf) == 0) {
+ CryptReleaseContext(provider, 0);
+ goto fail;
+ }
+ CryptReleaseContext(provider, 0);
+ return (0);
+
+fail:
+ errno = EIO;
+ return (-1);
+}
--- /dev/null
+/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */
+/*
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *optr, size_t nmemb, size_t size)
+{
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return realloc(optr, size * nmemb);
+}
--- /dev/null
+/*
+ * FILE: sha2.c
+ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Modified by Jelte Jansen to fit in ldns, and not clash with any
+ * system-defined SHA code.
+ * Changes:
+ * - Renamed (external) functions and constants to fit ldns style
+ * - Removed _End and _Data functions
+ * - Added ldns_shaX(data, len, digest) convenience functions
+ * - Removed prototypes of _Transform functions and made those static
+ * Modified by Wouter, and trimmed, to provide SHA512 for getentropy_fallback.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``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 AUTHOR OR CONTRIBUTOR(S) 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.
+ *
+ * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
+ */
+#include "config.h"
+
+#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */
+#include <assert.h> /* assert() */
+
+/* do we have sha512 header defs */
+#ifndef SHA512_DIGEST_LENGTH
+#define SHA512_BLOCK_LENGTH 128
+#define SHA512_DIGEST_LENGTH 64
+#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
+typedef struct _SHA512_CTX {
+ uint64_t state[8];
+ uint64_t bitcount[2];
+ uint8_t buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+#endif /* do we have sha512 header defs */
+
+void SHA512_Init(SHA512_CTX*);
+void SHA512_Update(SHA512_CTX*, void*, size_t);
+void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
+unsigned char *SHA512(void *data, unsigned int data_len, unsigned char *digest);
+
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER. If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ * #define LITTLE_ENDIAN 1234
+ * #define BIG_ENDIAN 4321
+ *
+ * And for little-endian machines, add:
+ *
+ * #define BYTE_ORDER LITTLE_ENDIAN
+ *
+ * Or for big-endian machines:
+ *
+ * #define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+
+typedef uint8_t sha2_byte; /* Exactly 1 byte */
+typedef uint32_t sha2_word32; /* Exactly 4 bytes */
+#ifdef S_SPLINT_S
+typedef unsigned long long sha2_word64; /* lint 8 bytes */
+#else
+typedef uint64_t sha2_word64; /* Exactly 8 bytes */
+#endif
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x) { \
+ sha2_word32 tmp = (w); \
+ tmp = (tmp >> 16) | (tmp << 16); \
+ (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#ifndef S_SPLINT_S
+#define REVERSE64(w,x) { \
+ sha2_word64 tmp = (w); \
+ tmp = (tmp >> 32) | (tmp << 32); \
+ tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+ ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+ ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#else /* splint */
+#define REVERSE64(w,x) /* splint */
+#endif /* splint */
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n) { \
+ (w)[0] += (sha2_word64)(n); \
+ if ((w)[0] < (n)) { \
+ (w)[1]++; \
+ } \
+}
+#ifdef S_SPLINT_S
+#undef ADDINC128
+#define ADDINC128(w,n) /* splint */
+#endif
+
+/*
+ * Macros for copying blocks of memory and for zeroing out ranges
+ * of memory. Using these macros makes it easy to switch from
+ * using memset()/memcpy() and using bzero()/bcopy().
+ *
+ * Please define either SHA2_USE_MEMSET_MEMCPY or define
+ * SHA2_USE_BZERO_BCOPY depending on which function set you
+ * choose to use:
+ */
+#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
+/* Default to memset()/memcpy() if no option is specified */
+#define SHA2_USE_MEMSET_MEMCPY 1
+#endif
+#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
+/* Abort with an error if BOTH options are defined */
+#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
+#endif
+
+#ifdef SHA2_USE_MEMSET_MEMCPY
+#define MEMSET_BZERO(p,l) memset((p), 0, (l))
+#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l))
+#endif
+#ifdef SHA2_USE_BZERO_BCOPY
+#define MEMSET_BZERO(p,l) bzero((p), (l))
+#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l))
+#endif
+
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ * NOTE: The naming of R and S appears backwards here (R is a SHIFT and
+ * S is a ROTATION) because the SHA-256/384/512 description document
+ * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ * same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) ((x) >> (b))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
+#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-384 and SHA-512: */
+static const sha2_word64 K512[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* initial hash value H for SHA-512 */
+static const sha2_word64 sha512_initial_hash_value[8] = {
+ 0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL
+};
+
+typedef union _ldns_sha2_buffer_union {
+ uint8_t* theChars;
+ uint64_t* theLongs;
+} ldns_sha2_buffer_union;
+
+/*** SHA-512: *********************************************************/
+void SHA512_Init(SHA512_CTX* context) {
+ if (context == (SHA512_CTX*)0) {
+ return;
+ }
+ MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
+ MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH);
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+static void SHA512_Transform(SHA512_CTX* context,
+ const sha2_word64* data) {
+ sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer;
+ int j;
+
+ /* initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert TO host byte order */
+ REVERSE64(*data++, W512[j]);
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-512 compression function to update a..h with copy */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W512[(j+1)&0x0f];
+ s0 = sigma0_512(s0);
+ s1 = W512[(j+14)&0x0f];
+ s1 = sigma1_512(s1);
+
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+void SHA512_Update(SHA512_CTX* context, void *datain, size_t len) {
+ size_t freespace, usedspace;
+ const sha2_byte* data = (const sha2_byte*)datain;
+
+ if (len == 0) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
+
+ usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = SHA512_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+ ADDINC128(context->bitcount, freespace << 3);
+ len -= freespace;
+ data += freespace;
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+ } else {
+ /* The buffer is not yet full */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+ ADDINC128(context->bitcount, len << 3);
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return;
+ }
+ }
+ while (len >= SHA512_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ SHA512_Transform(context, (sha2_word64*)data);
+ ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
+ len -= SHA512_BLOCK_LENGTH;
+ data += SHA512_BLOCK_LENGTH;
+ }
+ if (len > 0) {
+ /* There's left-overs, so save 'em */
+ MEMCPY_BCOPY(context->buffer, data, len);
+ ADDINC128(context->bitcount, len << 3);
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+}
+
+static void SHA512_Last(SHA512_CTX* context) {
+ size_t usedspace;
+ ldns_sha2_buffer_union cast_var;
+
+ usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(context->bitcount[0],context->bitcount[0]);
+ REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ context->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < SHA512_BLOCK_LENGTH) {
+ MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
+ }
+ /* Do second-to-last transform: */
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+
+ /* And set-up for the last transform: */
+ MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
+ }
+ } else {
+ /* Prepare for final transform: */
+ MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *context->buffer = 0x80;
+ }
+ /* Store the length of input data (in bits): */
+ cast_var.theChars = context->buffer;
+ cast_var.theLongs[SHA512_SHORT_BLOCK_LENGTH / 8] = context->bitcount[1];
+ cast_var.theLongs[SHA512_SHORT_BLOCK_LENGTH / 8 + 1] = context->bitcount[0];
+
+ /* final transform: */
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+}
+
+void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+ sha2_word64 *d = (sha2_word64*)digest;
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (sha2_byte*)0) {
+ SHA512_Last(context);
+
+ /* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE64(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
+#endif
+ }
+
+ /* Zero out state data */
+ MEMSET_BZERO(context, sizeof(SHA512_CTX));
+}
+
+unsigned char *
+SHA512(void *data, unsigned int data_len, unsigned char *digest)
+{
+ SHA512_CTX ctx;
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, data, data_len);
+ SHA512_Final(digest, &ctx);
+ return digest;
+}
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2014-03-23'
+timestamp='2013-06-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
LIBC=gnu
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
;;
esac
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
- *:MSYS*:*)
+ i*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
;;
- openrisc*:Linux:*:*)
- echo or1k-unknown-linux-${LIBC}
+ or1k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
- or32:Linux:*:* | or1k*:Linux:*:*)
+ or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
padre:Linux:*:*)
if test "$UNAME_PROCESSOR" = unknown ; then
UNAME_PROCESSOR=powerpc
fi
- if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
fi
- elif test "$UNAME_PROCESSOR" = i386 ; then
- # Avoid executing cc on OS X 10.9, as it ships with a stub
- # that puts up a graphical alert prompting to install
- # developer tools. Any system running Mac OS X 10.7 or
- # later (Darwin 11 and later) is required to have a 64-bit
- # processor. This is not true of the ARM version of Darwin
- # that Apple uses in portable devices.
- UNAME_PROCESSOR=x86_64
fi
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
exit ;;
exit ;;
esac
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
cat >&2 <<EOF
$0: unable to guess system type
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2014 Free Software Foundation, Inc.
+# Copyright 1992-2013 Free Software Foundation, Inc.
-timestamp='2014-09-11'
+timestamp='2013-08-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2014 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
- | k1om \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipsr5900 | mipsr5900el \
| nds32 | nds32le | nds32be \
| nios | nios2 | nios2eb | nios2el \
| ns16k | ns32k \
- | open8 | or1k | or1knd | or32 \
+ | open8 \
+ | or1k | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
- | riscv32 | riscv64 \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
c6x)
basic_machine=tic6x-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
- | k1om-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa32r6-* | mipsisa32r6el-* \
| mipsisa64-* | mipsisa64el-* \
| mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64r6-* | mipsisa64r6el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipsr5900-* | mipsr5900el-* \
| nios-* | nios2-* | nios2eb-* | nios2el-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
- | or1k*-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
basic_machine=powerpc-unknown
os=-morphos
;;
- moxiebox)
- basic_machine=moxie-unknown
- os=-moxiebox
- ;;
msdos)
basic_machine=i386-pc
os=-msdos
;;
ppc64) basic_machine=powerpc64-unknown
;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little | ppc64-le | powerpc64-little)
basic_machine=powerpc64le-unknown
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
mips*-*)
os=-elf
;;
+ or1k-*)
+ os=-elf
+ ;;
or32-*)
os=-coff
;;
--- /dev/null
+--- unbound-1.4.17.orig/doc/unbound.conf.5.in
++++ unbound-1.4.17/doc/unbound.conf.5.in
+@@ -519,6 +519,13 @@ authority servers and checks if the repl
+ Disabled by default.
+ This feature is an experimental implementation of draft dns\-0x20.
+ .TP
++.B aaaa\-filter: \fI<yes or no>
++Activate behavior similar to BIND's AAAA-filter.
++This forces the dropping of all AAAA records, unless in the case of
++explicit AAAA queries, when no A records have been confirmed.
++This also causes an additional A query to be sent for each AAAA query.
++This breaks DNSSEC!
++.TP
+ .B private\-address: \fI<IP address or subnet>
+ Give IPv4 of IPv6 addresses or classless subnets. These are addresses
+ on your private network, and are not allowed to be returned for public
+--- unbound-1.4.17.orig/util/config_file.c
++++ unbound-1.4.17/util/config_file.c
+@@ -160,6 +160,7 @@ config_create(void)
+ cfg->harden_below_nxdomain = 0;
+ cfg->harden_referral_path = 0;
+ cfg->use_caps_bits_for_id = 0;
++ cfg->aaaa_filter = 0; /* ASN: default is disabled */
+ cfg->private_address = NULL;
+ cfg->private_domain = NULL;
+ cfg->unwanted_threshold = 0;
+--- unbound-1.4.17.orig/iterator/iter_scrub.c
++++ unbound-1.4.17/iterator/iter_scrub.c
+@@ -580,6 +580,32 @@ static int sanitize_nsec_is_overreach(st
+ }
+
+ /**
++ * ASN: Lookup A records from rrset cache.
++ * @param qinfo: the question originally asked.
++ * @param env: module environment with config and cache.
++ * @param ie: iterator environment with private address data.
++ * @return 0 if no A record found, 1 if A record found.
++ */
++static int
++asn_lookup_a_record_from_cache(struct query_info* qinfo,
++ struct module_env* env, struct iter_env* ie)
++{
++ struct ub_packed_rrset_key* akey;
++
++ /* get cached A records for queried name */
++ akey = rrset_cache_lookup(env->rrset_cache, qinfo->qname,
++ qinfo->qname_len, LDNS_RR_TYPE_A, qinfo->qclass,
++ 0, *env->now, 0);
++ if(akey) { /* we had some. */
++ log_rrset_key(VERB_ALGO, "ASN-AAAA-filter: found A record",
++ akey);
++ lock_rw_unlock(&akey->entry.lock);
++ return 1;
++ }
++ return 0;
++}
++
++/**
+ * Given a response event, remove suspect RRsets from the response.
+ * "Suspect" rrsets are potentially poison. Note that this routine expects
+ * the response to be in a "normalized" state -- that is, all "irrelevant"
+@@ -598,6 +625,7 @@ scrub_sanitize(ldns_buffer* pkt, struct
+ struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
+ struct iter_env* ie)
+ {
++ int found_a_record = 0; /* ASN: do we have a A record? */
+ int del_addi = 0; /* if additional-holding rrsets are deleted, we
+ do not trust the normalized additional-A-AAAA any more */
+ struct rrset_parse* rrset, *prev;
+@@ -633,6 +661,13 @@ scrub_sanitize(ldns_buffer* pkt, struct
+ rrset = rrset->rrset_all_next;
+ }
+
++ /* ASN: Locate any A record we can find */
++ if((ie->aaaa_filter) && (qinfo->qtype == LDNS_RR_TYPE_AAAA)) {
++ found_a_record = asn_lookup_a_record_from_cache(qinfo,
++ env, ie);
++ }
++ /* ASN: End of added code */
++
+ /* At this point, we brutally remove ALL rrsets that aren't
+ * children of the originating zone. The idea here is that,
+ * as far as we know, the server that we contacted is ONLY
+@@ -644,6 +679,24 @@ scrub_sanitize(ldns_buffer* pkt, struct
+ rrset = msg->rrset_first;
+ while(rrset) {
+
++ /* ASN: For AAAA records only... */
++ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
++ /* ASN: If this is not a AAAA query, then remove AAAA
++ * records, no questions asked. If this IS a AAAA query
++ * then remove AAAA records if we have an A record.
++ * Otherwise, leave things be. */
++ if((qinfo->qtype != LDNS_RR_TYPE_AAAA) ||
++ (found_a_record)) {
++ remove_rrset("ASN-AAAA-filter: removing AAAA "
++ "for record", pkt, msg, prev, &rrset);
++ continue;
++ }
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: "
++ "keep AAAA for", zonename,
++ LDNS_RR_TYPE_AAAA, qinfo->qclass);
++ }
++ /* ASN: End of added code */
++
+ /* remove private addresses */
+ if( (rrset->type == LDNS_RR_TYPE_A ||
+ rrset->type == LDNS_RR_TYPE_AAAA) &&
+--- unbound-1.4.17.orig/iterator/iterator.c
++++ unbound-1.4.17/iterator/iterator.c
+@@ -1579,6 +1579,53 @@ processDSNSFind(struct module_qstate* qs
+
+ return 0;
+ }
++
++/**
++ * ASN: This event state was added as an intermediary step between
++ * QUERYTARGETS_STATE and the next step, in order to cast a subquery for the
++ * purpose of caching A records for the queried name.
++ *
++ * @param qstate: query state.
++ * @param iq: iterator query state.
++ * @param ie: iterator shared global environment.
++ * @param id: module id.
++ * @return true if the event requires more request processing immediately,
++ * false if not. This state only returns true when it is generating
++ * a SERVFAIL response because the query has hit a dead end.
++ */
++static int
++asn_processQueryAAAA(struct module_qstate* qstate, struct iter_qstate* iq,
++ struct iter_env* ie, int id)
++{
++ struct module_qstate* subq = NULL;
++
++ log_assert(iq->fetch_a_for_aaaa == 0);
++
++ /* flag the query properly in order to not loop */
++ iq->fetch_a_for_aaaa = 1;
++
++ /* re-throw same query, but with a different type */
++ if(!generate_sub_request(iq->qchase.qname,
++ iq->qchase.qname_len, LDNS_RR_TYPE_A,
++ iq->qchase.qclass, qstate, id, iq,
++ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: failed "
++ "preloading of A record for",
++ iq->qchase.qname, LDNS_RR_TYPE_A,
++ iq->qchase.qclass);
++ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
++ }
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: "
++ "preloading records in cache for",
++ iq->qchase.qname, LDNS_RR_TYPE_A,
++ iq->qchase.qclass);
++
++ /* set this query as waiting */
++ qstate->ext_state[id] = module_wait_subquery;
++ /* at this point break loop */
++ return 0;
++}
++/* ASN: End of added code */
+
+ /**
+ * This is the request event state where the request will be sent to one of
+@@ -1626,6 +1673,13 @@ processQueryTargets(struct module_qstate
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+
++ /* ASN: If we have a AAAA query, then also query for A records */
++ if((ie->aaaa_filter) && (iq->qchase.qtype == LDNS_RR_TYPE_AAAA) &&
++ (iq->fetch_a_for_aaaa == 0)) {
++ return next_state(iq, ASN_FETCH_A_FOR_AAAA_STATE);
++ }
++ /* ASN: End of added code */
++
+ /* Make sure we have a delegation point, otherwise priming failed
+ * or another failure occurred */
+ if(!iq->dp) {
+@@ -2568,6 +2622,62 @@ processFinished(struct module_qstate* qs
+ return 0;
+ }
+
++/**
++ * ASN: Do final processing on responses to A queries originated from AAAA
++ * queries. Events reach this state after the iterative resolution algorithm
++ * terminates.
++ * This is required down the road to decide whether to scrub AAAA records
++ * from the results or not.
++ *
++ * @param qstate: query state.
++ * @param id: module id.
++ * @param forq: super query state.
++ */
++static void
++asn_processAAAAResponse(struct module_qstate* qstate, int id,
++ struct module_qstate* super)
++{
++ struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
++ struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id];
++ struct ub_packed_rrset_key* rrset;
++ struct delegpt_ns* dpns = NULL;
++ int error = (qstate->return_rcode != LDNS_RCODE_NOERROR);
++
++ log_assert(super_iq->fetch_a_for_aaaa > 0);
++
++ /* let super go to evaluation of targets after this */
++ super_iq->state = QUERYTARGETS_STATE;
++
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: processAAAAResponse",
++ &qstate->qinfo);
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: processAAAAResponse super",
++ &super->qinfo);
++
++ if(super_iq->dp)
++ dpns = delegpt_find_ns(super_iq->dp,
++ qstate->qinfo.qname, qstate->qinfo.qname_len);
++ if (!dpns) {
++ /* not interested */
++ verbose(VERB_ALGO, "ASN-AAAA-filter: subq: %s, but parent not "
++ "interested%s", (error ? "error, but" : "success"),
++ (super_iq->dp ? "anymore" : " (was reset)"));
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: superq", &super->qinfo);
++ if(super_iq->dp && error)
++ delegpt_log(VERB_ALGO, super_iq->dp);
++ return;
++ } else if (error) {
++ verbose(VERB_ALGO, "ASN-AAAA-filter: mark as failed, "
++ "and go to target query.");
++ /* see if the failure did get (parent-lame) info */
++ if(!cache_fill_missing(super->env,
++ super_iq->qchase.qclass, super->region,
++ super_iq->dp))
++ log_err("ASN-AAAA-filter: out of memory adding missing");
++ dpns->resolved = 1; /* mark as failed */
++ }
++}
++/* ASN: End of added code */
++
+ /*
+ * Return priming query results to interestes super querystates.
+ *
+@@ -2587,6 +2697,9 @@ iter_inform_super(struct module_qstate*
+ else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
+ super->minfo[id])->state == DSNS_FIND_STATE)
+ processDSNSResponse(qstate, id, super);
++ else if (super->qinfo.qtype == LDNS_RR_TYPE_AAAA && ((struct iter_qstate*)
++ super->minfo[id])->state == ASN_FETCH_A_FOR_AAAA_STATE)
++ asn_processAAAAResponse(qstate, id, super);
+ else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
+ error_supers(qstate, id, super);
+ else if(qstate->is_priming)
+@@ -2624,6 +2737,9 @@ iter_handle(struct module_qstate* qstate
+ case INIT_REQUEST_3_STATE:
+ cont = processInitRequest3(qstate, iq, id);
+ break;
++ case ASN_FETCH_A_FOR_AAAA_STATE:
++ cont = asn_processQueryAAAA(qstate, iq, ie, id);
++ break;
+ case QUERYTARGETS_STATE:
+ cont = processQueryTargets(qstate, iq, ie, id);
+ break;
+@@ -2863,6 +2979,8 @@ iter_state_to_string(enum iter_state sta
+ return "INIT REQUEST STATE (stage 2)";
+ case INIT_REQUEST_3_STATE:
+ return "INIT REQUEST STATE (stage 3)";
++ case ASN_FETCH_A_FOR_AAAA_STATE:
++ return "ASN_FETCH_A_FOR_AAAA_STATE";
+ case QUERYTARGETS_STATE :
+ return "QUERY TARGETS STATE";
+ case PRIME_RESP_STATE :
+@@ -2887,6 +3005,7 @@ iter_state_is_responsestate(enum iter_st
+ case INIT_REQUEST_STATE :
+ case INIT_REQUEST_2_STATE :
+ case INIT_REQUEST_3_STATE :
++ case ASN_FETCH_A_FOR_AAAA_STATE :
+ case QUERYTARGETS_STATE :
+ case COLLECT_CLASS_STATE :
+ return 0;
+--- unbound-1.4.17.orig/iterator/iter_utils.c
++++ unbound-1.4.17/iterator/iter_utils.c
+@@ -128,6 +128,7 @@ iter_apply_cfg(struct iter_env* iter_env
+ }
+ iter_env->supports_ipv6 = cfg->do_ip6;
+ iter_env->supports_ipv4 = cfg->do_ip4;
++ iter_env->aaaa_filter = cfg->aaaa_filter;
+ return 1;
+ }
+
+--- unbound-1.4.17.orig/iterator/iterator.h
++++ unbound-1.4.17/iterator/iterator.h
+@@ -110,6 +110,9 @@ struct iter_env {
+ * array of max_dependency_depth+1 size.
+ */
+ int* target_fetch_policy;
++
++ /** ASN: AAAA-filter flag */
++ int aaaa_filter;
+ };
+
+ /**
+@@ -135,6 +138,14 @@ enum iter_state {
+ INIT_REQUEST_3_STATE,
+
+ /**
++ * This state is responsible for intercepting AAAA queries,
++ * and launch a A subquery on the same target, to populate the
++ * cache with A records, so the AAAA filter scrubbing logic can
++ * work.
++ */
++ ASN_FETCH_A_FOR_AAAA_STATE,
++
++ /**
+ * Each time a delegation point changes for a given query or a
+ * query times out and/or wakes up, this state is (re)visited.
+ * This state is reponsible for iterating through a list of
+@@ -309,6 +320,13 @@ struct iter_qstate {
+ */
+ int refetch_glue;
+
++ /**
++ * ASN: This is a flag that, if true, means that this query is
++ * for fetching A records to populate cache and determine if we must
++ * return AAAA records or not.
++ */
++ int fetch_a_for_aaaa;
++
+ /** list of pending queries to authoritative servers. */
+ struct outbound_list outlist;
+ };
+--- unbound-1.4.17.orig/util/config_file.h
++++ unbound-1.4.17/util/config_file.h
+@@ -169,6 +169,8 @@ struct config_file {
+ int harden_referral_path;
+ /** use 0x20 bits in query as random ID bits */
+ int use_caps_bits_for_id;
++ /** ASN: enable AAAA filter? */
++ int aaaa_filter;
+ /** strip away these private addrs from answers, no DNS Rebinding */
+ struct config_strlist* private_address;
+ /** allow domain (and subdomains) to use private address space */
+--- unbound-1.4.17.orig/util/configlexer.lex
++++ unbound-1.4.17/util/configlexer.lex
+@@ -177,6 +177,7 @@ harden-below-nxdomain{COLON} { YDVAR(1,
+ harden-referral-path{COLON} { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) }
+ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
+ unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
++aaaa-filter{COLON} { YDVAR(1, VAR_AAAA_FILTER) }
+ private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) }
+ private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
+ prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
+--- unbound-1.4.17.orig/util/configparser.y
++++ unbound-1.4.17/util/configparser.y
+@@ -92,6 +92,7 @@ extern struct config_parser_state* cfg_p
+ %token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
+ %token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
+ %token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
++%token VAR_AAAA_FILTER
+ %token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
+ %token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
+ %token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
+@@ -151,6 +152,7 @@ content_server: server_num_threads | ser
+ server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
+ server_harden_referral_path | server_private_address |
+ server_private_domain | server_extended_statistics |
++ server_aaaa_filter |
+ server_local_data_ptr | server_jostle_timeout |
+ server_unwanted_reply_threshold | server_log_time_ascii |
+ server_domain_insecure | server_val_sig_skew_min |
+@@ -802,6 +803,15 @@ server_use_caps_for_id: VAR_USE_CAPS_FOR
+ free($2);
+ }
+ ;
++server_aaaa_filter: VAR_AAAA_FILTER STRING_ARG
++ {
++ OUTYY(("P(server_aaaa_filter:%s)\n", $2));
++ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
++ yyerror("expected yes or no.");
++ else cfg_parser->cfg->aaaa_filter = (strcmp($2, "yes")==0);
++ free($2);
++ }
++ ;
+ server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG
+ {
+ OUTYY(("P(server_private_address:%s)\n", $2));
+--- unbound-1.4.17.orig/pythonmod/interface.i
++++ unbound-1.4.17/pythonmod/interface.i
+@@ -626,6 +626,7 @@ struct config_file {
+ int harden_dnssec_stripped;
+ int harden_referral_path;
+ int use_caps_bits_for_id;
++ int aaaa_filter; /* ASN */
+ struct config_strlist* private_address;
+ struct config_strlist* private_domain;
+ size_t unwanted_threshold;
--- /dev/null
+/*
+ * dns64/dns64.c - DNS64 module
+ *
+ * Copyright (c) 2009, Viagénie. 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 Viagénie 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains a module that performs DNS64 query processing.
+ */
+
+#include "config.h"
+#include "dns64/dns64.h"
+#include "services/cache/dns.h"
+#include "services/cache/rrset.h"
+#include "util/config_file.h"
+#include "util/data/msgreply.h"
+#include "util/fptr_wlist.h"
+#include "util/net_help.h"
+#include "util/regional.h"
+
+/******************************************************************************
+ * *
+ * STATIC CONSTANTS *
+ * *
+ ******************************************************************************/
+
+/**
+ * This is the default DNS64 prefix that is used whent he dns64 module is listed
+ * in module-config but when the dns64-prefix variable is not present.
+ */
+static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
+
+/**
+ * Maximum length of a domain name in a PTR query in the .in-addr.arpa tree.
+ */
+#define MAX_PTR_QNAME_IPV4 30
+
+/**
+ * Per-query module-specific state. This is usually a dynamically-allocated
+ * structure, but in our case we only need to store one variable describing the
+ * state the query is in. So we repurpose the minfo pointer by storing an
+ * integer in there.
+ */
+enum dns64_qstate {
+ DNS64_INTERNAL_QUERY, /**< Internally-generated query, no DNS64
+ processing. */
+ DNS64_NEW_QUERY, /**< Query for which we're the first module in
+ line. */
+ DNS64_SUBQUERY_FINISHED /**< Query for which we generated a sub-query, and
+ for which this sub-query is finished. */
+};
+
+
+/******************************************************************************
+ * *
+ * STRUCTURES *
+ * *
+ ******************************************************************************/
+
+/**
+ * This structure contains module configuration information. One instance of
+ * this structure exists per instance of the module. Normally there is only one
+ * instance of the module.
+ */
+struct dns64_env {
+ /**
+ * DNS64 prefix address. We're using a full sockaddr instead of just an
+ * in6_addr because we can reuse Unbound's generic string parsing functions.
+ * It will always contain a sockaddr_in6, and only the sin6_addr member will
+ * ever be used.
+ */
+ struct sockaddr_storage prefix_addr;
+
+ /**
+ * This is always sizeof(sockaddr_in6).
+ */
+ socklen_t prefix_addrlen;
+
+ /**
+ * This is the CIDR length of the prefix. It needs to be between 0 and 96.
+ */
+ int prefix_net;
+};
+
+
+/******************************************************************************
+ * *
+ * UTILITY FUNCTIONS *
+ * *
+ ******************************************************************************/
+
+/**
+ * Generic macro for swapping two variables.
+ *
+ * \param t Type of the variables. (e.g. int)
+ * \param a First variable.
+ * \param b Second variable.
+ *
+ * \warning Do not attempt something foolish such as swap(int,a++,b++)!
+ */
+#define swap(t,a,b) do {t x = a; a = b; b = x;} while(0)
+
+/**
+ * Reverses a string.
+ *
+ * \param begin Points to the first character of the string.
+ * \param end Points one past the last character of the string.
+ */
+static void
+reverse(char* begin, char* end)
+{
+ while ( begin < --end ) {
+ swap(char, *begin, *end);
+ ++begin;
+ }
+}
+
+/**
+ * Convert an unsigned integer to a string. The point of this function is that
+ * of being faster than sprintf().
+ *
+ * \param n The number to be converted.
+ * \param s The result will be written here. Must be large enough, be careful!
+ *
+ * \return The number of characters written.
+ */
+static int
+uitoa(unsigned n, char* s)
+{
+ char* ss = s;
+ do {
+ *ss++ = '0' + n % 10;
+ } while (n /= 10);
+ reverse(s, ss);
+ return ss - s;
+}
+
+/**
+ * Extract an IPv4 address embedded in the IPv6 address \a ipv6 at offset \a
+ * offset (in bits). Note that bits are not necessarily aligned on bytes so we
+ * need to be careful.
+ *
+ * \param ipv6 IPv6 address represented as a 128-bit array in big-endian
+ * order.
+ * \param offset Index of the MSB of the IPv4 address embedded in the IPv6
+ * address.
+ */
+static uint32_t
+extract_ipv4(const uint8_t ipv6[16], const int offset)
+{
+ uint32_t ipv4 = (uint32_t)ipv6[offset/8+0] << (24 + (offset%8))
+ | (uint32_t)ipv6[offset/8+1] << (16 + (offset%8))
+ | (uint32_t)ipv6[offset/8+2] << ( 8 + (offset%8))
+ | (uint32_t)ipv6[offset/8+3] << ( 0 + (offset%8));
+ if (offset/8+4 < 16)
+ ipv4 |= (uint32_t)ipv6[offset/8+4] >> (8 - offset%8);
+ return ipv4;
+}
+
+/**
+ * Builds the PTR query name corresponding to an IPv4 address. For example,
+ * given the number 3,464,175,361, this will build the string
+ * "\03206\03123\0231\011\07in-addr\04arpa".
+ *
+ * \param ipv4 IPv4 address represented as an unsigned 32-bit number.
+ * \param ptr The result will be written here. Must be large enough, be
+ * careful!
+ *
+ * \return The number of characters written.
+ */
+static size_t
+ipv4_to_ptr(uint32_t ipv4, char ptr[MAX_PTR_QNAME_IPV4])
+{
+ static const char IPV4_PTR_SUFFIX[] = "\07in-addr\04arpa";
+ int i;
+ char* c = ptr;
+
+ for (i = 0; i < 4; ++i) {
+ *c = uitoa((unsigned int)(ipv4 % 256), c + 1);
+ c += *c + 1;
+ ipv4 /= 256;
+ }
+
+ memmove(c, IPV4_PTR_SUFFIX, sizeof(IPV4_PTR_SUFFIX));
+
+ return c + sizeof(IPV4_PTR_SUFFIX) - ptr;
+}
+
+/**
+ * Converts an IPv6-related domain name string from a PTR query into an IPv6
+ * address represented as a 128-bit array.
+ *
+ * \param ptr The domain name. (e.g. "\011[...]\010\012\016\012\03ip6\04arpa")
+ * \param ipv6 The result will be written here, in network byte order.
+ *
+ * \return 1 on success, 0 on failure.
+ */
+static int
+ptr_to_ipv6(const char* ptr, uint8_t ipv6[16])
+{
+ int i;
+
+ for (i = 0; i < 64; i++) {
+ int x;
+
+ if (ptr[i++] != 1)
+ return 0;
+
+ if (ptr[i] >= '0' && ptr[i] <= '9') {
+ x = ptr[i] - '0';
+ } else if (ptr[i] >= 'a' && ptr[i] <= 'f') {
+ x = ptr[i] - 'a' + 10;
+ } else if (ptr[i] >= 'A' && ptr[i] <= 'F') {
+ x = ptr[i] - 'A' + 10;
+ } else {
+ return 0;
+ }
+
+ ipv6[15-i/4] |= x << (2 * ((i-1) % 4));
+ }
+
+ return 1;
+}
+
+/**
+ * Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix.
+ *
+ * \param prefix_addr DNS64 prefix address.
+ * \param prefix_net CIDR length of the DNS64 prefix. Must be between 0 and 96.
+ * \param a IPv4 address.
+ * \param aaaa IPv6 address. The result will be written here.
+ */
+static void
+synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net,
+ const uint8_t a[4], uint8_t aaaa[16])
+{
+ memcpy(aaaa, prefix_addr, 16);
+ aaaa[prefix_net/8+0] |= a[0] >> (0+prefix_net%8);
+ aaaa[prefix_net/8+1] |= a[0] << (8-prefix_net%8);
+ aaaa[prefix_net/8+1] |= a[1] >> (0+prefix_net%8);
+ aaaa[prefix_net/8+2] |= a[1] << (8-prefix_net%8);
+ aaaa[prefix_net/8+2] |= a[2] >> (0+prefix_net%8);
+ aaaa[prefix_net/8+3] |= a[2] << (8-prefix_net%8);
+ aaaa[prefix_net/8+3] |= a[3] >> (0+prefix_net%8);
+ if (prefix_net/8+4 < 16) /* <-- my beautiful symmetry is destroyed! */
+ aaaa[prefix_net/8+4] |= a[3] << (8-prefix_net%8);
+}
+
+
+/******************************************************************************
+ * *
+ * DNS64 MODULE FUNCTIONS *
+ * *
+ ******************************************************************************/
+
+/**
+ * This function applies the configuration found in the parsed configuration
+ * file \a cfg to this instance of the dns64 module. Currently only the DNS64
+ * prefix (a.k.a. Pref64) is configurable.
+ *
+ * \param dns64_env Module-specific global parameters.
+ * \param cfg Parsed configuration file.
+ */
+static int
+dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
+{
+ verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix);
+ if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix :
+ DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr,
+ &dns64_env->prefix_addrlen, &dns64_env->prefix_net)) {
+ log_err("cannot parse dns64-prefix netblock: %s", cfg->dns64_prefix);
+ return 0;
+ }
+ if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) {
+ log_err("dns64_prefix is not IPv6: %s", cfg->dns64_prefix);
+ return 0;
+ }
+ if (dns64_env->prefix_net < 0 || dns64_env->prefix_net > 96) {
+ log_err("dns64-prefix length it not between 0 and 96: %s",
+ cfg->dns64_prefix);
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Initializes this instance of the dns64 module.
+ *
+ * \param env Global state of all module instances.
+ * \param id This instance's ID number.
+ */
+int
+dns64_init(struct module_env* env, int id)
+{
+ struct dns64_env* dns64_env =
+ (struct dns64_env*)calloc(1, sizeof(struct dns64_env));
+ if (!dns64_env) {
+ log_err("malloc failure");
+ return 0;
+ }
+ env->modinfo[id] = (void*)dns64_env;
+ if (!dns64_apply_cfg(dns64_env, env->cfg)) {
+ log_err("dns64: could not apply configuration settings.");
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Deinitializes this instance of the dns64 module.
+ *
+ * \param env Global state of all module instances.
+ * \param id This instance's ID number.
+ */
+void
+dns64_deinit(struct module_env* env, int id)
+{
+ if (!env)
+ return;
+ free(env->modinfo[id]);
+ env->modinfo[id] = NULL;
+}
+
+/**
+ * Handle PTR queries for IPv6 addresses. If the address belongs to the DNS64
+ * prefix, we must do a PTR query for the corresponding IPv4 address instead.
+ *
+ * \param qstate Query state structure.
+ * \param id This module instance's ID number.
+ *
+ * \return The new state of the query.
+ */
+static enum module_ext_state
+handle_ipv6_ptr(struct module_qstate* qstate, int id)
+{
+ struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id];
+ struct module_qstate* subq = NULL;
+ struct query_info qinfo;
+ struct sockaddr_in6 sin6;
+
+ /* Convert the PTR query string to an IPv6 address. */
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr))
+ return module_wait_module; /* Let other module handle this. */
+
+ /*
+ * If this IPv6 address is not part of our DNS64 prefix, then we don't need
+ * to do anything. Let another module handle the query.
+ */
+ if (addr_in_common((struct sockaddr_storage*)&sin6, 128,
+ &dns64_env->prefix_addr, dns64_env->prefix_net,
+ (socklen_t)sizeof(sin6)) != dns64_env->prefix_net)
+ return module_wait_module;
+
+ verbose(VERB_ALGO, "dns64: rewrite PTR record");
+
+ /*
+ * Create a new PTR query info for the domain name corresponding to the IPv4
+ * address corresponding to the IPv6 address corresponding to the original
+ * PTR query domain name.
+ */
+ qinfo = qstate->qinfo;
+ if (!(qinfo.qname = regional_alloc(qstate->region, MAX_PTR_QNAME_IPV4)))
+ return module_error;
+ qinfo.qname_len = ipv4_to_ptr(extract_ipv4(sin6.sin6_addr.s6_addr,
+ dns64_env->prefix_net), (char*)qinfo.qname);
+
+ /* Create the new sub-query. */
+ fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
+ if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0,
+ &subq))
+ return module_error;
+ if (subq) {
+ subq->curmod = id;
+ subq->ext_state[id] = module_state_initial;
+ subq->minfo[id] = NULL;
+ }
+
+ return module_wait_subquery;
+}
+
+/** allocate (special) rrset keys, return 0 on error */
+static int
+repinfo_alloc_rrset_keys(struct reply_info* rep,
+ struct regional* region)
+{
+ size_t i;
+ for(i=0; i<rep->rrset_count; i++) {
+ if(region) {
+ rep->rrsets[i] = (struct ub_packed_rrset_key*)
+ regional_alloc(region,
+ sizeof(struct ub_packed_rrset_key));
+ if(rep->rrsets[i]) {
+ memset(rep->rrsets[i], 0,
+ sizeof(struct ub_packed_rrset_key));
+ rep->rrsets[i]->entry.key = rep->rrsets[i];
+ }
+ }
+ else return 0;/* rep->rrsets[i] = alloc_special_obtain(alloc);*/
+ if(!rep->rrsets[i])
+ return 0;
+ rep->rrsets[i]->entry.data = NULL;
+ }
+ return 1;
+}
+
+static enum module_ext_state
+generate_type_A_query(struct module_qstate* qstate, int id)
+{
+ struct module_qstate* subq = NULL;
+ struct query_info qinfo;
+
+ verbose(VERB_ALGO, "dns64: query A record");
+
+ /* Create a new query info. */
+ qinfo = qstate->qinfo;
+ qinfo.qtype = LDNS_RR_TYPE_A;
+
+ /* Start the sub-query. */
+ fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
+ if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0,
+ 0, &subq))
+ {
+ verbose(VERB_ALGO, "dns64: sub-query creation failed");
+ return module_error;
+ }
+ if (subq) {
+ subq->curmod = id;
+ subq->ext_state[id] = module_state_initial;
+ subq->minfo[id] = NULL;
+ }
+
+ return module_wait_subquery;
+}
+
+/**
+ * Handles the "pass" event for a query. This event is received when a new query
+ * is received by this module. The query may have been generated internally by
+ * another module, in which case we don't want to do any special processing
+ * (this is an interesting discussion topic), or it may be brand new, e.g.
+ * received over a socket, in which case we do want to apply DNS64 processing.
+ *
+ * \param qstate A structure representing the state of the query that has just
+ * received the "pass" event.
+ * \param id This module's instance ID.
+ *
+ * \return The new state of the query.
+ */
+static enum module_ext_state
+handle_event_pass(struct module_qstate* qstate, int id)
+{
+ if ((uintptr_t)qstate->minfo[id] == DNS64_NEW_QUERY
+ && qstate->qinfo.qtype == LDNS_RR_TYPE_PTR
+ && qstate->qinfo.qname_len == 74
+ && !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa"))
+ /* Handle PTR queries for IPv6 addresses. */
+ return handle_ipv6_ptr(qstate, id);
+
+ if (qstate->env->cfg->dns64_synthall &&
+ (uintptr_t)qstate->minfo[id] == DNS64_NEW_QUERY
+ && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)
+ return generate_type_A_query(qstate, id);
+
+ /* We are finished when our sub-query is finished. */
+ if ((uintptr_t)qstate->minfo[id] == DNS64_SUBQUERY_FINISHED)
+ return module_finished;
+
+ /* Otherwise, pass request to next module. */
+ verbose(VERB_ALGO, "dns64: pass to next module");
+ return module_wait_module;
+}
+
+/**
+ * Handles the "done" event for a query. We need to analyze the response and
+ * maybe issue a new sub-query for the A record.
+ *
+ * \param qstate A structure representing the state of the query that has just
+ * received the "pass" event.
+ * \param id This module's instance ID.
+ *
+ * \return The new state of the query.
+ */
+static enum module_ext_state
+handle_event_moddone(struct module_qstate* qstate, int id)
+{
+ /*
+ * In many cases we have nothing special to do. From most to least common:
+ *
+ * - An internal query.
+ * - A query for a record type other than AAAA.
+ * - CD FLAG was set on querier
+ * - An AAAA query for which an error was returned.
+ * - A successful AAAA query with an answer.
+ */
+ if ( (enum dns64_qstate)qstate->minfo[id] == DNS64_INTERNAL_QUERY
+ || qstate->qinfo.qtype != LDNS_RR_TYPE_AAAA
+ || (qstate->query_flags & BIT_CD)
+ || qstate->return_rcode != LDNS_RCODE_NOERROR
+ || (qstate->return_msg &&
+ qstate->return_msg->rep &&
+ reply_find_answer_rrset(&qstate->qinfo,
+ qstate->return_msg->rep)))
+ return module_finished;
+
+ /* So, this is a AAAA noerror/nodata answer */
+ return generate_type_A_query(qstate, id);
+}
+
+/**
+ * This is the module's main() function. It gets called each time a query
+ * receives an event which we may need to handle. We respond by updating the
+ * state of the query.
+ *
+ * \param qstate Structure containing the state of the query.
+ * \param event Event that has just been received.
+ * \param id This module's instance ID.
+ * \param outbound State of a DNS query on an authoritative server. We never do
+ * our own queries ourselves (other modules do it for us), so
+ * this is unused.
+ */
+void
+dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
+ struct outbound_entry* outbound)
+{
+ (void)outbound;
+ verbose(VERB_QUERY, "dns64[module %d] operate: extstate:%s event:%s",
+ id, strextstate(qstate->ext_state[id]),
+ strmodulevent(event));
+ log_query_info(VERB_QUERY, "dns64 operate: query", &qstate->qinfo);
+
+ switch(event) {
+ case module_event_new:
+ /* Tag this query as being new and fall through. */
+ qstate->minfo[id] = (void*)DNS64_NEW_QUERY;
+ case module_event_pass:
+ qstate->ext_state[id] = handle_event_pass(qstate, id);
+ break;
+ case module_event_moddone:
+ qstate->ext_state[id] = handle_event_moddone(qstate, id);
+ break;
+ default:
+ qstate->ext_state[id] = module_finished;
+ break;
+ }
+}
+
+static void
+dns64_synth_aaaa_data(const struct ub_packed_rrset_key* fk,
+ const struct packed_rrset_data* fd,
+ struct ub_packed_rrset_key *dk,
+ struct packed_rrset_data **dd_out, struct regional *region,
+ struct dns64_env* dns64_env )
+{
+ struct packed_rrset_data *dd;
+ size_t i;
+ /*
+ * Create synthesized AAAA RR set data. We need to allocated extra memory
+ * for the RRs themselves. Each RR has a length, TTL, pointer to wireformat
+ * data, 2 bytes of data length, and 16 bytes of IPv6 address.
+ */
+ if(fd->count > RR_COUNT_MAX) {
+ *dd_out = NULL;
+ return; /* integer overflow protection in alloc */
+ }
+ if (!(dd = *dd_out = regional_alloc(region,
+ sizeof(struct packed_rrset_data)
+ + fd->count * (sizeof(size_t) + sizeof(time_t) +
+ sizeof(uint8_t*) + 2 + 16)))) {
+ log_err("out of memory");
+ return;
+ }
+
+ /* Copy attributes from A RR set. */
+ dd->ttl = fd->ttl;
+ dd->count = fd->count;
+ dd->rrsig_count = 0;
+ dd->trust = fd->trust;
+ dd->security = fd->security;
+
+ /*
+ * Synthesize AAAA records. Adjust pointers in structure.
+ */
+ dd->rr_len =
+ (size_t*)((uint8_t*)dd + sizeof(struct packed_rrset_data));
+ dd->rr_data = (uint8_t**)&dd->rr_len[dd->count];
+ dd->rr_ttl = (time_t*)&dd->rr_data[dd->count];
+ for(i = 0; i < fd->count; ++i) {
+ if (fd->rr_len[i] != 6 || fd->rr_data[i][0] != 0
+ || fd->rr_data[i][1] != 4)
+ return;
+ dd->rr_len[i] = 18;
+ dd->rr_data[i] =
+ (uint8_t*)&dd->rr_ttl[dd->count] + 18*i;
+ dd->rr_data[i][0] = 0;
+ dd->rr_data[i][1] = 16;
+ synthesize_aaaa(
+ ((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr,
+ dns64_env->prefix_net, &fd->rr_data[i][2],
+ &dd->rr_data[i][2] );
+ dd->rr_ttl[i] = fd->rr_ttl[i];
+ }
+
+ /*
+ * Create synthesized AAAA RR set key. This is mostly just bookkeeping,
+ * nothing interesting here.
+ */
+ if(!dk) {
+ log_err("no key");
+ return;
+ }
+
+ dk->rk.dname = (uint8_t*)regional_alloc_init(region,
+ fk->rk.dname, fk->rk.dname_len);
+
+ if(!dk->rk.dname) {
+ log_err("out of memory");
+ return;
+ }
+
+ dk->rk.type = htons(LDNS_RR_TYPE_AAAA);
+ memset(&dk->entry, 0, sizeof(dk->entry));
+ dk->entry.key = dk;
+ dk->entry.hash = rrset_key_hash(&dk->rk);
+ dk->entry.data = dd;
+
+}
+
+/**
+ * Synthesize an AAAA RR set from an A sub-query's answer and add it to the
+ * original empty response.
+ *
+ * \param id This module's instance ID.
+ * \param super Original AAAA query.
+ * \param qstate A query.
+ */
+static void
+dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate)
+{
+ struct dns64_env* dns64_env = (struct dns64_env*)super->env->modinfo[id];
+ struct reply_info *rep, *cp;
+ size_t i, s;
+ struct packed_rrset_data* fd, *dd;
+ struct ub_packed_rrset_key* fk, *dk;
+
+ verbose(VERB_ALGO, "converting A answers to AAAA answers");
+
+ log_assert(super->region);
+ log_assert(qstate->return_msg);
+ log_assert(qstate->return_msg->rep);
+
+ /* If dns64-synthall is enabled, return_msg is not initialized */
+ if(!super->return_msg) {
+ super->return_msg = (struct dns_msg*)regional_alloc(
+ super->region, sizeof(struct dns_msg));
+ if(!super->return_msg)
+ return;
+ memset(super->return_msg, 0, sizeof(*super->return_msg));
+ super->return_msg->qinfo = super->qinfo;
+ }
+
+ rep = qstate->return_msg->rep;
+
+ /*
+ * Build the actual reply.
+ */
+ cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
+ rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, rep->ns_numrrsets,
+ rep->ar_numrrsets, rep->rrset_count, rep->security);
+ if(!cp)
+ return;
+
+ /* allocate ub_key structures special or not */
+ if(!repinfo_alloc_rrset_keys(cp, super->region)) {
+ return;
+ }
+
+ /* copy everything and replace A by AAAA */
+ for(i=0; i<cp->rrset_count; i++) {
+ fk = rep->rrsets[i];
+ dk = cp->rrsets[i];
+ fd = (struct packed_rrset_data*)fk->entry.data;
+ dk->rk = fk->rk;
+ dk->id = fk->id;
+
+ if(i<rep->an_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) {
+ /* also sets dk->entry.hash */
+ dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env);
+ if(!dd)
+ return;
+ /* Delete negative AAAA record from cache stored by
+ * the iterator module */
+ rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
+ dk->rk.dname_len, LDNS_RR_TYPE_AAAA,
+ LDNS_RR_CLASS_IN, 0);
+ } else {
+ dk->entry.hash = fk->entry.hash;
+ dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
+ fk->rk.dname, fk->rk.dname_len);
+
+ if(!dk->rk.dname)
+ return;
+
+ s = packed_rrset_sizeof(fd);
+ dd = (struct packed_rrset_data*)regional_alloc_init(
+ super->region, fd, s);
+
+ if(!dd)
+ return;
+ }
+
+ packed_rrset_ptr_fixup(dd);
+ dk->entry.data = (void*)dd;
+ }
+
+ /* Commit changes. */
+ super->return_msg->rep = cp;
+}
+
+/**
+ * Generate a response for the original IPv6 PTR query based on an IPv4 PTR
+ * sub-query's response.
+ *
+ * \param qstate IPv4 PTR sub-query.
+ * \param super Original IPv6 PTR query.
+ */
+static void
+dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
+{
+ struct ub_packed_rrset_key* answer;
+
+ verbose(VERB_ALGO, "adjusting PTR reply");
+
+ /* Copy the sub-query's reply to the parent. */
+ if (!(super->return_msg = (struct dns_msg*)regional_alloc(super->region,
+ sizeof(struct dns_msg))))
+ return;
+ super->return_msg->qinfo = super->qinfo;
+ super->return_msg->rep = reply_info_copy(qstate->return_msg->rep, NULL,
+ super->region);
+
+ /*
+ * Adjust the domain name of the answer RR set so that it matches the
+ * initial query's domain name.
+ */
+ answer = reply_find_answer_rrset(&qstate->qinfo, super->return_msg->rep);
+ log_assert(answer);
+ answer->rk.dname = super->qinfo.qname;
+ answer->rk.dname_len = super->qinfo.qname_len;
+}
+
+/**
+ * This function is called when a sub-query finishes to inform the parent query.
+ *
+ * We issue two kinds of sub-queries: PTR and A.
+ *
+ * \param qstate State of the sub-query.
+ * \param id This module's instance ID.
+ * \param super State of the super-query.
+ */
+void
+dns64_inform_super(struct module_qstate* qstate, int id,
+ struct module_qstate* super)
+{
+ log_query_info(VERB_ALGO, "dns64: inform_super, sub is",
+ &qstate->qinfo);
+ log_query_info(VERB_ALGO, "super is", &super->qinfo);
+
+ /*
+ * Signal that the sub-query is finished, no matter whether we are
+ * successful or not. This lets the state machine terminate.
+ */
+ super->minfo[id] = (void*)DNS64_SUBQUERY_FINISHED;
+
+ /* If there is no successful answer, we're done. */
+ if (qstate->return_rcode != LDNS_RCODE_NOERROR
+ || !qstate->return_msg
+ || !qstate->return_msg->rep
+ || !reply_find_answer_rrset(&qstate->qinfo,
+ qstate->return_msg->rep))
+ return;
+
+ /* Generate a response suitable for the original query. */
+ if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) {
+ dns64_adjust_a(id, super, qstate);
+ } else {
+ log_assert(qstate->qinfo.qtype == LDNS_RR_TYPE_PTR);
+ dns64_adjust_ptr(qstate, super);
+ }
+
+ /* 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))
+ log_err("out of memory");
+}
+
+/**
+ * Clear module-specific data from query state. Since we do not allocate memory,
+ * it's just a matter of setting a pointer to NULL.
+ *
+ * \param qstate Query state.
+ * \param id This module's instance ID.
+ */
+void
+dns64_clear(struct module_qstate* qstate, int id)
+{
+ qstate->minfo[id] = NULL;
+}
+
+/**
+ * Returns the amount of global memory that this module uses, not including
+ * per-query data.
+ *
+ * \param env Module environment.
+ * \param id This module's instance ID.
+ */
+size_t
+dns64_get_mem(struct module_env* env, int id)
+{
+ struct dns64_env* dns64_env = (struct dns64_env*)env->modinfo[id];
+ if (!dns64_env)
+ return 0;
+ return sizeof(*dns64_env);
+}
+
+/**
+ * The dns64 function block.
+ */
+static struct module_func_block dns64_block = {
+ "dns64",
+ &dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super,
+ &dns64_clear, &dns64_get_mem
+};
+
+/**
+ * Function for returning the above function block.
+ */
+struct module_func_block *
+dns64_get_funcblock()
+{
+ return &dns64_block;
+}
--- /dev/null
+/*
+ * dns64/dns64.h - DNS64 module
+ *
+ * Copyright (c) 2009, Viagénie. 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 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.
+ */
+
+/**
+ * \file
+ *
+ * This file contains a module that performs DNS64 query processing.
+ */
+
+#ifndef DNS64_DNS64_H
+#define DNS64_DNS64_H
+#include "util/module.h"
+
+/**
+ * Get the dns64 function block.
+ * @return: function block with function pointers to dns64 methods.
+ */
+struct module_func_block *dns64_get_funcblock(void);
+
+/** dns64 init */
+int dns64_init(struct module_env* env, int id);
+
+/** dns64 deinit */
+void dns64_deinit(struct module_env* env, int id);
+
+/** dns64 operate on a query */
+void dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
+ struct outbound_entry* outbound);
+
+void dns64_inform_super(struct module_qstate* qstate, int id,
+ struct module_qstate* super);
+
+/** dns64 cleanup query state */
+void dns64_clear(struct module_qstate* qstate, int id);
+
+/** dns64 alloc size routine */
+size_t dns64_get_mem(struct module_env* env, int id);
+
+#endif /* DNS64_DNS64_H */
--- /dev/null
+/* dnstap support for Unbound */
+
+/*
+ * Copyright (c) 2013-2014, Farsight Security, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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.
+ */
+
+#include "dnstap/dnstap_config.h"
+
+#ifdef USE_DNSTAP
+
+#include "config.h"
+#include <string.h>
+#include <sys/time.h>
+#include "sldns/sbuffer.h"
+#include "util/config_file.h"
+#include "util/net_help.h"
+#include "util/netevent.h"
+#include "util/log.h"
+
+#include <fstrm.h>
+#include <protobuf-c/protobuf-c.h>
+
+#include "dnstap/dnstap.h"
+#include "dnstap/dnstap.pb-c.h"
+
+#define DNSTAP_CONTENT_TYPE "protobuf:dnstap.Dnstap"
+#define DNSTAP_INITIAL_BUF_SIZE 256
+
+struct dt_msg {
+ void *buf;
+ size_t len_buf;
+ Dnstap__Dnstap d;
+ Dnstap__Message m;
+};
+
+static int
+dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
+{
+ ProtobufCBufferSimple sbuf;
+
+ memset(&sbuf, 0, sizeof(sbuf));
+ sbuf.base.append = protobuf_c_buffer_simple_append;
+ sbuf.len = 0;
+ sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE;
+ sbuf.data = malloc(sbuf.alloced);
+ if (sbuf.data == NULL)
+ return 0;
+ sbuf.must_free_data = 1;
+
+ *sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf);
+ if (sbuf.data == NULL)
+ return 0;
+ *buf = sbuf.data;
+
+ return 1;
+}
+
+static void
+dt_send(const struct dt_env *env, void *buf, size_t len_buf)
+{
+ fstrm_res res;
+ if (!buf)
+ return;
+ res = fstrm_iothr_submit(env->iothr, env->ioq, buf, len_buf,
+ fstrm_free_wrapper, NULL);
+ if (res != fstrm_res_success)
+ free(buf);
+}
+
+static void
+dt_msg_init(const struct dt_env *env,
+ struct dt_msg *dm,
+ Dnstap__Message__Type mtype)
+{
+ memset(dm, 0, sizeof(*dm));
+ dm->d.base.descriptor = &dnstap__dnstap__descriptor;
+ dm->m.base.descriptor = &dnstap__message__descriptor;
+ dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE;
+ dm->d.message = &dm->m;
+ dm->m.type = mtype;
+ if (env->identity != NULL) {
+ dm->d.identity.data = (uint8_t *) env->identity;
+ dm->d.identity.len = (size_t) env->len_identity;
+ dm->d.has_identity = 1;
+ }
+ if (env->version != NULL) {
+ dm->d.version.data = (uint8_t *) env->version;
+ dm->d.version.len = (size_t) env->len_version;
+ dm->d.has_version = 1;
+ }
+}
+
+struct dt_env *
+dt_create(const char *socket_path, unsigned num_workers)
+{
+ fstrm_res res;
+ struct dt_env *env;
+ struct fstrm_iothr_options *fopt;
+ struct fstrm_unix_writer_options *fuwopt;
+ struct fstrm_writer *fw;
+ struct fstrm_writer_options *fwopt;
+
+ verbose(VERB_OPS, "opening dnstap socket %s", socket_path);
+ log_assert(socket_path != NULL);
+ log_assert(num_workers > 0);
+
+ env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
+ if (!env)
+ return NULL;
+
+ fwopt = fstrm_writer_options_init();
+ res = fstrm_writer_options_add_content_type(fwopt,
+ DNSTAP_CONTENT_TYPE, sizeof(DNSTAP_CONTENT_TYPE) - 1);
+ log_assert(res == fstrm_res_success);
+
+ fuwopt = fstrm_unix_writer_options_init();
+ fstrm_unix_writer_options_set_socket_path(fuwopt, socket_path);
+
+ fw = fstrm_unix_writer_init(fuwopt, fwopt);
+ log_assert(fw != NULL);
+
+ fopt = fstrm_iothr_options_init();
+ fstrm_iothr_options_set_num_input_queues(fopt, num_workers);
+ env->iothr = fstrm_iothr_init(fopt, &fw);
+ if (env->iothr == NULL) {
+ verbose(VERB_DETAIL, "dt_create: fstrm_iothr_init() failed");
+ fstrm_writer_destroy(&fw);
+ free(env);
+ env = NULL;
+ }
+ fstrm_iothr_options_destroy(&fopt);
+ fstrm_unix_writer_options_destroy(&fuwopt);
+ fstrm_writer_options_destroy(&fwopt);
+
+ return env;
+}
+
+static void
+dt_apply_identity(struct dt_env *env, struct config_file *cfg)
+{
+ char buf[MAXHOSTNAMELEN+1];
+ if (!cfg->dnstap_send_identity)
+ return;
+ free(env->identity);
+ if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
+ if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
+ buf[MAXHOSTNAMELEN] = 0;
+ env->identity = strdup(buf);
+ } else {
+ fatal_exit("dt_apply_identity: gethostname() failed");
+ }
+ } else {
+ env->identity = strdup(cfg->dnstap_identity);
+ }
+ if (env->identity == NULL)
+ fatal_exit("dt_apply_identity: strdup() failed");
+ env->len_identity = (unsigned int)strlen(env->identity);
+ verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
+ env->identity);
+}
+
+static void
+dt_apply_version(struct dt_env *env, struct config_file *cfg)
+{
+ if (!cfg->dnstap_send_version)
+ return;
+ free(env->version);
+ if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
+ env->version = strdup(PACKAGE_STRING);
+ else
+ env->version = strdup(cfg->dnstap_version);
+ if (env->version == NULL)
+ fatal_exit("dt_apply_version: strdup() failed");
+ env->len_version = (unsigned int)strlen(env->version);
+ verbose(VERB_OPS, "dnstap version field set to \"%s\"",
+ env->version);
+}
+
+void
+dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
+{
+ if (!cfg->dnstap)
+ return;
+
+ dt_apply_identity(env, cfg);
+ dt_apply_version(env, cfg);
+ if ((env->log_resolver_query_messages = (unsigned int)
+ cfg->dnstap_log_resolver_query_messages))
+ {
+ verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled");
+ }
+ if ((env->log_resolver_response_messages = (unsigned int)
+ cfg->dnstap_log_resolver_response_messages))
+ {
+ verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled");
+ }
+ if ((env->log_client_query_messages = (unsigned int)
+ cfg->dnstap_log_client_query_messages))
+ {
+ verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled");
+ }
+ if ((env->log_client_response_messages = (unsigned int)
+ cfg->dnstap_log_client_response_messages))
+ {
+ verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled");
+ }
+ if ((env->log_forwarder_query_messages = (unsigned int)
+ cfg->dnstap_log_forwarder_query_messages))
+ {
+ verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled");
+ }
+ if ((env->log_forwarder_response_messages = (unsigned int)
+ cfg->dnstap_log_forwarder_response_messages))
+ {
+ verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
+ }
+}
+
+int
+dt_init(struct dt_env *env)
+{
+ env->ioq = fstrm_iothr_get_input_queue(env->iothr);
+ if (env->ioq == NULL)
+ return 0;
+ return 1;
+}
+
+void
+dt_delete(struct dt_env *env)
+{
+ if (!env)
+ return;
+ verbose(VERB_OPS, "closing dnstap socket");
+ fstrm_iothr_destroy(&env->iothr);
+ free(env->identity);
+ free(env->version);
+ free(env);
+}
+
+static void
+dt_fill_timeval(const struct timeval *tv,
+ uint64_t *time_sec, protobuf_c_boolean *has_time_sec,
+ uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec)
+{
+#ifndef S_SPLINT_S
+ *time_sec = tv->tv_sec;
+ *time_nsec = tv->tv_usec * 1000;
+#endif
+ *has_time_sec = 1;
+ *has_time_nsec = 1;
+}
+
+static void
+dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has)
+{
+ log_assert(b != NULL);
+ p->len = sldns_buffer_limit(b);
+ p->data = sldns_buffer_begin(b);
+ *has = 1;
+}
+
+static void
+dt_msg_fill_net(struct dt_msg *dm,
+ struct sockaddr_storage *ss,
+ enum comm_point_type cptype,
+ ProtobufCBinaryData *addr, protobuf_c_boolean *has_addr,
+ uint32_t *port, protobuf_c_boolean *has_port)
+{
+ log_assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET);
+ if (ss->ss_family == AF_INET6) {
+ struct sockaddr_in6 *s = (struct sockaddr_in6 *) ss;
+
+ /* socket_family */
+ dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6;
+ dm->m.has_socket_family = 1;
+
+ /* addr: query_address or response_address */
+ addr->data = s->sin6_addr.s6_addr;
+ addr->len = 16; /* IPv6 */
+ *has_addr = 1;
+
+ /* port: query_port or response_port */
+ *port = ntohs(s->sin6_port);
+ *has_port = 1;
+ } else if (ss->ss_family == AF_INET) {
+ struct sockaddr_in *s = (struct sockaddr_in *) ss;
+
+ /* socket_family */
+ dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET;
+ dm->m.has_socket_family = 1;
+
+ /* addr: query_address or response_address */
+ addr->data = (uint8_t *) &s->sin_addr.s_addr;
+ addr->len = 4; /* IPv4 */
+ *has_addr = 1;
+
+ /* port: query_port or response_port */
+ *port = ntohs(s->sin_port);
+ *has_port = 1;
+ }
+
+ log_assert(cptype == comm_udp || cptype == comm_tcp);
+ if (cptype == comm_udp) {
+ /* socket_protocol */
+ dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
+ dm->m.has_socket_protocol = 1;
+ } else if (cptype == comm_tcp) {
+ /* socket_protocol */
+ dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
+ dm->m.has_socket_protocol = 1;
+ }
+}
+
+void
+dt_msg_send_client_query(struct dt_env *env,
+ struct sockaddr_storage *qsock,
+ enum comm_point_type cptype,
+ sldns_buffer *qmsg)
+{
+ struct dt_msg dm;
+ struct timeval qtime;
+
+ gettimeofday(&qtime, NULL);
+
+ /* type */
+ dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY);
+
+ /* query_time */
+ dt_fill_timeval(&qtime,
+ &dm.m.query_time_sec, &dm.m.has_query_time_sec,
+ &dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
+
+ /* query_message */
+ dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
+
+ /* socket_family, socket_protocol, query_address, query_port */
+ log_assert(cptype == comm_udp || cptype == comm_tcp);
+ dt_msg_fill_net(&dm, qsock, cptype,
+ &dm.m.query_address, &dm.m.has_query_address,
+ &dm.m.query_port, &dm.m.has_query_port);
+
+ if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
+ dt_send(env, dm.buf, dm.len_buf);
+}
+
+void
+dt_msg_send_client_response(struct dt_env *env,
+ struct sockaddr_storage *qsock,
+ enum comm_point_type cptype,
+ sldns_buffer *rmsg)
+{
+ struct dt_msg dm;
+ struct timeval rtime;
+
+ gettimeofday(&rtime, NULL);
+
+ /* type */
+ dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE);
+
+ /* response_time */
+ dt_fill_timeval(&rtime,
+ &dm.m.response_time_sec, &dm.m.has_response_time_sec,
+ &dm.m.response_time_nsec, &dm.m.has_response_time_nsec);
+
+ /* response_message */
+ dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
+
+ /* socket_family, socket_protocol, query_address, query_port */
+ log_assert(cptype == comm_udp || cptype == comm_tcp);
+ dt_msg_fill_net(&dm, qsock, cptype,
+ &dm.m.query_address, &dm.m.has_query_address,
+ &dm.m.query_port, &dm.m.has_query_port);
+
+ if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
+ dt_send(env, dm.buf, dm.len_buf);
+}
+
+void
+dt_msg_send_outside_query(struct dt_env *env,
+ struct sockaddr_storage *rsock,
+ enum comm_point_type cptype,
+ uint8_t *zone, size_t zone_len,
+ sldns_buffer *qmsg)
+{
+ struct dt_msg dm;
+ struct timeval qtime;
+ uint16_t qflags;
+
+ gettimeofday(&qtime, NULL);
+ qflags = sldns_buffer_read_u16_at(qmsg, 2);
+
+ /* type */
+ if (qflags & BIT_RD) {
+ if (!env->log_forwarder_query_messages)
+ return;
+ dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY);
+ } else {
+ if (!env->log_resolver_query_messages)
+ return;
+ dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY);
+ }
+
+ /* query_zone */
+ dm.m.query_zone.data = zone;
+ dm.m.query_zone.len = zone_len;
+ dm.m.has_query_zone = 1;
+
+ /* query_time_sec, query_time_nsec */
+ dt_fill_timeval(&qtime,
+ &dm.m.query_time_sec, &dm.m.has_query_time_sec,
+ &dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
+
+ /* query_message */
+ dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
+
+ /* socket_family, socket_protocol, response_address, response_port */
+ log_assert(cptype == comm_udp || cptype == comm_tcp);
+ dt_msg_fill_net(&dm, rsock, cptype,
+ &dm.m.response_address, &dm.m.has_response_address,
+ &dm.m.response_port, &dm.m.has_response_port);
+
+ if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
+ dt_send(env, dm.buf, dm.len_buf);
+}
+
+void
+dt_msg_send_outside_response(struct dt_env *env,
+ struct sockaddr_storage *rsock,
+ enum comm_point_type cptype,
+ uint8_t *zone, size_t zone_len,
+ uint8_t *qbuf, size_t qbuf_len,
+ const struct timeval *qtime,
+ const struct timeval *rtime,
+ sldns_buffer *rmsg)
+{
+ struct dt_msg dm;
+ uint16_t qflags;
+
+ log_assert(qbuf_len >= sizeof(qflags));
+ memcpy(&qflags, qbuf, sizeof(qflags));
+ qflags = ntohs(qflags);
+
+ /* type */
+ if (qflags & BIT_RD) {
+ if (!env->log_forwarder_response_messages)
+ return;
+ dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
+ } else {
+ if (!env->log_resolver_query_messages)
+ return;
+ dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE);
+ }
+
+ /* query_zone */
+ dm.m.query_zone.data = zone;
+ dm.m.query_zone.len = zone_len;
+ dm.m.has_query_zone = 1;
+
+ /* query_time_sec, query_time_nsec */
+ dt_fill_timeval(qtime,
+ &dm.m.query_time_sec, &dm.m.has_query_time_sec,
+ &dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
+
+ /* response_time_sec, response_time_nsec */
+ dt_fill_timeval(rtime,
+ &dm.m.response_time_sec, &dm.m.has_response_time_sec,
+ &dm.m.response_time_nsec, &dm.m.has_response_time_nsec);
+
+ /* response_message */
+ dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
+
+ /* socket_family, socket_protocol, response_address, response_port */
+ log_assert(cptype == comm_udp || cptype == comm_tcp);
+ dt_msg_fill_net(&dm, rsock, cptype,
+ &dm.m.response_address, &dm.m.has_response_address,
+ &dm.m.response_port, &dm.m.has_response_port);
+
+ if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
+ dt_send(env, dm.buf, dm.len_buf);
+}
+
+#endif /* USE_DNSTAP */
--- /dev/null
+/* dnstap support for Unbound */
+
+/*
+ * Copyright (c) 2013-2014, Farsight Security, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 3. Neither the name of the copyright holder 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.
+ */
+
+#ifndef UNBOUND_DNSTAP_H
+#define UNBOUND_DNSTAP_H
+
+#include "dnstap/dnstap_config.h"
+
+#ifdef USE_DNSTAP
+
+struct config_file;
+struct fstrm_io;
+struct fstrm_queue;
+struct sldns_buffer;
+
+struct dt_env {
+ /** dnstap I/O thread */
+ struct fstrm_iothr *iothr;
+
+ /** dnstap I/O thread input queue */
+ struct fstrm_iothr_queue *ioq;
+
+ /** dnstap "identity" field, NULL if disabled */
+ char *identity;
+
+ /** dnstap "version" field, NULL if disabled */
+ char *version;
+
+ /** length of "identity" field */
+ unsigned len_identity;
+
+ /** length of "version" field */
+ unsigned len_version;
+
+ /** whether to log Message/RESOLVER_QUERY */
+ unsigned log_resolver_query_messages : 1;
+ /** whether to log Message/RESOLVER_RESPONSE */
+ unsigned log_resolver_response_messages : 1;
+ /** whether to log Message/CLIENT_QUERY */
+ unsigned log_client_query_messages : 1;
+ /** whether to log Message/CLIENT_RESPONSE */
+ unsigned log_client_response_messages : 1;
+ /** whether to log Message/FORWARDER_QUERY */
+ unsigned log_forwarder_query_messages : 1;
+ /** whether to log Message/FORWARDER_RESPONSE */
+ unsigned log_forwarder_response_messages : 1;
+};
+
+/**
+ * Create dnstap environment object. Afterwards, call dt_apply_cfg() to fill in
+ * the config variables and dt_init() to fill in the per-worker state. Each
+ * worker needs a copy of this object but with its own I/O queue (the fq field
+ * of the structure) to ensure lock-free access to its own per-worker circular
+ * queue. Duplicate the environment object if more than one worker needs to
+ * share access to the dnstap I/O socket.
+ * @param socket_path: path to dnstap logging socket, must be non-NULL.
+ * @param num_workers: number of worker threads, must be > 0.
+ * @return dt_env object, NULL on failure.
+ */
+struct dt_env *
+dt_create(const char *socket_path, unsigned num_workers);
+
+/**
+ * Apply config settings.
+ * @param env: dnstap environment object.
+ * @param cfg: new config settings.
+ */
+void
+dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
+
+/**
+ * Initialize per-worker state in dnstap environment object.
+ * @param env: dnstap environment object to initialize, created with dt_create().
+ * @return: true on success, false on failure.
+ */
+int
+dt_init(struct dt_env *env);
+
+/**
+ * Delete dnstap environment object. Closes dnstap I/O socket and deletes all
+ * per-worker I/O queues.
+ */
+void
+dt_delete(struct dt_env *env);
+
+/**
+ * Create and send a new dnstap "Message" event of type CLIENT_QUERY.
+ * @param env: dnstap environment object.
+ * @param qsock: address/port of client.
+ * @param cptype: comm_udp or comm_tcp.
+ * @param qmsg: query message.
+ */
+void
+dt_msg_send_client_query(struct dt_env *env,
+ struct sockaddr_storage *qsock,
+ enum comm_point_type cptype,
+ struct sldns_buffer *qmsg);
+
+/**
+ * Create and send a new dnstap "Message" event of type CLIENT_RESPONSE.
+ * @param env: dnstap environment object.
+ * @param qsock: address/port of client.
+ * @param cptype: comm_udp or comm_tcp.
+ * @param rmsg: response message.
+ */
+void
+dt_msg_send_client_response(struct dt_env *env,
+ struct sockaddr_storage *qsock,
+ enum comm_point_type cptype,
+ struct sldns_buffer *rmsg);
+
+/**
+ * Create and send a new dnstap "Message" event of type RESOLVER_QUERY or
+ * FORWARDER_QUERY. The type used is dependent on the value of the RD bit
+ * in the query header.
+ * @param env: dnstap environment object.
+ * @param rsock: address/port of server the query is being sent to.
+ * @param cptype: comm_udp or comm_tcp.
+ * @param zone: query zone.
+ * @param zone_len: length of zone.
+ * @param qmsg: query message.
+ */
+void
+dt_msg_send_outside_query(struct dt_env *env,
+ struct sockaddr_storage *rsock,
+ enum comm_point_type cptype,
+ uint8_t *zone, size_t zone_len,
+ struct sldns_buffer *qmsg);
+
+/**
+ * Create and send a new dnstap "Message" event of type RESOLVER_RESPONSE or
+ * FORWARDER_RESPONSE. The type used is dependent on the value of the RD bit
+ * in the query header.
+ * @param env: dnstap environment object.
+ * @param rsock: address/port of server the response was received from.
+ * @param cptype: comm_udp or comm_tcp.
+ * @param zone: query zone.
+ * @param zone_len: length of zone.
+ * @param qbuf: outside_network's qbuf key.
+ * @param qbuf_len: length of outside_network's qbuf key.
+ * @param qtime: time query message was sent.
+ * @param rtime: time response message was sent.
+ * @param rmsg: response message.
+ */
+void
+dt_msg_send_outside_response(struct dt_env *env,
+ struct sockaddr_storage *rsock,
+ enum comm_point_type cptype,
+ uint8_t *zone, size_t zone_len,
+ uint8_t *qbuf, size_t qbuf_len,
+ const struct timeval *qtime,
+ const struct timeval *rtime,
+ struct sldns_buffer *rmsg);
+
+#endif /* USE_DNSTAP */
+
+#endif /* UNBOUND_DNSTAP_H */
--- /dev/null
+# dnstap.m4
+
+# dt_DNSTAP(default_dnstap_socket_path, [action-if-true], [action-if-false])
+# --------------------------------------------------------------------------
+# Check for required dnstap libraries and add dnstap configure args.
+AC_DEFUN([dt_DNSTAP],
+[
+ AC_ARG_ENABLE([dnstap],
+ AS_HELP_STRING([--enable-dnstap],
+ [Enable dnstap support (requires fstrm, protobuf-c)]),
+ [opt_dnstap=$enableval], [opt_dnstap=no])
+
+ AC_ARG_WITH([dnstap-socket-path],
+ AS_HELP_STRING([--with-dnstap-socket-path=pathname],
+ [set default dnstap socket path]),
+ [opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"])
+
+ if test "x$opt_dnstap" != "xno"; then
+ AC_PATH_PROG([PROTOC_C], [protoc-c])
+ if test -z "$PROTOC_C"; then
+ AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
+ fi
+ AC_ARG_WITH([protobuf-c], AC_HELP_STRING([--with-protobuf-c=path],
+ [Path where protobuf-c is installed, for dnstap]), [
+ # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+ if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
+ CFLAGS="$CFLAGS -I$withval/include/google"
+ else
+ CFLAGS="$CFLAGS -I$withval/include"
+ fi
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ ], [
+ # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+ if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
+ CFLAGS="$CFLAGS -I/usr/include/google"
+ else
+ if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
+ CFLAGS="$CFLAGS -I/usr/local/include/google"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+ fi
+ fi
+ ])
+ AC_ARG_WITH([libfstrm], AC_HELP_STRING([--with-libfstrm=path],
+ [Path where libfstrm is installed, for dnstap]), [
+ CFLAGS="$CFLAGS -I$withval/include"
+ LDFLAGS="$LDFLAGS -L$withval/lib"
+ ])
+ AC_SEARCH_LIBS([fstrm_iothr_init], [fstrm], [],
+ AC_MSG_ERROR([The fstrm library was not found. Please install fstrm!]))
+ AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
+ AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!]))
+ $2
+ else
+ $3
+ fi
+])
--- /dev/null
+// dnstap: flexible, structured event replication format for DNS software
+//
+// This file contains the protobuf schemas for the "dnstap" structured event
+// replication format for DNS software.
+
+// Written in 2013-2014 by Farsight Security, Inc.
+//
+// To the extent possible under law, the author(s) have dedicated all
+// copyright and related and neighboring rights to this file to the public
+// domain worldwide. This file is distributed without any warranty.
+//
+// You should have received a copy of the CC0 Public Domain Dedication along
+// with this file. If not, see:
+//
+// <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+package dnstap;
+
+// "Dnstap": this is the top-level dnstap type, which is a "union" type that
+// contains other kinds of dnstap payloads, although currently only one type
+// of dnstap payload is defined.
+// See: https://developers.google.com/protocol-buffers/docs/techniques#union
+message Dnstap {
+ // DNS server identity.
+ // If enabled, this is the identity string of the DNS server which generated
+ // this message. Typically this would be the same string as returned by an
+ // "NSID" (RFC 5001) query.
+ optional bytes identity = 1;
+
+ // DNS server version.
+ // If enabled, this is the version string of the DNS server which generated
+ // this message. Typically this would be the same string as returned by a
+ // "version.bind" query.
+ optional bytes version = 2;
+
+ // Extra data for this payload.
+ // This field can be used for adding an arbitrary byte-string annotation to
+ // the payload. No encoding or interpretation is applied or enforced.
+ optional bytes extra = 3;
+
+ // Identifies which field below is filled in.
+ enum Type {
+ MESSAGE = 1;
+ }
+ required Type type = 15;
+
+ // One of the following will be filled in.
+ optional Message message = 14;
+}
+
+// SocketFamily: the network protocol family of a socket. This specifies how
+// to interpret "network address" fields.
+enum SocketFamily {
+ INET = 1; // IPv4 (RFC 791)
+ INET6 = 2; // IPv6 (RFC 2460)
+}
+
+// SocketProtocol: the transport protocol of a socket. This specifies how to
+// interpret "transport port" fields.
+enum SocketProtocol {
+ UDP = 1; // User Datagram Protocol (RFC 768)
+ TCP = 2; // Transmission Control Protocol (RFC 793)
+}
+
+// Message: a wire-format (RFC 1035 section 4) DNS message and associated
+// metadata. Applications generating "Message" payloads should follow
+// certain requirements based on the MessageType, see below.
+message Message {
+
+ // There are eight types of "Message" defined that correspond to the
+ // four arrows in the following diagram, slightly modified from RFC 1035
+ // section 2:
+
+ // +---------+ +----------+ +--------+
+ // | | query | | query | |
+ // | Stub |-SQ--------CQ->| Recursive|-RQ----AQ->| Auth. |
+ // | Resolver| | Server | | Name |
+ // | |<-SR--------CR-| |<-RR----AR-| Server |
+ // +---------+ response | | response | |
+ // +----------+ +--------+
+
+ // Each arrow has two Type values each, one for each "end" of each arrow,
+ // because these are considered to be distinct events. Each end of each
+ // arrow on the diagram above has been marked with a two-letter Type
+ // mnemonic. Clockwise from upper left, these mnemonic values are:
+ //
+ // SQ: STUB_QUERY
+ // CQ: CLIENT_QUERY
+ // RQ: RESOLVER_QUERY
+ // AQ: AUTH_QUERY
+ // AR: AUTH_RESPONSE
+ // RR: RESOLVER_RESPONSE
+ // CR: CLIENT_RESPONSE
+ // SR: STUB_RESPONSE
+
+ // Two additional types of "Message" have been defined for the
+ // "forwarding" case where an upstream DNS server is responsible for
+ // further recursion. These are not shown on the diagram above, but have
+ // the following mnemonic values:
+
+ // FQ: FORWARDER_QUERY
+ // FR: FORWARDER_RESPONSE
+
+ // The "Message" Type values are defined below.
+
+ enum Type {
+ // AUTH_QUERY is a DNS query message received from a resolver by an
+ // authoritative name server, from the perspective of the authorative
+ // name server.
+ AUTH_QUERY = 1;
+
+ // AUTH_RESPONSE is a DNS response message sent from an authoritative
+ // name server to a resolver, from the perspective of the authoritative
+ // name server.
+ AUTH_RESPONSE = 2;
+
+ // RESOLVER_QUERY is a DNS query message sent from a resolver to an
+ // authoritative name server, from the perspective of the resolver.
+ // Resolvers typically clear the RD (recursion desired) bit when
+ // sending queries.
+ RESOLVER_QUERY = 3;
+
+ // RESOLVER_RESPONSE is a DNS response message received from an
+ // authoritative name server by a resolver, from the perspective of
+ // the resolver.
+ RESOLVER_RESPONSE = 4;
+
+ // CLIENT_QUERY is a DNS query message sent from a client to a DNS
+ // server which is expected to perform further recursion, from the
+ // perspective of the DNS server. The client may be a stub resolver or
+ // forwarder or some other type of software which typically sets the RD
+ // (recursion desired) bit when querying the DNS server. The DNS server
+ // may be a simple forwarding proxy or it may be a full recursive
+ // resolver.
+ CLIENT_QUERY = 5;
+
+ // CLIENT_RESPONSE is a DNS response message sent from a DNS server to
+ // a client, from the perspective of the DNS server. The DNS server
+ // typically sets the RA (recursion available) bit when responding.
+ CLIENT_RESPONSE = 6;
+
+ // FORWARDER_QUERY is a DNS query message sent from a downstream DNS
+ // server to an upstream DNS server which is expected to perform
+ // further recursion, from the perspective of the downstream DNS
+ // server.
+ FORWARDER_QUERY = 7;
+
+ // FORWARDER_RESPONSE is a DNS response message sent from an upstream
+ // DNS server performing recursion to a downstream DNS server, from the
+ // perspective of the downstream DNS server.
+ FORWARDER_RESPONSE = 8;
+
+ // STUB_QUERY is a DNS query message sent from a stub resolver to a DNS
+ // server, from the perspective of the stub resolver.
+ STUB_QUERY = 9;
+
+ // STUB_RESPONSE is a DNS response message sent from a DNS server to a
+ // stub resolver, from the perspective of the stub resolver.
+ STUB_RESPONSE = 10;
+ }
+
+ // One of the Type values described above.
+ required Type type = 1;
+
+ // One of the SocketFamily values described above.
+ optional SocketFamily socket_family = 2;
+
+ // One of the SocketProtocol values described above.
+ optional SocketProtocol socket_protocol = 3;
+
+ // The network address of the message initiator.
+ // For SocketFamily INET, this field is 4 octets (IPv4 address).
+ // For SocketFamily INET6, this field is 16 octets (IPv6 address).
+ optional bytes query_address = 4;
+
+ // The network address of the message responder.
+ // For SocketFamily INET, this field is 4 octets (IPv4 address).
+ // For SocketFamily INET6, this field is 16 octets (IPv6 address).
+ optional bytes response_address = 5;
+
+ // The transport port of the message initiator.
+ // This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
+ optional uint32 query_port = 6;
+
+ // The transport port of the message responder.
+ // This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
+ optional uint32 response_port = 7;
+
+ // The time at which the DNS query message was sent or received, depending
+ // on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY.
+ // This is the number of seconds since the UNIX epoch.
+ optional uint64 query_time_sec = 8;
+
+ // The time at which the DNS query message was sent or received.
+ // This is the seconds fraction, expressed as a count of nanoseconds.
+ optional fixed32 query_time_nsec = 9;
+
+ // The initiator's original wire-format DNS query message, verbatim.
+ optional bytes query_message = 10;
+
+ // The "zone" or "bailiwick" pertaining to the DNS query message.
+ // This is a wire-format DNS domain name.
+ optional bytes query_zone = 11;
+
+ // The time at which the DNS response message was sent or received,
+ // depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or
+ // CLIENT_RESPONSE.
+ // This is the number of seconds since the UNIX epoch.
+ optional uint64 response_time_sec = 12;
+
+ // The time at which the DNS response message was sent or received.
+ // This is the seconds fraction, expressed as a count of nanoseconds.
+ optional fixed32 response_time_nsec = 13;
+
+ // The responder's original wire-format DNS response message, verbatim.
+ optional bytes response_message = 14;
+}
+
+// All fields except for 'type' in the Message schema are optional.
+// It is recommended that at least the following fields be filled in for
+// particular types of Messages.
+
+// AUTH_QUERY:
+// socket_family, socket_protocol
+// query_address, query_port
+// query_message
+// query_time_sec, query_time_nsec
+
+// AUTH_RESPONSE:
+// socket_family, socket_protocol
+// query_address, query_port
+// query_time_sec, query_time_nsec
+// response_message
+// response_time_sec, response_time_nsec
+
+// RESOLVER_QUERY:
+// socket_family, socket_protocol
+// query_name, query_type, query_class
+// query_message
+// query_time_sec, query_time_nsec
+// query_zone
+// response_address, response_port
+
+// RESOLVER_RESPONSE:
+// socket_family, socket_protocol
+// query_name, query_type, query_class
+// query_time_sec, query_time_nsec
+// query_zone
+// response_address, response_port
+// response_message
+// response_time_sec, response_time_nsec
+
+// CLIENT_QUERY:
+// socket_family, socket_protocol
+// query_message
+// query_time_sec, query_time_nsec
+
+// CLIENT_RESPONSE:
+// socket_family, socket_protocol
+// query_time_sec, query_time_nsec
+// response_message
+// response_time_sec, response_time_nsec
--- /dev/null
+#ifndef UNBOUND_DNSTAP_CONFIG_H
+#define UNBOUND_DNSTAP_CONFIG_H
+
+/*
+ * Process this file (dnstap_config.h.in) with AC_CONFIG_FILES to generate
+ * dnstap_config.h.
+ *
+ * This file exists so that USE_DNSTAP can be used without including config.h.
+ */
+
+#if @ENABLE_DNSTAP@ /* ENABLE_DNSTAP */
+# ifndef USE_DNSTAP
+# define USE_DNSTAP 1
+# endif
+#endif
+
+#endif /* UNBOUND_DNSTAP_CONFIG_H */
--- /dev/null
+The DNS64 code was written by Viagenie, 2009, by Simon Perrault as part
+of the Ecdysis project. The code is copyright by them, and has the BSD
+license (see the dns64/dns64.c file).
+
+To enable DNS64 functionality in Unbound, two directives in unbound.conf must
+be edited:
+
+1. The "module-config" directive must start with "dns64". For example:
+
+ module-config: "dns64 validator iterator"
+
+If you're not using DNSSEC then you may remove "validator".
+
+2. The "dns64-prefix" directive indicates your DNS64 prefix. For example:
+
+ dns64-prefix: 64:FF9B::/96
+
+The prefix must be a /96 or shorter.
+
+To test that things are working right, perform a query against Unbound for a
+domain name for which no AAAA record exists. You should see a AAAA record in
+the answer section. The corresponding IPv6 address will be inside the DNS64
+prefix. For example:
+
+ $ unbound -c unbound.conf
+ $ dig @localhost jazz-v4.viagenie.ca aaaa
+ [...]
+ ;; ANSWER SECTION:
+ jazz-v4.viagenie.ca. 86400 IN AAAA 64:ff9b::ce7b:1f02
+
--- /dev/null
+/*
+ * file_py3.i: Typemaps for FILE* for Python 3
+ *
+ * Copyright (c) 2011, Karel Slany (karel.slany AT nic.cz)
+ * All rights reserved.
+ *
+ * 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 COPYRIGHT OWNER 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.
+ */
+
+%{
+#include <unistd.h>
+#include <fcntl.h>
+%}
+
+%types(FILE *);
+
+//#define SWIG_FILE3_DEBUG
+
+/* converts basic file descriptor flags onto a string */
+%fragment("fdfl_to_str", "header") {
+const char *
+fdfl_to_str(int fdfl) {
+
+ static const char * const file_mode[] = {"w+", "w", "r"};
+
+ if (fdfl & O_RDWR) {
+ return file_mode[0];
+ } else if (fdfl & O_WRONLY) {
+ return file_mode[1];
+ } else {
+ return file_mode[2];
+ }
+}
+}
+
+%fragment("is_obj_file", "header") {
+int
+is_obj_file(PyObject *obj) {
+ int fd, fdfl;
+ if (!PyLong_Check(obj) && /* is not an integer */
+ PyObject_HasAttrString(obj, "fileno") && /* has fileno method */
+ (PyObject_CallMethod(obj, "flush", NULL) != NULL) && /* flush() succeeded */
+ ((fd = PyObject_AsFileDescriptor(obj)) != -1) && /* got file descriptor */
+ ((fdfl = fcntl(fd, F_GETFL)) != -1) /* got descriptor flags */
+ ) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+}
+
+%fragment("obj_to_file","header", fragment="fdfl_to_str,is_obj_file") {
+FILE *
+obj_to_file(PyObject *obj) {
+ int fd, fdfl;
+ FILE *fp;
+ if (is_obj_file(obj)) {
+ fd = PyObject_AsFileDescriptor(obj);
+ fdfl = fcntl(fd, F_GETFL);
+ fp = fdopen(dup(fd), fdfl_to_str(fdfl)); /* the FILE* must be flushed
+ and closed after being used */
+#ifdef SWIG_FILE3_DEBUG
+ fprintf(stderr, "opening fd %d (fl %d \"%s\") as FILE %p\n",
+ fd, fdfl, fdfl_to_str(fdfl), (void *)fp);
+#endif
+ return fp;
+ }
+ return NULL;
+}
+}
+
+/* returns -1 if error occurred */
+/* caused magic SWIG Syntax errors when was commented out */
+#if 0
+%fragment("dispose_file", "header") {
+int
+dispose_file(FILE **fp) {
+#ifdef SWIG_FILE3_DEBUG
+ fprintf(stderr, "flushing FILE %p\n", (void *)fp);
+#endif
+ if (*fp == NULL) {
+ return 0;
+ }
+ if ((fflush(*fp) == 0) && /* flush file */
+ (fclose(*fp) == 0)) { /* close file */
+ *fp = NULL;
+ return 0;
+ }
+ return -1;
+}
+}
+#endif
+
+%typemap(arginit, noblock = 1) FILE* {
+ $1 = NULL;
+}
+
+/*
+ * added due to ub_ctx_debugout since since it is overloaded:
+ * takes void* and FILE*. In reality only FILE* but the wrapper
+ * and the function is declared in such way.
+ */
+%typemap(typecheck, noblock = 1, fragment = "is_obj_file", precedence = SWIG_TYPECHECK_POINTER) FILE* {
+ $1 = is_obj_file($input);
+}
+
+%typemap(check, noblock = 1) FILE* {
+ if ($1 == NULL) {
+ /* The generated wrapper function raises TypeError on mismatching types. */
+ SWIG_exception_fail(SWIG_TypeError, "in method '" "$symname" "', argument "
+ "$argnum"" of type '" "$type""'");
+ }
+}
+
+%typemap(in, noblock = 1, fragment = "obj_to_file") FILE* {
+ $1 = obj_to_file($input);
+}
+
+/*
+ * Commented out due the way how ub_ctx_debugout() uses the parameter.
+ * This typemap would cause the FILE* to be closed after return from
+ * the function. This caused Python interpreter to crash, since the
+ * function just stores the FILE* internally in ctx and use it for
+ * logging. So we'll leave the closing of the file on the OS.
+ */
+/*%typemap(freearg, noblock = 1, fragment = "dispose_file") FILE* {
+ if (dispose_file(&$1) == -1) {
+ SWIG_exception_fail(SWIG_IOError, "closing file in method '" "$symname" "', argument "
+ "$argnum"" of type '" "$type""'");
+ }
+}*/
--- /dev/null
+/*
+ * libunbound/worker.h - prototypes for worker methods.
+ *
+ * Copyright (c) 2007, 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 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.
+ */
+
+/**
+ * \file
+ *
+ * This file declares the methods any worker has to implement.
+ */
+
+#ifndef LIBUNBOUND_WORKER_H
+#define LIBUNBOUND_WORKER_H
+
+#include "sldns/sbuffer.h"
+#include "util/data/packed_rrset.h" /* for enum sec_status */
+struct comm_reply;
+struct comm_point;
+struct module_qstate;
+struct tube;
+
+/**
+ * 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 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 addr: where to.
+ * @param addrlen: length of addr.
+ * @param zone: delegation point name.
+ * @param zonelen: length of zone name wireformat dname.
+ * @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 sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ struct module_qstate* q);
+
+/** process incoming replies from the network */
+int libworker_handle_reply(struct comm_point* c, void* arg, int error,
+ struct comm_reply* reply_info);
+
+/** process incoming serviced query replies from the network */
+int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
+ struct comm_reply* reply_info);
+
+/** handle control command coming into server */
+void libworker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len,
+ int err, void* arg);
+
+/** mesh callback with fg results */
+void libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf,
+ enum sec_status s, char* why_bogus);
+
+/** mesh callback with bg results */
+void libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf,
+ enum sec_status s, char* why_bogus);
+
+/** mesh callback with event results */
+void libworker_event_done_cb(void* arg, int rcode, struct sldns_buffer* buf,
+ enum sec_status s, char* why_bogus);
+
+/**
+ * Worker signal handler function. User argument is the worker itself.
+ * @param sig: signal number.
+ * @param arg: the worker (main worker) that handles signals.
+ */
+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 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 addr: where to.
+ * @param addrlen: length of addr.
+ * @param zone: wireformat dname of the zone.
+ * @param zonelen: length of zone name.
+ * @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 sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ struct module_qstate* q);
+
+/**
+ * process control messages from the main thread. Frees the control
+ * command message.
+ * @param tube: tube control message came on.
+ * @param msg: message contents. Is freed.
+ * @param len: length of message.
+ * @param error: if error (NETEVENT_*) happened.
+ * @param arg: user argument
+ */
+void worker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len,
+ int error, void* arg);
+
+/** handles callbacks from listening event interface */
+int worker_handle_request(struct comm_point* c, void* arg, int error,
+ struct comm_reply* repinfo);
+
+/** process incoming replies from the network */
+int worker_handle_reply(struct comm_point* c, void* arg, int error,
+ struct comm_reply* reply_info);
+
+/** process incoming serviced query replies from the network */
+int worker_handle_service_reply(struct comm_point* c, void* arg, int error,
+ struct comm_reply* reply_info);
+
+/** cleanup the cache to remove all rrset IDs from it, arg is worker */
+void worker_alloc_cleanup(void* arg);
+
+/** statistics timer callback handler */
+void worker_stat_timer_cb(void* arg);
+
+/** probe timer callback handler */
+void worker_probe_timer_cb(void* arg);
+
+/** start accept callback handler */
+void worker_start_accept(void* arg);
+
+/** stop accept callback handler */
+void worker_stop_accept(void* arg);
+
+/** handle remote control accept callbacks */
+int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*);
+
+/** handle remote control data callbacks */
+int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*);
+
+/** routine to printout option values over SSL */
+void remote_get_opt_ssl(char* line, void* arg);
+
+#endif /* LIBUNBOUND_WORKER_H */
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.4.2
+# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.11
# automake: $automake_version
# autoconf: $autoconf_version
#
PROGRAM=libtool
PACKAGE=libtool
-VERSION=2.4.2
+VERSION="2.4.2 Debian-2.4.2-1.11"
TIMESTAMP=""
package_revision=1.3337
case $pass in
dlopen) libs="$dlfiles" ;;
dlpreopen) libs="$dlprefiles" ;;
- link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ link)
+ libs="$deplibs %DEPLIBS%"
+ test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+ ;;
esac
fi
if test "$linkmode,$pass" = "lib,dlpreopen"; then
# It is a libtool convenience library, so add in its objects.
func_append convenience " $ladir/$objdir/$old_library"
func_append old_convenience " $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if $opt_preserve_dup_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done
elif test "$linkmode" != prog && test "$linkmode" != lib; then
func_fatal_error "\`$lib' is not a convenience library"
fi
- tmp_libs=
- for deplib in $dependency_libs; do
- deplibs="$deplib $deplibs"
- if $opt_preserve_dup_deps ; then
- case "$tmp_libs " in
- *" $deplib "*) func_append specialdeplibs " $deplib" ;;
- esac
- fi
- func_append tmp_libs " $deplib"
- done
continue
fi # $pass = conv
revision="$number_minor"
lt_irix_increment=no
;;
+ *)
+ func_fatal_configuration "$modename: unknown library version type \`$version_type'"
+ ;;
esac
;;
no)
--- /dev/null
+/*
+ * keyraw.c - raw key operations and conversions
+ *
+ * (c) NLnet Labs, 2004-2008
+ *
+ * See the file LICENSE for the license
+ */
+/**
+ * \file
+ * Implementation of raw DNSKEY functions (work on wire rdata).
+ */
+
+#include "config.h"
+#include "sldns/keyraw.h"
+#include "sldns/rrdef.h"
+
+#ifdef HAVE_SSL
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+# include <openssl/engine.h>
+#endif
+#endif /* HAVE_SSL */
+
+size_t
+sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
+ const size_t len, int alg)
+{
+ /* for DSA keys */
+ uint8_t t;
+
+ /* for RSA keys */
+ uint16_t exp;
+ uint16_t int16;
+
+ switch ((sldns_algorithm)alg) {
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ if (len > 0) {
+ t = keydata[0];
+ return (64 + t*8)*8;
+ } else {
+ return 0;
+ }
+ break;
+ case LDNS_RSAMD5:
+ case LDNS_RSASHA1:
+ case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA2
+ case LDNS_RSASHA256:
+ case LDNS_RSASHA512:
+#endif
+ if (len > 0) {
+ if (keydata[0] == 0) {
+ /* big exponent */
+ if (len > 3) {
+ memmove(&int16, keydata + 1, 2);
+ exp = ntohs(int16);
+ return (len - exp - 3)*8;
+ } else {
+ return 0;
+ }
+ } else {
+ exp = keydata[0];
+ return (len-exp-1)*8;
+ }
+ } else {
+ return 0;
+ }
+ break;
+#ifdef USE_GOST
+ case LDNS_ECC_GOST:
+ return 512;
+#endif
+#ifdef USE_ECDSA
+ case LDNS_ECDSAP256SHA256:
+ return 256;
+ case LDNS_ECDSAP384SHA384:
+ return 384;
+#endif
+ default:
+ return 0;
+ }
+}
+
+uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
+{
+ if(keysize < 4) {
+ return 0;
+ }
+ /* look at the algorithm field, copied from 2535bis */
+ if (key[3] == LDNS_RSAMD5) {
+ uint16_t ac16 = 0;
+ if (keysize > 4) {
+ memmove(&ac16, key + keysize - 3, 2);
+ }
+ ac16 = ntohs(ac16);
+ return (uint16_t) ac16;
+ } else {
+ size_t i;
+ uint32_t ac32 = 0;
+ for (i = 0; i < keysize; ++i) {
+ ac32 += (i & 1) ? key[i] : key[i] << 8;
+ }
+ ac32 += (ac32 >> 16) & 0xFFFF;
+ return (uint16_t) (ac32 & 0xFFFF);
+ }
+}
+
+#ifdef HAVE_SSL
+#ifdef USE_GOST
+/** store GOST engine reference loaded into OpenSSL library */
+ENGINE* sldns_gost_engine = NULL;
+
+int
+sldns_key_EVP_load_gost_id(void)
+{
+ static int gost_id = 0;
+ const EVP_PKEY_ASN1_METHOD* meth;
+ ENGINE* e;
+
+ if(gost_id) return gost_id;
+
+ /* see if configuration loaded gost implementation from other engine*/
+ meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
+ if(meth) {
+ EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
+ return gost_id;
+ }
+
+ /* see if engine can be loaded already */
+ e = ENGINE_by_id("gost");
+ if(!e) {
+ /* load it ourself, in case statically linked */
+ ENGINE_load_builtin_engines();
+ ENGINE_load_dynamic();
+ e = ENGINE_by_id("gost");
+ }
+ if(!e) {
+ /* no gost engine in openssl */
+ return 0;
+ }
+ if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ return 0;
+ }
+
+ meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
+ if(!meth) {
+ /* algo not found */
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ return 0;
+ }
+ /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
+ * on some platforms this frees up the meth and unloads gost stuff */
+ sldns_gost_engine = e;
+
+ EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
+ return gost_id;
+}
+
+void sldns_key_EVP_unload_gost(void)
+{
+ if(sldns_gost_engine) {
+ ENGINE_finish(sldns_gost_engine);
+ ENGINE_free(sldns_gost_engine);
+ sldns_gost_engine = NULL;
+ }
+}
+#endif /* USE_GOST */
+
+DSA *
+sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
+{
+ uint8_t T;
+ uint16_t length;
+ uint16_t offset;
+ DSA *dsa;
+ BIGNUM *Q; BIGNUM *P;
+ BIGNUM *G; BIGNUM *Y;
+
+ if(len == 0)
+ return NULL;
+ T = (uint8_t)key[0];
+ length = (64 + T * 8);
+ offset = 1;
+
+ if (T > 8) {
+ return NULL;
+ }
+ if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
+ return NULL;
+
+ Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
+ offset += SHA_DIGEST_LENGTH;
+
+ P = BN_bin2bn(key+offset, (int)length, NULL);
+ offset += length;
+
+ G = BN_bin2bn(key+offset, (int)length, NULL);
+ offset += length;
+
+ Y = BN_bin2bn(key+offset, (int)length, NULL);
+ offset += length;
+
+ /* create the key and set its properties */
+ if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
+ BN_free(Q);
+ BN_free(P);
+ BN_free(G);
+ BN_free(Y);
+ return NULL;
+ }
+#ifndef S_SPLINT_S
+ dsa->p = P;
+ dsa->q = Q;
+ dsa->g = G;
+ dsa->pub_key = Y;
+#endif /* splint */
+
+ return dsa;
+}
+
+RSA *
+sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
+{
+ uint16_t offset;
+ uint16_t exp;
+ uint16_t int16;
+ RSA *rsa;
+ BIGNUM *modulus;
+ BIGNUM *exponent;
+
+ if (len == 0)
+ return NULL;
+ if (key[0] == 0) {
+ if(len < 3)
+ return NULL;
+ memmove(&int16, key+1, 2);
+ exp = ntohs(int16);
+ offset = 3;
+ } else {
+ exp = key[0];
+ offset = 1;
+ }
+
+ /* key length at least one */
+ if(len < (size_t)offset + exp + 1)
+ return NULL;
+
+ /* Exponent */
+ exponent = BN_new();
+ if(!exponent) return NULL;
+ (void) BN_bin2bn(key+offset, (int)exp, exponent);
+ offset += exp;
+
+ /* Modulus */
+ modulus = BN_new();
+ if(!modulus) {
+ BN_free(exponent);
+ return NULL;
+ }
+ /* length of the buffer must match the key length! */
+ (void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
+
+ rsa = RSA_new();
+ if(!rsa) {
+ BN_free(exponent);
+ BN_free(modulus);
+ return NULL;
+ }
+#ifndef S_SPLINT_S
+ rsa->n = modulus;
+ rsa->e = exponent;
+#endif /* splint */
+
+ return rsa;
+}
+
+#ifdef USE_GOST
+EVP_PKEY*
+sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
+{
+ /* prefix header for X509 encoding */
+ uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
+ 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
+ 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
+ 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
+ unsigned char encoded[37+64];
+ const unsigned char* pp;
+ if(keylen != 64) {
+ /* key wrong size */
+ return NULL;
+ }
+
+ /* create evp_key */
+ memmove(encoded, asn, 37);
+ memmove(encoded+37, key, 64);
+ pp = (unsigned char*)&encoded[0];
+
+ return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
+}
+#endif /* USE_GOST */
+
+#ifdef USE_ECDSA
+EVP_PKEY*
+sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
+{
+ unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
+ const unsigned char* pp = buf;
+ EVP_PKEY *evp_key;
+ EC_KEY *ec;
+ /* check length, which uncompressed must be 2 bignums */
+ if(algo == LDNS_ECDSAP256SHA256) {
+ if(keylen != 2*256/8) return NULL;
+ ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ } else if(algo == LDNS_ECDSAP384SHA384) {
+ if(keylen != 2*384/8) return NULL;
+ ec = EC_KEY_new_by_curve_name(NID_secp384r1);
+ } else ec = NULL;
+ if(!ec) return NULL;
+ if(keylen+1 > sizeof(buf)) { /* sanity check */
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ /* prepend the 0x02 (from docs) (or actually 0x04 from implementation
+ * of openssl) for uncompressed data */
+ buf[0] = POINT_CONVERSION_UNCOMPRESSED;
+ memmove(buf+1, key, keylen);
+ if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ evp_key = EVP_PKEY_new();
+ if(!evp_key) {
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
+ EVP_PKEY_free(evp_key);
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ return evp_key;
+}
+#endif /* USE_ECDSA */
+
+int
+sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
+ const EVP_MD* md)
+{
+ EVP_MD_CTX* ctx;
+ ctx = EVP_MD_CTX_create();
+ if(!ctx)
+ return 0;
+ if(!EVP_DigestInit_ex(ctx, md, NULL) ||
+ !EVP_DigestUpdate(ctx, data, len) ||
+ !EVP_DigestFinal_ex(ctx, dest, NULL)) {
+ EVP_MD_CTX_destroy(ctx);
+ return 0;
+ }
+ EVP_MD_CTX_destroy(ctx);
+ return 1;
+}
+#endif /* HAVE_SSL */
--- /dev/null
+/*
+ * keyraw.h -- raw key and signature access and conversion
+ *
+ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+
+/**
+ * \file
+ *
+ * raw key and signature access and conversion
+ *
+ * Since those functions heavily rely op cryptographic operations,
+ * this module is dependent on openssl.
+ *
+ */
+
+#ifndef LDNS_KEYRAW_H
+#define LDNS_KEYRAW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if LDNS_BUILD_CONFIG_HAVE_SSL
+# include <openssl/ssl.h>
+# include <openssl/evp.h>
+#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+
+/**
+ * get the length of the keydata in bits
+ * \param[in] keydata the raw key data
+ * \param[in] len the length of the keydata
+ * \param[in] alg the cryptographic algorithm this is a key for
+ * \return the keysize in bits, or 0 on error
+ */
+size_t sldns_rr_dnskey_key_size_raw(const unsigned char *keydata,
+ const size_t len, int alg);
+
+/**
+ * Calculates keytag of DNSSEC key, operates on wireformat rdata.
+ * \param[in] key the key as uncompressed wireformat rdata.
+ * \param[in] keysize length of key data.
+ * \return the keytag
+ */
+uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize);
+
+#if LDNS_BUILD_CONFIG_HAVE_SSL
+/**
+ * Get the PKEY id for GOST, loads GOST into openssl as a side effect.
+ * Only available if GOST is compiled into the library and openssl.
+ * \return the gost id for EVP_CTX creation.
+ */
+int sldns_key_EVP_load_gost_id(void);
+
+/** Release the engine reference held for the GOST engine. */
+void sldns_key_EVP_unload_gost(void);
+
+/**
+ * Like sldns_key_buf2dsa, but uses raw buffer.
+ * \param[in] key the uncompressed wireformat of the key.
+ * \param[in] len length of key data
+ * \return a DSA * structure with the key material
+ */
+DSA *sldns_key_buf2dsa_raw(unsigned char* key, size_t len);
+
+/**
+ * Converts a holding buffer with key material to EVP PKEY in openssl.
+ * Only available if ldns was compiled with GOST.
+ * \param[in] key data to convert
+ * \param[in] keylen length of the key data
+ * \return the key or NULL on error.
+ */
+EVP_PKEY* sldns_gost2pkey_raw(unsigned char* key, size_t keylen);
+
+/**
+ * Converts a holding buffer with key material to EVP PKEY in openssl.
+ * Only available if ldns was compiled with ECDSA.
+ * \param[in] key data to convert
+ * \param[in] keylen length of the key data
+ * \param[in] algo precise algorithm to initialize ECC group values.
+ * \return the key or NULL on error.
+ */
+EVP_PKEY* sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
+
+/**
+ * Like sldns_key_buf2rsa, but uses raw buffer.
+ * \param[in] key the uncompressed wireformat of the key.
+ * \param[in] len length of key data
+ * \return a RSA * structure with the key material
+ */
+RSA *sldns_key_buf2rsa_raw(unsigned char* key, size_t len);
+
+/**
+ * Utility function to calculate hash using generic EVP_MD pointer.
+ * \param[in] data the data to hash.
+ * \param[in] len length of data.
+ * \param[out] dest the destination of the hash, must be large enough.
+ * \param[in] md the message digest to use.
+ * \return true if worked, false on failure.
+ */
+int sldns_digest_evp(unsigned char* data, unsigned int len,
+ unsigned char* dest, const EVP_MD* md);
+
+#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_KEYRAW_H */
--- /dev/null
+/*
+ * a generic (simple) parser. Use to parse rr's, private key
+ * information and /etc/resolv.conf files
+ *
+ * a Net::DNS like library for C
+ * LibDNS Team @ NLnet Labs
+ * (c) NLnet Labs, 2005-2006
+ * See the file LICENSE for the license
+ */
+#include "config.h"
+#include "sldns/parse.h"
+#include "sldns/parseutil.h"
+#include "sldns/sbuffer.h"
+
+#include <limits.h>
+#include <strings.h>
+
+sldns_lookup_table sldns_directive_types[] = {
+ { LDNS_DIR_TTL, "$TTL" },
+ { LDNS_DIR_ORIGIN, "$ORIGIN" },
+ { LDNS_DIR_INCLUDE, "$INCLUDE" },
+ { 0, NULL }
+};
+
+/* add max_limit here? */
+ssize_t
+sldns_fget_token(FILE *f, char *token, const char *delim, size_t limit)
+{
+ return sldns_fget_token_l(f, token, delim, limit, NULL);
+}
+
+ssize_t
+sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
+{
+ int c, prev_c;
+ int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
+ int com, quoted;
+ char *t;
+ size_t i;
+ const char *d;
+ const char *del;
+
+ /* standard delimeters */
+ if (!delim) {
+ /* from isspace(3) */
+ del = LDNS_PARSE_NORMAL;
+ } else {
+ del = delim;
+ }
+
+ p = 0;
+ i = 0;
+ com = 0;
+ quoted = 0;
+ prev_c = 0;
+ t = token;
+ if (del[0] == '"') {
+ quoted = 1;
+ }
+ while ((c = getc(f)) != EOF) {
+ if (c == '\r') /* carriage return */
+ c = ' ';
+ if (c == '(' && prev_c != '\\' && !quoted) {
+ /* this only counts for non-comments */
+ if (com == 0) {
+ p++;
+ }
+ prev_c = c;
+ continue;
+ }
+
+ if (c == ')' && prev_c != '\\' && !quoted) {
+ /* this only counts for non-comments */
+ if (com == 0) {
+ p--;
+ }
+ prev_c = c;
+ continue;
+ }
+
+ if (p < 0) {
+ /* more ) then ( - close off the string */
+ *t = '\0';
+ return 0;
+ }
+
+ /* do something with comments ; */
+ if (c == ';' && quoted == 0) {
+ if (prev_c != '\\') {
+ com = 1;
+ }
+ }
+ if (c == '\"' && com == 0 && prev_c != '\\') {
+ quoted = 1 - quoted;
+ }
+
+ if (c == '\n' && com != 0) {
+ /* comments */
+ com = 0;
+ *t = ' ';
+ if (line_nr) {
+ *line_nr = *line_nr + 1;
+ }
+ if (p == 0 && i > 0) {
+ goto tokenread;
+ } else {
+ prev_c = c;
+ continue;
+ }
+ }
+
+ if (com == 1) {
+ *t = ' ';
+ prev_c = c;
+ continue;
+ }
+
+ if (c == '\n' && p != 0 && t > token) {
+ /* in parentheses */
+ if (line_nr) {
+ *line_nr = *line_nr + 1;
+ }
+ *t++ = ' ';
+ prev_c = c;
+ continue;
+ }
+
+ /* check if we hit the delim */
+ for (d = del; *d; d++) {
+ if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
+ if (c == '\n' && line_nr) {
+ *line_nr = *line_nr + 1;
+ }
+ goto tokenread;
+ }
+ }
+ if (c != '\0' && c != '\n') {
+ i++;
+ }
+ if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+ *t = '\0';
+ return -1;
+ }
+ if (c != '\0' && c != '\n') {
+ *t++ = c;
+ }
+ if (c == '\\' && prev_c == '\\')
+ prev_c = 0;
+ else prev_c = c;
+ }
+ *t = '\0';
+ if (c == EOF) {
+ return (ssize_t)i;
+ }
+
+ if (i == 0) {
+ /* nothing read */
+ return -1;
+ }
+ if (p != 0) {
+ return -1;
+ }
+ return (ssize_t)i;
+
+tokenread:
+ if(*del == '"')
+ /* do not skip over quotes after the string, they are part
+ * of the next string. But skip over whitespace (if needed)*/
+ sldns_fskipcs_l(f, del+1, line_nr);
+ else sldns_fskipcs_l(f, del, line_nr);
+ *t = '\0';
+ if (p != 0) {
+ return -1;
+ }
+
+ return (ssize_t)i;
+}
+
+ssize_t
+sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data,
+ const char *d_del, size_t data_limit)
+{
+ return sldns_fget_keyword_data_l(f, keyword, k_del, data, d_del,
+ data_limit, NULL);
+}
+
+ssize_t
+sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data,
+ const char *d_del, size_t data_limit, int *line_nr)
+{
+ /* we assume: keyword|sep|data */
+ char *fkeyword;
+ ssize_t i;
+
+ if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
+ return -1;
+ fkeyword = (char*)malloc(LDNS_MAX_KEYWORDLEN);
+ if(!fkeyword)
+ return -1;
+
+ i = sldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN);
+ if(i==0 || i==-1) {
+ free(fkeyword);
+ return -1;
+ }
+
+ /* case??? i instead of strlen? */
+ if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) {
+ /* whee! */
+ /* printf("%s\n%s\n", "Matching keyword", fkeyword); */
+ i = sldns_fget_token_l(f, data, d_del, data_limit, line_nr);
+ free(fkeyword);
+ return i;
+ } else {
+ /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/
+ free(fkeyword);
+ return -1;
+ }
+}
+
+int
+sldns_bgetc(sldns_buffer *buffer)
+{
+ if (!sldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
+ sldns_buffer_set_position(buffer, sldns_buffer_limit(buffer));
+ /* sldns_buffer_rewind(buffer);*/
+ return EOF;
+ }
+ return (int)sldns_buffer_read_u8(buffer);
+}
+
+ssize_t
+sldns_bget_token(sldns_buffer *b, char *token, const char *delim, size_t limit)
+{
+ return sldns_bget_token_par(b, token, delim, limit, NULL, NULL);
+}
+
+ssize_t
+sldns_bget_token_par(sldns_buffer *b, char *token, const char *delim,
+ size_t limit, int* par, const char* skipw)
+{
+ int c, lc;
+ int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
+ int com, quoted;
+ char *t;
+ size_t i;
+ const char *d;
+ const char *del;
+
+ /* standard delimiters */
+ if (!delim) {
+ /* from isspace(3) */
+ del = LDNS_PARSE_NORMAL;
+ } else {
+ del = delim;
+ }
+
+ p = (par?*par:0);
+ i = 0;
+ com = 0;
+ quoted = 0;
+ t = token;
+ lc = 0;
+ if (del[0] == '"') {
+ quoted = 1;
+ }
+
+ while ((c = sldns_bgetc(b)) != EOF) {
+ if (c == '\r') /* carriage return */
+ c = ' ';
+ if (c == '(' && lc != '\\' && !quoted) {
+ /* this only counts for non-comments */
+ if (com == 0) {
+ if(par) (*par)++;
+ p++;
+ }
+ lc = c;
+ continue;
+ }
+
+ if (c == ')' && lc != '\\' && !quoted) {
+ /* this only counts for non-comments */
+ if (com == 0) {
+ if(par) (*par)--;
+ p--;
+ }
+ lc = c;
+ continue;
+ }
+
+ if (p < 0) {
+ /* more ) then ( */
+ *t = '\0';
+ return 0;
+ }
+
+ /* do something with comments ; */
+ if (c == ';' && quoted == 0) {
+ if (lc != '\\') {
+ com = 1;
+ }
+ }
+ if (c == '"' && com == 0 && lc != '\\') {
+ quoted = 1 - quoted;
+ }
+
+ if (c == '\n' && com != 0) {
+ /* comments */
+ com = 0;
+ *t = ' ';
+ lc = c;
+ continue;
+ }
+
+ if (com == 1) {
+ *t = ' ';
+ lc = c;
+ continue;
+ }
+
+ if (c == '\n' && p != 0) {
+ /* in parentheses */
+ /* do not write ' ' if we want to skip spaces */
+ if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' '))))
+ *t++ = ' ';
+ lc = c;
+ continue;
+ }
+
+ /* check to skip whitespace at start, but also after ( */
+ if(skipw && i==0 && !com && !quoted && lc != '\\') {
+ if(strchr(skipw, c)) {
+ lc = c;
+ continue;
+ }
+ }
+
+ /* check if we hit the delim */
+ for (d = del; *d; d++) {
+ /* we can only exit if no parens or user tracks them */
+ if (c == *d && lc != '\\' && (p == 0 || par)) {
+ goto tokenread;
+ }
+ }
+
+ i++;
+ if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+ *t = '\0';
+ return -1;
+ }
+ *t++ = c;
+
+ if (c == '\\' && lc == '\\') {
+ lc = 0;
+ } else {
+ lc = c;
+ }
+ }
+ *t = '\0';
+ if (i == 0) {
+ /* nothing read */
+ return -1;
+ }
+ if (!par && p != 0) {
+ return -1;
+ }
+ return (ssize_t)i;
+
+tokenread:
+ if(*del == '"')
+ /* do not skip over quotes after the string, they are part
+ * of the next string. But skip over whitespace (if needed)*/
+ sldns_bskipcs(b, del+1);
+ else sldns_bskipcs(b, del);
+ *t = '\0';
+
+ if (!par && p != 0) {
+ return -1;
+ }
+ return (ssize_t)i;
+}
+
+
+void
+sldns_bskipcs(sldns_buffer *buffer, const char *s)
+{
+ int found;
+ char c;
+ const char *d;
+
+ while(sldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) {
+ c = (char) sldns_buffer_read_u8_at(buffer, buffer->_position);
+ found = 0;
+ for (d = s; *d; d++) {
+ if (*d == c) {
+ found = 1;
+ }
+ }
+ if (found && buffer->_limit > buffer->_position) {
+ buffer->_position += sizeof(char);
+ } else {
+ return;
+ }
+ }
+}
+
+void
+sldns_fskipcs(FILE *fp, const char *s)
+{
+ sldns_fskipcs_l(fp, s, NULL);
+}
+
+void
+sldns_fskipcs_l(FILE *fp, const char *s, int *line_nr)
+{
+ int found;
+ int c;
+ const char *d;
+
+ while ((c = fgetc(fp)) != EOF) {
+ if (line_nr && c == '\n') {
+ *line_nr = *line_nr + 1;
+ }
+ found = 0;
+ for (d = s; *d; d++) {
+ if (*d == c) {
+ found = 1;
+ }
+ }
+ if (!found) {
+ /* with getc, we've read too far */
+ ungetc(c, fp);
+ return;
+ }
+ }
+}
+
+ssize_t
+sldns_bget_keyword_data(sldns_buffer *b, const char *keyword, const char *k_del, char
+*data, const char *d_del, size_t data_limit)
+{
+ /* we assume: keyword|sep|data */
+ char *fkeyword;
+ ssize_t i;
+
+ if(strlen(keyword) >= LDNS_MAX_KEYWORDLEN)
+ return -1;
+ fkeyword = (char*)malloc(LDNS_MAX_KEYWORDLEN);
+ if(!fkeyword)
+ return -1; /* out of memory */
+
+ i = sldns_bget_token(b, fkeyword, k_del, data_limit);
+ if(i==0 || i==-1) {
+ free(fkeyword);
+ return -1; /* nothing read */
+ }
+
+ /* case??? */
+ if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) {
+ free(fkeyword);
+ /* whee, the match! */
+ /* retrieve it's data */
+ i = sldns_bget_token(b, data, d_del, 0);
+ return i;
+ } else {
+ free(fkeyword);
+ return -1;
+ }
+}
+
--- /dev/null
+/*
+ * parse.h
+ *
+ * a Net::DNS like library for C
+ * LibDNS Team @ NLnet Labs
+ * (c) NLnet Labs, 2005-2006
+ * See the file LICENSE for the license
+ */
+
+#ifndef LDNS_PARSE_H
+#define LDNS_PARSE_H
+
+struct sldns_buffer;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LDNS_PARSE_SKIP_SPACE "\f\n\r\v"
+#define LDNS_PARSE_NORMAL " \f\n\r\t\v"
+#define LDNS_PARSE_NO_NL " \t"
+#define LDNS_MAX_LINELEN 10230
+#define LDNS_MAX_KEYWORDLEN 32
+
+
+/**
+ * \file
+ *
+ * Contains some low-level parsing functions, mostly used in the _frm_str
+ * family of functions.
+ */
+
+/**
+ * different type of directives in zone files
+ * We now deal with $TTL, $ORIGIN and $INCLUDE.
+ * The latter is not implemented in ldns (yet)
+ */
+enum sldns_enum_directive
+{
+ LDNS_DIR_TTL,
+ LDNS_DIR_ORIGIN,
+ LDNS_DIR_INCLUDE
+};
+typedef enum sldns_enum_directive sldns_directive;
+
+/**
+ * returns a token/char from the stream F.
+ * This function deals with ( and ) in the stream,
+ * and ignores them when encountered
+ * \param[in] *f the file to read from
+ * \param[out] *token the read token is put here
+ * \param[in] *delim chars at which the parsing should stop
+ * \param[in] *limit how much to read. If 0 the builtin maximum is used
+ * \return 0 on error of EOF of the stream F. Otherwise return the length of what is read
+ */
+ssize_t sldns_fget_token(FILE *f, char *token, const char *delim, size_t limit);
+
+/**
+ * returns a token/char from the stream F.
+ * This function deals with ( and ) in the stream,
+ * and ignores when it finds them.
+ * \param[in] *f the file to read from
+ * \param[out] *token the token is put here
+ * \param[in] *delim chars at which the parsing should stop
+ * \param[in] *limit how much to read. If 0 use builtin maximum
+ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+ * \return 0 on error of EOF of F otherwise return the length of what is read
+ */
+ssize_t sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr);
+
+/**
+ * returns a token/char from the buffer b.
+ * This function deals with ( and ) in the buffer,
+ * and ignores when it finds them.
+ * \param[in] *b the buffer to read from
+ * \param[out] *token the token is put here
+ * \param[in] *delim chars at which the parsing should stop
+ * \param[in] *limit how much to read. If 0 the builtin maximum is used
+ * \param[in] *par if you pass nonNULL, set to 0 on first call, the parenthesis
+ * state is stored in it, for use on next call. User must check it is back
+ * to zero after last bget in string (for parse error). If you pass NULL,
+ * the entire parenthesized string is read in.
+ * \param[in] skipw string with whitespace to skip before the start of the
+ * token, like " ", or " \t", or NULL for none.
+ * \returns 0 on error of EOF of b. Otherwise return the length of what is read
+ */
+ssize_t sldns_bget_token_par(struct sldns_buffer *b, char *token, const char *delim, size_t limit, int* par, const char* skipw);
+
+/**
+ * returns a token/char from the buffer b.
+ * This function deals with ( and ) in the buffer,
+ * and ignores when it finds them.
+ * \param[in] *b the buffer to read from
+ * \param[out] *token the token is put here
+ * \param[in] *delim chars at which the parsing should stop
+ * \param[in] *limit how much to read. If 0 the builtin maximum is used
+ * \returns 0 on error of EOF of b. Otherwise return the length of what is read
+ */
+ssize_t sldns_bget_token(struct sldns_buffer *b, char *token, const char *delim, size_t limit);
+
+/*
+ * searches for keyword and delim in a file. Gives everything back
+ * after the keyword + k_del until we hit d_del
+ * \param[in] f file pointer to read from
+ * \param[in] keyword keyword to look for
+ * \param[in] k_del keyword delimeter
+ * \param[out] data the data found
+ * \param[in] d_del the data delimeter
+ * \param[in] data_limit maximum size the the data buffer
+ * \return the number of character read
+ */
+ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
+
+/*
+ * searches for keyword and delim. Gives everything back
+ * after the keyword + k_del until we hit d_del
+ * \param[in] f file pointer to read from
+ * \param[in] keyword keyword to look for
+ * \param[in] k_del keyword delimeter
+ * \param[out] data the data found
+ * \param[in] d_del the data delimeter
+ * \param[in] data_limit maximum size the the data buffer
+ * \param[in] line_nr pointer to an integer containing the current line number (for
+debugging purposes)
+ * \return the number of character read
+ */
+ssize_t sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit, int *line_nr);
+
+/*
+ * searches for keyword and delim in a buffer. Gives everything back
+ * after the keyword + k_del until we hit d_del
+ * \param[in] b buffer pointer to read from
+ * \param[in] keyword keyword to look for
+ * \param[in] k_del keyword delimeter
+ * \param[out] data the data found
+ * \param[in] d_del the data delimeter
+ * \param[in] data_limit maximum size the the data buffer
+ * \return the number of character read
+ */
+ssize_t sldns_bget_keyword_data(struct sldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
+
+/**
+ * returns the next character from a buffer. Advances the position pointer with 1.
+ * When end of buffer is reached returns EOF. This is the buffer's equivalent
+ * for getc().
+ * \param[in] *buffer buffer to read from
+ * \return EOF on failure otherwise return the character
+ */
+int sldns_bgetc(struct sldns_buffer *buffer);
+
+/**
+ * skips all of the characters in the given string in the buffer, moving
+ * the position to the first character that is not in *s.
+ * \param[in] *buffer buffer to use
+ * \param[in] *s characters to skip
+ * \return void
+ */
+void sldns_bskipcs(struct sldns_buffer *buffer, const char *s);
+
+/**
+ * skips all of the characters in the given string in the fp, moving
+ * the position to the first character that is not in *s.
+ * \param[in] *fp file to use
+ * \param[in] *s characters to skip
+ * \return void
+ */
+void sldns_fskipcs(FILE *fp, const char *s);
+
+
+/**
+ * skips all of the characters in the given string in the fp, moving
+ * the position to the first character that is not in *s.
+ * \param[in] *fp file to use
+ * \param[in] *s characters to skip
+ * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes)
+ * \return void
+ */
+void sldns_fskipcs_l(FILE *fp, const char *s, int *line_nr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_PARSE_H */
--- /dev/null
+/*
+ * parseutil.c - parse utilities for string and wire conversion
+ *
+ * (c) NLnet Labs, 2004-2006
+ *
+ * See the file LICENSE for the license
+ */
+/**
+ * \file
+ *
+ * Utility functions for parsing, base32(DNS variant) and base64 encoding
+ * and decoding, Hex, Time units, Escape codes.
+ */
+
+#include "config.h"
+#include "sldns/parseutil.h"
+#include <sys/time.h>
+#include <time.h>
+#include <ctype.h>
+
+sldns_lookup_table *
+sldns_lookup_by_name(sldns_lookup_table *table, const char *name)
+{
+ while (table->name != NULL) {
+ if (strcasecmp(name, table->name) == 0)
+ return table;
+ table++;
+ }
+ return NULL;
+}
+
+sldns_lookup_table *
+sldns_lookup_by_id(sldns_lookup_table *table, int id)
+{
+ while (table->name != NULL) {
+ if (table->id == id)
+ return table;
+ table++;
+ }
+ return NULL;
+}
+
+/* Number of days per month (except for February in leap years). */
+static const int mdays[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y)))
+#define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) - 1 ) : ((x) / (y)))
+
+static int
+is_leap_year(int year)
+{
+ return LDNS_MOD(year, 4) == 0 && (LDNS_MOD(year, 100) != 0
+ || LDNS_MOD(year, 400) == 0);
+}
+
+static int
+leap_days(int y1, int y2)
+{
+ --y1;
+ --y2;
+ return (LDNS_DIV(y2, 4) - LDNS_DIV(y1, 4)) -
+ (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) +
+ (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400));
+}
+
+/*
+ * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
+ */
+time_t
+sldns_mktime_from_utc(const struct tm *tm)
+{
+ int year = 1900 + tm->tm_year;
+ time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year);
+ time_t hours;
+ time_t minutes;
+ time_t seconds;
+ int i;
+
+ for (i = 0; i < tm->tm_mon; ++i) {
+ days += mdays[i];
+ }
+ if (tm->tm_mon > 1 && is_leap_year(year)) {
+ ++days;
+ }
+ days += tm->tm_mday - 1;
+
+ hours = days * 24 + tm->tm_hour;
+ minutes = hours * 60 + tm->tm_min;
+ seconds = minutes * 60 + tm->tm_sec;
+
+ return seconds;
+}
+
+#if SIZEOF_TIME_T <= 4
+
+static void
+sldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result)
+{
+ int year = 1970;
+ int new_year;
+
+ while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) {
+ new_year = year + (int) LDNS_DIV(days, 365);
+ days -= (new_year - year) * 365;
+ days -= leap_days(year, new_year);
+ year = new_year;
+ }
+ result->tm_year = year;
+ result->tm_yday = (int) days;
+}
+
+/* Number of days per month in a leap year. */
+static const int leap_year_mdays[] = {
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static void
+sldns_mon_and_mday_from_year_and_yday(struct tm *result)
+{
+ int idays = result->tm_yday;
+ const int *mon_lengths = is_leap_year(result->tm_year) ?
+ leap_year_mdays : mdays;
+
+ result->tm_mon = 0;
+ while (idays >= mon_lengths[result->tm_mon]) {
+ idays -= mon_lengths[result->tm_mon++];
+ }
+ result->tm_mday = idays + 1;
+}
+
+static void
+sldns_wday_from_year_and_yday(struct tm *result)
+{
+ result->tm_wday = 4 /* 1-1-1970 was a thursday */
+ + LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7)
+ + leap_days(1970, result->tm_year)
+ + result->tm_yday;
+ result->tm_wday = LDNS_MOD(result->tm_wday, 7);
+ if (result->tm_wday < 0) {
+ result->tm_wday += 7;
+ }
+}
+
+static struct tm *
+sldns_gmtime64_r(int64_t clock, struct tm *result)
+{
+ result->tm_isdst = 0;
+ result->tm_sec = (int) LDNS_MOD(clock, 60);
+ clock = LDNS_DIV(clock, 60);
+ result->tm_min = (int) LDNS_MOD(clock, 60);
+ clock = LDNS_DIV(clock, 60);
+ result->tm_hour = (int) LDNS_MOD(clock, 24);
+ clock = LDNS_DIV(clock, 24);
+
+ sldns_year_and_yday_from_days_since_epoch(clock, result);
+ sldns_mon_and_mday_from_year_and_yday(result);
+ sldns_wday_from_year_and_yday(result);
+ result->tm_year -= 1900;
+
+ return result;
+}
+
+#endif /* SIZEOF_TIME_T <= 4 */
+
+static int64_t
+sldns_serial_arithmitics_time(int32_t time, time_t now)
+{
+ int32_t offset = time - (int32_t) now;
+ return (int64_t) now + offset;
+}
+
+struct tm *
+sldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result)
+{
+#if SIZEOF_TIME_T <= 4
+ int64_t secs_since_epoch = sldns_serial_arithmitics_time(time, now);
+ return sldns_gmtime64_r(secs_since_epoch, result);
+#else
+ time_t secs_since_epoch = sldns_serial_arithmitics_time(time, now);
+ return gmtime_r(&secs_since_epoch, result);
+#endif
+}
+
+int
+sldns_hexdigit_to_int(char ch)
+{
+ switch (ch) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'a': case 'A': return 10;
+ case 'b': case 'B': return 11;
+ case 'c': case 'C': return 12;
+ case 'd': case 'D': return 13;
+ case 'e': case 'E': return 14;
+ case 'f': case 'F': return 15;
+ default:
+ return -1;
+ }
+}
+
+uint32_t
+sldns_str2period(const char *nptr, const char **endptr)
+{
+ int sign = 0;
+ uint32_t i = 0;
+ uint32_t seconds = 0;
+
+ for(*endptr = nptr; **endptr; (*endptr)++) {
+ switch (**endptr) {
+ case ' ':
+ case '\t':
+ break;
+ case '-':
+ if(sign == 0) {
+ sign = -1;
+ } else {
+ return seconds;
+ }
+ break;
+ case '+':
+ if(sign == 0) {
+ sign = 1;
+ } else {
+ return seconds;
+ }
+ break;
+ case 's':
+ case 'S':
+ seconds += i;
+ i = 0;
+ break;
+ case 'm':
+ case 'M':
+ seconds += i * 60;
+ i = 0;
+ break;
+ case 'h':
+ case 'H':
+ seconds += i * 60 * 60;
+ i = 0;
+ break;
+ case 'd':
+ case 'D':
+ seconds += i * 60 * 60 * 24;
+ i = 0;
+ break;
+ case 'w':
+ case 'W':
+ seconds += i * 60 * 60 * 24 * 7;
+ i = 0;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ i *= 10;
+ i += (**endptr - '0');
+ break;
+ default:
+ seconds += i;
+ /* disregard signedness */
+ return seconds;
+ }
+ }
+ seconds += i;
+ /* disregard signedness */
+ return seconds;
+}
+
+int
+sldns_parse_escape(uint8_t *ch_p, const char** str_p)
+{
+ uint16_t val;
+
+ if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) &&
+ (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) &&
+ (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) {
+
+ val = (uint16_t)(((*str_p)[0] - '0') * 100 +
+ ((*str_p)[1] - '0') * 10 +
+ ((*str_p)[2] - '0'));
+
+ if (val > 255) {
+ goto error;
+ }
+ *ch_p = (uint8_t)val;
+ *str_p += 3;
+ return 1;
+
+ } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) {
+
+ *ch_p = (uint8_t)*(*str_p)++;
+ return 1;
+ }
+error:
+ *str_p = NULL;
+ return 0; /* LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE */
+}
+
+/** parse one character, with escape codes */
+int
+sldns_parse_char(uint8_t *ch_p, const char** str_p)
+{
+ switch (**str_p) {
+
+ case '\0': return 0;
+
+ case '\\': *str_p += 1;
+ return sldns_parse_escape(ch_p, str_p);
+
+ default: *ch_p = (uint8_t)*(*str_p)++;
+ return 1;
+ }
+}
+
+size_t sldns_b32_ntop_calculate_size(size_t src_data_length)
+{
+ return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8;
+}
+
+size_t sldns_b32_ntop_calculate_size_no_padding(size_t src_data_length)
+{
+ return ((src_data_length + 3) * 8 / 5) - 4;
+}
+
+static int
+sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
+ int extended_hex, int add_padding)
+{
+ size_t ret_sz;
+ const char* b32 = extended_hex ? "0123456789abcdefghijklmnopqrstuv"
+ : "abcdefghijklmnopqrstuvwxyz234567";
+
+ size_t c = 0; /* c is used to carry partial base32 character over
+ * byte boundaries for sizes with a remainder.
+ * (i.e. src_sz % 5 != 0)
+ */
+
+ ret_sz = add_padding ? sldns_b32_ntop_calculate_size(src_sz)
+ : sldns_b32_ntop_calculate_size_no_padding(src_sz);
+
+ /* Do we have enough space? */
+ if (dst_sz < ret_sz + 1)
+ return -1;
+
+ /* We know the size; terminate the string */
+ dst[ret_sz] = '\0';
+
+ /* First process all chunks of five */
+ while (src_sz >= 5) {
+ /* 00000... ........ ........ ........ ........ */
+ dst[0] = b32[(src[0] ) >> 3];
+
+ /* .....111 11...... ........ ........ ........ */
+ dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6];
+
+ /* ........ ..22222. ........ ........ ........ */
+ dst[2] = b32[(src[1] & 0x3e) >> 1];
+
+ /* ........ .......3 3333.... ........ ........ */
+ dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4];
+
+ /* ........ ........ ....4444 4....... ........ */
+ dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7];
+
+ /* ........ ........ ........ .55555.. ........ */
+ dst[5] = b32[(src[3] & 0x7c) >> 2];
+
+ /* ........ ........ ........ ......66 666..... */
+ dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5];
+
+ /* ........ ........ ........ ........ ...77777 */
+ dst[7] = b32[(src[4] & 0x1f) ];
+
+ src_sz -= 5;
+ src += 5;
+ dst += 8;
+ }
+ /* Process what remains */
+ switch (src_sz) {
+ case 4: /* ........ ........ ........ ......66 666..... */
+ dst[6] = b32[(src[3] & 0x03) << 3];
+
+ /* ........ ........ ........ .55555.. ........ */
+ dst[5] = b32[(src[3] & 0x7c) >> 2];
+
+ /* ........ ........ ....4444 4....... ........ */
+ c = src[3] >> 7 ;
+ case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
+
+ /* ........ .......3 3333.... ........ ........ */
+ c = src[2] >> 4 ;
+ case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c];
+
+ /* ........ ..22222. ........ ........ ........ */
+ dst[2] = b32[(src[1] & 0x3e) >> 1];
+
+ /* .....111 11...... ........ ........ ........ */
+ c = src[1] >> 6 ;
+ case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c];
+
+ /* 00000... ........ ........ ........ ........ */
+ dst[0] = b32[ src[0] >> 3];
+ }
+ /* Add padding */
+ if (add_padding) {
+ switch (src_sz) {
+ case 1: dst[2] = '=';
+ dst[3] = '=';
+ case 2: dst[4] = '=';
+ case 3: dst[5] = '=';
+ dst[6] = '=';
+ case 4: dst[7] = '=';
+ }
+ }
+ return (int)ret_sz;
+}
+
+int
+sldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
+{
+ return sldns_b32_ntop_base(src, src_sz, dst, dst_sz, 0, 1);
+}
+
+int
+sldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
+ char* dst, size_t dst_sz)
+{
+ return sldns_b32_ntop_base(src, src_sz, dst, dst_sz, 1, 1);
+}
+
+size_t sldns_b32_pton_calculate_size(size_t src_text_length)
+{
+ return src_text_length * 5 / 8;
+}
+
+static int
+sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz,
+ int extended_hex, int check_padding)
+{
+ size_t i = 0;
+ char ch = '\0';
+ uint8_t buf[8];
+ uint8_t* start = dst;
+
+ while (src_sz) {
+ /* Collect 8 characters in buf (if possible) */
+ for (i = 0; i < 8; i++) {
+
+ do {
+ ch = *src++;
+ --src_sz;
+
+ } while (isspace((unsigned char)ch) && src_sz > 0);
+
+ if (ch == '=' || ch == '\0')
+ break;
+
+ else if (extended_hex)
+
+ if (ch >= '0' && ch <= '9')
+ buf[i] = (uint8_t)ch - '0';
+ else if (ch >= 'a' && ch <= 'v')
+ buf[i] = (uint8_t)ch - 'a' + 10;
+ else if (ch >= 'A' && ch <= 'V')
+ buf[i] = (uint8_t)ch - 'A' + 10;
+ else
+ return -1;
+
+ else if (ch >= 'a' && ch <= 'z')
+ buf[i] = (uint8_t)ch - 'a';
+ else if (ch >= 'A' && ch <= 'Z')
+ buf[i] = (uint8_t)ch - 'A';
+ else if (ch >= '2' && ch <= '7')
+ buf[i] = (uint8_t)ch - '2' + 26;
+ else
+ return -1;
+ }
+ /* Less that 8 characters. We're done. */
+ if (i < 8)
+ break;
+
+ /* Enough space available at the destination? */
+ if (dst_sz < 5)
+ return -1;
+
+ /* 00000... ........ ........ ........ ........ */
+ /* .....111 11...... ........ ........ ........ */
+ dst[0] = buf[0] << 3 | buf[1] >> 2;
+
+ /* .....111 11...... ........ ........ ........ */
+ /* ........ ..22222. ........ ........ ........ */
+ /* ........ .......3 3333.... ........ ........ */
+ dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
+
+ /* ........ .......3 3333.... ........ ........ */
+ /* ........ ........ ....4444 4....... ........ */
+ dst[2] = buf[3] << 4 | buf[4] >> 1;
+
+ /* ........ ........ ....4444 4....... ........ */
+ /* ........ ........ ........ .55555.. ........ */
+ /* ........ ........ ........ ......66 666..... */
+ dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
+
+ /* ........ ........ ........ ......66 666..... */
+ /* ........ ........ ........ ........ ...77777 */
+ dst[4] = buf[6] << 5 | buf[7];
+
+ dst += 5;
+ dst_sz -= 5;
+ }
+ /* Not ending on a eight byte boundary? */
+ if (i > 0 && i < 8) {
+
+ /* Enough space available at the destination? */
+ if (dst_sz < (i + 1) / 2)
+ return -1;
+
+ switch (i) {
+ case 7: /* ........ ........ ........ ......66 666..... */
+ /* ........ ........ ........ .55555.. ........ */
+ /* ........ ........ ....4444 4....... ........ */
+ dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
+
+ case 5: /* ........ ........ ....4444 4....... ........ */
+ /* ........ .......3 3333.... ........ ........ */
+ dst[2] = buf[3] << 4 | buf[4] >> 1;
+
+ case 4: /* ........ .......3 3333.... ........ ........ */
+ /* ........ ..22222. ........ ........ ........ */
+ /* .....111 11...... ........ ........ ........ */
+ dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
+
+ case 2: /* .....111 11...... ........ ........ ........ */
+ /* 00000... ........ ........ ........ ........ */
+ dst[0] = buf[0] << 3 | buf[1] >> 2;
+
+ break;
+
+ default:
+ return -1;
+ }
+ dst += (i + 1) / 2;
+
+ if (check_padding) {
+ /* Check remaining padding characters */
+ if (ch != '=')
+ return -1;
+
+ /* One down, 8 - i - 1 more to come... */
+ for (i = 8 - i - 1; i > 0; i--) {
+
+ do {
+ if (src_sz == 0)
+ return -1;
+ ch = *src++;
+ src_sz--;
+
+ } while (isspace((unsigned char)ch));
+
+ if (ch != '=')
+ return -1;
+ }
+ }
+ }
+ return dst - start;
+}
+
+int
+sldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
+{
+ return sldns_b32_pton_base(src, src_sz, dst, dst_sz, 0, 1);
+}
+
+int
+sldns_b32_pton_extended_hex(const char* src, size_t src_sz,
+ uint8_t* dst, size_t dst_sz)
+{
+ return sldns_b32_pton_base(src, src_sz, dst, dst_sz, 1, 1);
+}
+
+size_t sldns_b64_ntop_calculate_size(size_t srcsize)
+{
+ return ((((srcsize + 2) / 3) * 4) + 1);
+}
+
+/* RFC 1521, section 5.2.
+ *
+ * The encoding process represents 24-bit groups of input bits as output
+ * strings of 4 encoded characters. Proceeding from left to right, a
+ * 24-bit input group is formed by concatenating 3 8-bit input groups.
+ * These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ * of which is translated into a single digit in the base64 alphabet.
+ *
+ * This routine does not insert spaces or linebreaks after 76 characters.
+ */
+int sldns_b64_ntop(uint8_t const *src, size_t srclength,
+ char *target, size_t targsize)
+{
+ const char* b64 =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ const char pad64 = '=';
+ size_t i = 0, o = 0;
+ if(targsize < sldns_b64_ntop_calculate_size(srclength))
+ return -1;
+ /* whole chunks: xxxxxxyy yyyyzzzz zzwwwwww */
+ while(i+3 <= srclength) {
+ if(o+4 > targsize) return -1;
+ target[o] = b64[src[i] >> 2];
+ target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ];
+ target[o+2] = b64[ ((src[i+1]&0x0f)<<2) | (src[i+2]>>6) ];
+ target[o+3] = b64[ (src[i+2]&0x3f) ];
+ i += 3;
+ o += 4;
+ }
+ /* remainder */
+ switch(srclength - i) {
+ case 2:
+ /* two at end, converted into A B C = */
+ target[o] = b64[src[i] >> 2];
+ target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ];
+ target[o+2] = b64[ ((src[i+1]&0x0f)<<2) ];
+ target[o+3] = pad64;
+ i += 2;
+ o += 4;
+ break;
+ case 1:
+ /* one at end, converted into A B = = */
+ target[o] = b64[src[i] >> 2];
+ target[o+1] = b64[ ((src[i]&0x03)<<4) ];
+ target[o+2] = pad64;
+ target[o+3] = pad64;
+ i += 1;
+ o += 4;
+ break;
+ case 0:
+ default:
+ /* nothing */
+ break;
+ }
+ /* assert: i == srclength */
+ if(o+1 > targsize) return -1;
+ target[o] = 0;
+ return (int)o;
+}
+
+size_t sldns_b64_pton_calculate_size(size_t srcsize)
+{
+ return (((((srcsize + 3) / 4) * 3)) + 1);
+}
+
+int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
+{
+ const uint8_t pad64 = 64; /* is 64th in the b64 array */
+ const char* s = src;
+ uint8_t in[4];
+ size_t o = 0, incount = 0;
+
+ while(*s) {
+ /* skip any character that is not base64 */
+ /* conceptually we do:
+ const char* b64 = pad'=' is appended to array
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+ const char* d = strchr(b64, *s++);
+ and use d-b64;
+ */
+ char d = *s++;
+ if(d <= 'Z' && d >= 'A')
+ d -= 'A';
+ else if(d <= 'z' && d >= 'a')
+ d = d - 'a' + 26;
+ else if(d <= '9' && d >= '0')
+ d = d - '0' + 52;
+ else if(d == '+')
+ d = 62;
+ else if(d == '/')
+ d = 63;
+ else if(d == '=')
+ d = 64;
+ else continue;
+ in[incount++] = (uint8_t)d;
+ if(incount != 4)
+ continue;
+ /* process whole block of 4 characters into 3 output bytes */
+ if(in[3] == pad64 && in[2] == pad64) { /* A B = = */
+ if(o+1 > targsize)
+ return -1;
+ target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
+ o += 1;
+ break; /* we are done */
+ } else if(in[3] == pad64) { /* A B C = */
+ if(o+2 > targsize)
+ return -1;
+ target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
+ target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
+ o += 2;
+ break; /* we are done */
+ } else {
+ if(o+3 > targsize)
+ return -1;
+ /* write xxxxxxyy yyyyzzzz zzwwwwww */
+ target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
+ target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
+ target[o+2]= ((in[2]&0x03)<<6) | in[3];
+ o += 3;
+ }
+ incount = 0;
+ }
+ return (int)o;
+}
--- /dev/null
+/*
+ * parseutil.h - parse utilities for string and wire conversion
+ *
+ * (c) NLnet Labs, 2004
+ *
+ * See the file LICENSE for the license
+ */
+/**
+ * \file
+ *
+ * Utility functions for parsing, base32(DNS variant) and base64 encoding
+ * and decoding, Hex, Time units, Escape codes.
+ */
+
+#ifndef LDNS_PARSEUTIL_H
+#define LDNS_PARSEUTIL_H
+struct tm;
+
+/**
+ * A general purpose lookup table
+ *
+ * Lookup tables are arrays of (id, name) pairs,
+ * So you can for instance lookup the RCODE 3, which is "NXDOMAIN",
+ * and vice versa. The lookup tables themselves are defined wherever needed,
+ * for instance in host2str.c
+ */
+struct sldns_struct_lookup_table {
+ int id;
+ const char *name;
+};
+typedef struct sldns_struct_lookup_table sldns_lookup_table;
+
+/**
+ * Looks up the table entry by name, returns NULL if not found.
+ * \param[in] table the lookup table to search in
+ * \param[in] name what to search for
+ * \return the item found
+ */
+sldns_lookup_table *sldns_lookup_by_name(sldns_lookup_table table[],
+ const char *name);
+/**
+ * Looks up the table entry by id, returns NULL if not found.
+ * \param[in] table the lookup table to search in
+ * \param[in] id what to search for
+ * \return the item found
+ */
+sldns_lookup_table *sldns_lookup_by_id(sldns_lookup_table table[], int id);
+
+/**
+ * Convert TM to seconds since epoch (midnight, January 1st, 1970).
+ * Like timegm(3), which is not always available.
+ * \param[in] tm a struct tm* with the date
+ * \return the seconds since epoch
+ */
+time_t sldns_mktime_from_utc(const struct tm *tm);
+
+/**
+ * The function interprets time as the number of seconds since epoch
+ * with respect to now using serial arithmitics (rfc1982).
+ * That number of seconds is then converted to broken-out time information.
+ * This is especially usefull when converting the inception and expiration
+ * fields of RRSIG records.
+ *
+ * \param[in] time number of seconds since epoch (midnight, January 1st, 1970)
+ * to be intepreted as a serial arithmitics number relative to now.
+ * \param[in] now number of seconds since epoch (midnight, January 1st, 1970)
+ * to which the time value is compared to determine the final value.
+ * \param[out] result the struct with the broken-out time information
+ * \return result on success or NULL on error
+ */
+struct tm * sldns_serial_arithmitics_gmtime_r(int32_t time, time_t now, struct tm *result);
+
+/**
+ * converts a ttl value (like 5d2h) to a long.
+ * \param[in] nptr the start of the string
+ * \param[out] endptr points to the last char in case of error
+ * \return the convert duration value
+ */
+uint32_t sldns_str2period(const char *nptr, const char **endptr);
+
+/**
+ * Returns the int value of the given (hex) digit
+ * \param[in] ch the hex char to convert
+ * \return the converted decimal value
+ */
+int sldns_hexdigit_to_int(char ch);
+
+/**
+ * calculates the size needed to store the result of b64_ntop
+ */
+size_t sldns_b64_ntop_calculate_size(size_t srcsize);
+
+int sldns_b64_ntop(uint8_t const *src, size_t srclength,
+ char *target, size_t targsize);
+
+/**
+ * calculates the size needed to store the result of sldns_b64_pton
+ */
+size_t sldns_b64_pton_calculate_size(size_t srcsize);
+
+int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize);
+
+/**
+ * calculates the size needed to store the result of b32_ntop
+ */
+size_t sldns_b32_ntop_calculate_size(size_t src_data_length);
+
+size_t sldns_b32_ntop_calculate_size_no_padding(size_t src_data_length);
+
+int sldns_b32_ntop(const uint8_t* src_data, size_t src_data_length,
+ char* target_text_buffer, size_t target_text_buffer_size);
+
+int sldns_b32_ntop_extended_hex(const uint8_t* src_data, size_t src_data_length,
+ char* target_text_buffer, size_t target_text_buffer_size);
+
+/**
+ * calculates the size needed to store the result of b32_pton
+ */
+size_t sldns_b32_pton_calculate_size(size_t src_text_length);
+
+int sldns_b32_pton(const char* src_text, size_t src_text_length,
+ uint8_t* target_data_buffer, size_t target_data_buffer_size);
+
+int sldns_b32_pton_extended_hex(const char* src_text, size_t src_text_length,
+ uint8_t* target_data_buffer, size_t target_data_buffer_size);
+
+/*
+ * Checks whether the escaped value at **s is an octal value or
+ * a 'normally' escaped character (and not eos)
+ *
+ * @param ch_p: the parsed character
+ * @param str_p: the string. moved along for characters read.
+ * The string pointer at *s is increased by either 0 (on error), 1 (on
+ * normal escapes), or 3 (on octals)
+ *
+ * @return 0 on error
+ */
+int sldns_parse_escape(uint8_t *ch_p, const char** str_p);
+
+/**
+ * Parse one character, with escape codes,
+ * @param ch_p: the parsed character
+ * @param str_p: the string. moved along for characters read.
+ * @return 0 on error
+ */
+int sldns_parse_char(uint8_t *ch_p, const char** str_p);
+
+#endif /* LDNS_PARSEUTIL_H */
--- /dev/null
+/*
+ * pkthdr.h - packet header from wire conversion routines
+ *
+ * a Net::DNS like library for C
+ *
+ * (c) NLnet Labs, 2005-2006
+ *
+ * See the file LICENSE for the license
+ */
+
+/**
+ * \file
+ *
+ * Contains functions that translate dns data from the wire format (as sent
+ * by servers and clients) to the internal structures for the packet header.
+ */
+
+#ifndef LDNS_PKTHDR_H
+#define LDNS_PKTHDR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The length of the header */
+#define LDNS_HEADER_SIZE 12
+
+/* First octet of flags */
+#define LDNS_RD_MASK 0x01U
+#define LDNS_RD_SHIFT 0
+#define LDNS_RD_WIRE(wirebuf) (*(wirebuf+2) & LDNS_RD_MASK)
+#define LDNS_RD_SET(wirebuf) (*(wirebuf+2) |= LDNS_RD_MASK)
+#define LDNS_RD_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_RD_MASK)
+
+#define LDNS_TC_MASK 0x02U
+#define LDNS_TC_SHIFT 1
+#define LDNS_TC_WIRE(wirebuf) (*(wirebuf+2) & LDNS_TC_MASK)
+#define LDNS_TC_SET(wirebuf) (*(wirebuf+2) |= LDNS_TC_MASK)
+#define LDNS_TC_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_TC_MASK)
+
+#define LDNS_AA_MASK 0x04U
+#define LDNS_AA_SHIFT 2
+#define LDNS_AA_WIRE(wirebuf) (*(wirebuf+2) & LDNS_AA_MASK)
+#define LDNS_AA_SET(wirebuf) (*(wirebuf+2) |= LDNS_AA_MASK)
+#define LDNS_AA_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_AA_MASK)
+
+#define LDNS_OPCODE_MASK 0x78U
+#define LDNS_OPCODE_SHIFT 3
+#define LDNS_OPCODE_WIRE(wirebuf) ((*(wirebuf+2) & LDNS_OPCODE_MASK) >> LDNS_OPCODE_SHIFT)
+#define LDNS_OPCODE_SET(wirebuf, opcode) \
+ (*(wirebuf+2) = ((*(wirebuf+2)) & ~LDNS_OPCODE_MASK) | ((opcode) << LDNS_OPCODE_SHIFT))
+
+#define LDNS_QR_MASK 0x80U
+#define LDNS_QR_SHIFT 7
+#define LDNS_QR_WIRE(wirebuf) (*(wirebuf+2) & LDNS_QR_MASK)
+#define LDNS_QR_SET(wirebuf) (*(wirebuf+2) |= LDNS_QR_MASK)
+#define LDNS_QR_CLR(wirebuf) (*(wirebuf+2) &= ~LDNS_QR_MASK)
+
+/* Second octet of flags */
+#define LDNS_RCODE_MASK 0x0fU
+#define LDNS_RCODE_SHIFT 0
+#define LDNS_RCODE_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RCODE_MASK)
+#define LDNS_RCODE_SET(wirebuf, rcode) \
+ (*(wirebuf+3) = ((*(wirebuf+3)) & ~LDNS_RCODE_MASK) | (rcode))
+
+#define LDNS_CD_MASK 0x10U
+#define LDNS_CD_SHIFT 4
+#define LDNS_CD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_CD_MASK)
+#define LDNS_CD_SET(wirebuf) (*(wirebuf+3) |= LDNS_CD_MASK)
+#define LDNS_CD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_CD_MASK)
+
+#define LDNS_AD_MASK 0x20U
+#define LDNS_AD_SHIFT 5
+#define LDNS_AD_WIRE(wirebuf) (*(wirebuf+3) & LDNS_AD_MASK)
+#define LDNS_AD_SET(wirebuf) (*(wirebuf+3) |= LDNS_AD_MASK)
+#define LDNS_AD_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_AD_MASK)
+
+#define LDNS_Z_MASK 0x40U
+#define LDNS_Z_SHIFT 6
+#define LDNS_Z_WIRE(wirebuf) (*(wirebuf+3) & LDNS_Z_MASK)
+#define LDNS_Z_SET(wirebuf) (*(wirebuf+3) |= LDNS_Z_MASK)
+#define LDNS_Z_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_Z_MASK)
+
+#define LDNS_RA_MASK 0x80U
+#define LDNS_RA_SHIFT 7
+#define LDNS_RA_WIRE(wirebuf) (*(wirebuf+3) & LDNS_RA_MASK)
+#define LDNS_RA_SET(wirebuf) (*(wirebuf+3) |= LDNS_RA_MASK)
+#define LDNS_RA_CLR(wirebuf) (*(wirebuf+3) &= ~LDNS_RA_MASK)
+
+/* Query ID */
+#define LDNS_ID_WIRE(wirebuf) (sldns_read_uint16(wirebuf))
+#define LDNS_ID_SET(wirebuf, id) (sldns_write_uint16(wirebuf, id))
+
+/* Counter of the question section */
+#define LDNS_QDCOUNT_OFF 4
+/*
+#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF)))
+*/
+#define LDNS_QDCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF))
+
+/* Counter of the answer section */
+#define LDNS_ANCOUNT_OFF 6
+#define LDNS_ANCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF))
+
+/* Counter of the authority section */
+#define LDNS_NSCOUNT_OFF 8
+#define LDNS_NSCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF))
+
+/* Counter of the additional section */
+#define LDNS_ARCOUNT_OFF 10
+#define LDNS_ARCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF))
+
+/**
+ * The sections of a packet
+ */
+enum sldns_enum_pkt_section {
+ LDNS_SECTION_QUESTION = 0,
+ LDNS_SECTION_ANSWER = 1,
+ LDNS_SECTION_AUTHORITY = 2,
+ LDNS_SECTION_ADDITIONAL = 3,
+ /** bogus section, if not interested */
+ LDNS_SECTION_ANY = 4,
+ /** used to get all non-question rrs from a packet */
+ LDNS_SECTION_ANY_NOQUESTION = 5
+};
+typedef enum sldns_enum_pkt_section sldns_pkt_section;
+
+/* opcodes for pkt's */
+enum sldns_enum_pkt_opcode {
+ LDNS_PACKET_QUERY = 0,
+ LDNS_PACKET_IQUERY = 1,
+ LDNS_PACKET_STATUS = 2, /* there is no 3?? DNS is weird */
+ LDNS_PACKET_NOTIFY = 4,
+ LDNS_PACKET_UPDATE = 5
+};
+typedef enum sldns_enum_pkt_opcode sldns_pkt_opcode;
+
+/* rcodes for pkts */
+enum sldns_enum_pkt_rcode {
+ LDNS_RCODE_NOERROR = 0,
+ LDNS_RCODE_FORMERR = 1,
+ LDNS_RCODE_SERVFAIL = 2,
+ LDNS_RCODE_NXDOMAIN = 3,
+ LDNS_RCODE_NOTIMPL = 4,
+ LDNS_RCODE_REFUSED = 5,
+ LDNS_RCODE_YXDOMAIN = 6,
+ LDNS_RCODE_YXRRSET = 7,
+ LDNS_RCODE_NXRRSET = 8,
+ LDNS_RCODE_NOTAUTH = 9,
+ LDNS_RCODE_NOTZONE = 10
+};
+typedef enum sldns_enum_pkt_rcode sldns_pkt_rcode;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_PKTHDR_H */
--- /dev/null
+/* rrdef.c
+ *
+ * access functions to rr definitions list.
+ * a Net::DNS like library for C
+ * LibDNS Team @ NLnet Labs
+ *
+ * (c) NLnet Labs, 2004-2006
+ * See the file LICENSE for the license
+ */
+/**
+ * \file
+ *
+ * Defines resource record types and constants.
+ */
+#include "config.h"
+#include "sldns/rrdef.h"
+#include "sldns/parseutil.h"
+
+/* classes */
+static sldns_lookup_table sldns_rr_classes_data[] = {
+ { LDNS_RR_CLASS_IN, "IN" },
+ { LDNS_RR_CLASS_CH, "CH" },
+ { LDNS_RR_CLASS_HS, "HS" },
+ { LDNS_RR_CLASS_NONE, "NONE" },
+ { LDNS_RR_CLASS_ANY, "ANY" },
+ { 0, NULL }
+};
+sldns_lookup_table* sldns_rr_classes = sldns_rr_classes_data;
+
+/* types */
+static const sldns_rdf_type type_0_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN };
+static const sldns_rdf_type type_a_wireformat[] = { LDNS_RDF_TYPE_A };
+static const sldns_rdf_type type_ns_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_md_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_mf_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_cname_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_soa_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_INT32,
+ LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD, LDNS_RDF_TYPE_PERIOD,
+ LDNS_RDF_TYPE_PERIOD
+};
+static const sldns_rdf_type type_mb_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_mg_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_mr_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_wks_wireformat[] = {
+ LDNS_RDF_TYPE_A, LDNS_RDF_TYPE_WKS
+};
+static const sldns_rdf_type type_ptr_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_hinfo_wireformat[] = {
+ LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
+};
+static const sldns_rdf_type type_minfo_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_mx_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_rp_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_afsdb_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_x25_wireformat[] = { LDNS_RDF_TYPE_STR };
+static const sldns_rdf_type type_isdn_wireformat[] = {
+ LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
+};
+static const sldns_rdf_type type_rt_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_nsap_wireformat[] = {
+ LDNS_RDF_TYPE_NSAP
+};
+static const sldns_rdf_type type_nsap_ptr_wireformat[] = {
+ LDNS_RDF_TYPE_STR
+};
+static const sldns_rdf_type type_sig_wireformat[] = {
+ LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
+ LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64
+};
+static const sldns_rdf_type type_key_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64
+};
+static const sldns_rdf_type type_px_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_gpos_wireformat[] = {
+ LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
+};
+static const sldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA };
+static const sldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC };
+static const sldns_rdf_type type_nxt_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_UNKNOWN
+};
+static const sldns_rdf_type type_eid_wireformat[] = {
+ LDNS_RDF_TYPE_HEX
+};
+static const sldns_rdf_type type_nimloc_wireformat[] = {
+ LDNS_RDF_TYPE_HEX
+};
+static const sldns_rdf_type type_srv_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_atma_wireformat[] = {
+ LDNS_RDF_TYPE_ATMA
+};
+static const sldns_rdf_type type_naptr_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_kx_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_cert_wireformat[] = {
+ LDNS_RDF_TYPE_CERT_ALG, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_B64
+};
+static const sldns_rdf_type type_a6_wireformat[] = { LDNS_RDF_TYPE_UNKNOWN };
+static const sldns_rdf_type type_dname_wireformat[] = { LDNS_RDF_TYPE_DNAME };
+static const sldns_rdf_type type_sink_wireformat[] = { LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_B64
+};
+static const sldns_rdf_type type_apl_wireformat[] = {
+ LDNS_RDF_TYPE_APL
+};
+static const sldns_rdf_type type_ds_wireformat[] = {
+ LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX
+};
+static const sldns_rdf_type type_sshfp_wireformat[] = {
+ LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_HEX
+};
+static const sldns_rdf_type type_ipseckey_wireformat[] = {
+ LDNS_RDF_TYPE_IPSECKEY
+};
+static const sldns_rdf_type type_rrsig_wireformat[] = {
+ LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
+ LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_TIME, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_B64
+};
+static const sldns_rdf_type type_nsec_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_NSEC
+};
+static const sldns_rdf_type type_dhcid_wireformat[] = {
+ LDNS_RDF_TYPE_B64
+};
+static const sldns_rdf_type type_talink_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
+};
+/* nsec3 is some vars, followed by same type of data of nsec */
+static const sldns_rdf_type type_nsec3_wireformat[] = {
+/* LDNS_RDF_TYPE_NSEC3_VARS, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC*/
+ LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_NSEC3_SALT, LDNS_RDF_TYPE_NSEC3_NEXT_OWNER, LDNS_RDF_TYPE_NSEC
+};
+
+static const sldns_rdf_type type_nsec3param_wireformat[] = {
+/* LDNS_RDF_TYPE_NSEC3_PARAMS_VARS*/
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_NSEC3_SALT
+};
+
+static const sldns_rdf_type type_dnskey_wireformat[] = {
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_ALG,
+ LDNS_RDF_TYPE_B64
+};
+static const sldns_rdf_type type_tkey_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME,
+ LDNS_RDF_TYPE_TIME,
+ LDNS_RDF_TYPE_TIME,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT16_DATA,
+ LDNS_RDF_TYPE_INT16_DATA,
+};
+static const sldns_rdf_type type_tsig_wireformat[] = {
+ LDNS_RDF_TYPE_DNAME,
+ LDNS_RDF_TYPE_TSIGTIME,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT16_DATA,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT16_DATA
+};
+static const sldns_rdf_type type_tlsa_wireformat[] = {
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_HEX
+};
+static const sldns_rdf_type type_hip_wireformat[] = {
+ LDNS_RDF_TYPE_HIP
+};
+static const sldns_rdf_type type_nid_wireformat[] = {
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_ILNP64
+};
+static const sldns_rdf_type type_l32_wireformat[] = {
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_A
+};
+static const sldns_rdf_type type_l64_wireformat[] = {
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_ILNP64
+};
+static const sldns_rdf_type type_lp_wireformat[] = {
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_DNAME
+};
+static const sldns_rdf_type type_eui48_wireformat[] = {
+ LDNS_RDF_TYPE_EUI48
+};
+static const sldns_rdf_type type_eui64_wireformat[] = {
+ LDNS_RDF_TYPE_EUI64
+};
+#ifdef DRAFT_RRTYPES
+static const sldns_rdf_type type_uri_wireformat[] = {
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_INT16,
+ LDNS_RDF_TYPE_LONG_STR
+};
+#endif
+static const sldns_rdf_type type_caa_wireformat[] = {
+ LDNS_RDF_TYPE_INT8,
+ LDNS_RDF_TYPE_TAG,
+ LDNS_RDF_TYPE_LONG_STR
+};
+
+/* All RR's defined in 1035 are well known and can thus
+ * be compressed. See RFC3597. These RR's are:
+ * CNAME HINFO MB MD MF MG MINFO MR MX NULL NS PTR SOA TXT
+ */
+static sldns_rr_descriptor rdata_field_descriptors[] = {
+ /* 0 */
+ { 0, NULL, 0, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 1 */
+ {LDNS_RR_TYPE_A, "A", 1, 1, type_a_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 2 */
+ {LDNS_RR_TYPE_NS, "NS", 1, 1, type_ns_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 3 */
+ {LDNS_RR_TYPE_MD, "MD", 1, 1, type_md_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 4 */
+ {LDNS_RR_TYPE_MF, "MF", 1, 1, type_mf_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 5 */
+ {LDNS_RR_TYPE_CNAME, "CNAME", 1, 1, type_cname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 6 */
+ {LDNS_RR_TYPE_SOA, "SOA", 7, 7, type_soa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 },
+ /* 7 */
+ {LDNS_RR_TYPE_MB, "MB", 1, 1, type_mb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 8 */
+ {LDNS_RR_TYPE_MG, "MG", 1, 1, type_mg_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 9 */
+ {LDNS_RR_TYPE_MR, "MR", 1, 1, type_mr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 10 */
+ {LDNS_RR_TYPE_NULL, "NULL", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 11 */
+ {LDNS_RR_TYPE_WKS, "WKS", 2, 2, type_wks_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 12 */
+ {LDNS_RR_TYPE_PTR, "PTR", 1, 1, type_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 13 */
+ {LDNS_RR_TYPE_HINFO, "HINFO", 2, 2, type_hinfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 14 */
+ {LDNS_RR_TYPE_MINFO, "MINFO", 2, 2, type_minfo_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 2 },
+ /* 15 */
+ {LDNS_RR_TYPE_MX, "MX", 2, 2, type_mx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_COMPRESS, 1 },
+ /* 16 */
+ {LDNS_RR_TYPE_TXT, "TXT", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
+ /* 17 */
+ {LDNS_RR_TYPE_RP, "RP", 2, 2, type_rp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
+ /* 18 */
+ {LDNS_RR_TYPE_AFSDB, "AFSDB", 2, 2, type_afsdb_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 19 */
+ {LDNS_RR_TYPE_X25, "X25", 1, 1, type_x25_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 20 */
+ {LDNS_RR_TYPE_ISDN, "ISDN", 1, 2, type_isdn_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 21 */
+ {LDNS_RR_TYPE_RT, "RT", 2, 2, type_rt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 22 */
+ {LDNS_RR_TYPE_NSAP, "NSAP", 1, 1, type_nsap_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 23 */
+ {LDNS_RR_TYPE_NSAP_PTR, "NSAP-PTR", 1, 1, type_nsap_ptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 24 */
+ {LDNS_RR_TYPE_SIG, "SIG", 9, 9, type_sig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 25 */
+ {LDNS_RR_TYPE_KEY, "KEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 26 */
+ {LDNS_RR_TYPE_PX, "PX", 3, 3, type_px_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
+ /* 27 */
+ {LDNS_RR_TYPE_GPOS, "GPOS", 3, 3, type_gpos_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 28 */
+ {LDNS_RR_TYPE_AAAA, "AAAA", 1, 1, type_aaaa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 29 */
+ {LDNS_RR_TYPE_LOC, "LOC", 1, 1, type_loc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 30 */
+ {LDNS_RR_TYPE_NXT, "NXT", 2, 2, type_nxt_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 31 */
+ {LDNS_RR_TYPE_EID, "EID", 1, 1, type_eid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 32 */
+ {LDNS_RR_TYPE_NIMLOC, "NIMLOC", 1, 1, type_nimloc_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 33 */
+ {LDNS_RR_TYPE_SRV, "SRV", 4, 4, type_srv_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 34 */
+ {LDNS_RR_TYPE_ATMA, "ATMA", 1, 1, type_atma_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 35 */
+ {LDNS_RR_TYPE_NAPTR, "NAPTR", 6, 6, type_naptr_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 36 */
+ {LDNS_RR_TYPE_KX, "KX", 2, 2, type_kx_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 37 */
+ {LDNS_RR_TYPE_CERT, "CERT", 4, 4, type_cert_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 38 */
+ {LDNS_RR_TYPE_A6, "A6", 1, 1, type_a6_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 39 */
+ {LDNS_RR_TYPE_DNAME, "DNAME", 1, 1, type_dname_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 40 */
+ {LDNS_RR_TYPE_SINK, "SINK", 1, 1, type_sink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 41 */
+ {LDNS_RR_TYPE_OPT, "OPT", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 42 */
+ {LDNS_RR_TYPE_APL, "APL", 0, 0, type_apl_wireformat, LDNS_RDF_TYPE_APL, LDNS_RR_NO_COMPRESS, 0 },
+ /* 43 */
+ {LDNS_RR_TYPE_DS, "DS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 44 */
+ {LDNS_RR_TYPE_SSHFP, "SSHFP", 3, 3, type_sshfp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 45 */
+ {LDNS_RR_TYPE_IPSECKEY, "IPSECKEY", 1, 1, type_ipseckey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 46 */
+ {LDNS_RR_TYPE_RRSIG, "RRSIG", 9, 9, type_rrsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 47 */
+ {LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* 48 */
+ {LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 49 */
+ {LDNS_RR_TYPE_DHCID, "DHCID", 1, 1, type_dhcid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 50 */
+ {LDNS_RR_TYPE_NSEC3, "NSEC3", 5, 6, type_nsec3_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 51 */
+ {LDNS_RR_TYPE_NSEC3PARAM, "NSEC3PARAM", 4, 4, type_nsec3param_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 52 */
+ {LDNS_RR_TYPE_TLSA, "TLSA", 4, 4, type_tlsa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+{LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 55
+ * Hip ends with 0 or more Rendezvous Servers represented as dname's.
+ * Hence the LDNS_RDF_TYPE_DNAME _variable field and the _maximum field
+ * set to 0.
+ */
+ {LDNS_RR_TYPE_HIP, "HIP", 1, 1, type_hip_wireformat, LDNS_RDF_TYPE_DNAME, LDNS_RR_NO_COMPRESS, 0 },
+
+#ifdef DRAFT_RRTYPES
+ /* 56 */
+ {LDNS_RR_TYPE_NINFO, "NINFO", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
+ /* 57 */
+ {LDNS_RR_TYPE_RKEY, "RKEY", 4, 4, type_key_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+#else
+{LDNS_RR_TYPE_NULL, "TYPE56", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE57", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+#endif
+ /* 58 */
+ {LDNS_RR_TYPE_TALINK, "TALINK", 2, 2, type_talink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 },
+
+ /* 59 */
+ {LDNS_RR_TYPE_CDS, "CDS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 60 */
+ {LDNS_RR_TYPE_CDNSKEY, "CDNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE62", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE64", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE65", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE69", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE70", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE71", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE72", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE73", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE74", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE75", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE76", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE77", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE78", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE79", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE80", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE81", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE82", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE83", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE84", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE85", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE86", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE87", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE88", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE89", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE90", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE91", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE92", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE93", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE94", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE95", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE96", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE97", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE98", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+ /* 99 */
+ {LDNS_RR_TYPE_SPF, "SPF", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
+
+ /* UINFO [IANA-Reserved] */
+{LDNS_RR_TYPE_NULL, "TYPE100", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* UID [IANA-Reserved] */
+{LDNS_RR_TYPE_NULL, "TYPE101", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* GID [IANA-Reserved] */
+{LDNS_RR_TYPE_NULL, "TYPE102", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* UNSPEC [IANA-Reserved] */
+{LDNS_RR_TYPE_NULL, "TYPE103", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+ /* 104 */
+ {LDNS_RR_TYPE_NID, "NID", 2, 2, type_nid_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 105 */
+ {LDNS_RR_TYPE_L32, "L32", 2, 2, type_l32_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 106 */
+ {LDNS_RR_TYPE_L64, "L64", 2, 2, type_l64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 107 */
+ {LDNS_RR_TYPE_LP, "LP", 2, 2, type_lp_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+
+ /* 108 */
+ {LDNS_RR_TYPE_EUI48, "EUI48", 1, 1, type_eui48_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* 109 */
+ {LDNS_RR_TYPE_EUI64, "EUI64", 1, 1, type_eui64_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+{LDNS_RR_TYPE_NULL, "TYPE110", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE111", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE112", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE113", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE114", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE115", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE116", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE117", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE118", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE119", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE120", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE121", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE122", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE123", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE124", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE125", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE126", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE127", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE128", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE129", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE130", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE131", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE132", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE133", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE134", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE135", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE136", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE137", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE138", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE139", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE140", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE141", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE142", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE143", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE144", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE145", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE146", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE147", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE148", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE149", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE150", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE151", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE152", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE153", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE154", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE155", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE156", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE157", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE158", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE159", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE160", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE161", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE162", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE163", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE164", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE165", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE166", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE167", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE168", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE169", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE170", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE171", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE172", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE173", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE174", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE175", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE176", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE177", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE178", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE179", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE180", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE181", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE182", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE183", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE184", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE185", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE186", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE187", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE188", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE189", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE190", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE191", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE192", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE193", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE194", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE195", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE196", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE197", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE198", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE199", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE200", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE201", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE202", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE203", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE204", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE205", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE206", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE207", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE208", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE209", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE210", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE211", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE212", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE213", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE214", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE215", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE216", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE217", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE218", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE219", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE220", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE221", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE222", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE223", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE224", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE225", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE226", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE227", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE228", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE229", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE230", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE231", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE232", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE233", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE234", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE235", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE236", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE237", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE238", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE239", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE240", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE241", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE242", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE243", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE244", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE245", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE246", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE247", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+{LDNS_RR_TYPE_NULL, "TYPE248", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+ /* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one.
+ * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9.
+ */
+ /* 249 */
+ {LDNS_RR_TYPE_TKEY, "TKEY", 7, 7, type_tkey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+ /* LDNS_RDF_TYPE_INT16_DATA takes two fields (length and data) as one.
+ * So, unlike RFC 2930 spec, we have 7 min/max rdf's i.s.o. 8/9.
+ */
+ /* 250 */
+ {LDNS_RR_TYPE_TSIG, "TSIG", 7, 7, type_tsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
+
+ /* IXFR: A request for a transfer of an incremental zone transfer */
+{LDNS_RR_TYPE_IXFR, "IXFR", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* AXFR: A request for a transfer of an entire zone */
+{LDNS_RR_TYPE_AXFR, "AXFR", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* MAILB: A request for mailbox-related records (MB, MG or MR) */
+{LDNS_RR_TYPE_MAILB, "MAILB", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* MAILA: A request for mail agent RRs (Obsolete - see MX) */
+{LDNS_RR_TYPE_MAILA, "MAILA", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+ /* ANY: A request for all (available) records */
+{LDNS_RR_TYPE_ANY, "ANY", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+#ifdef DRAFT_RRTYPES
+ /* 256 */
+ {LDNS_RR_TYPE_URI, "URI", 3, 3, type_uri_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+#else
+{LDNS_RR_TYPE_NULL, "TYPE256", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+#endif
+ /* 257 */
+ {LDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+/* split in array, no longer contiguous */
+
+#ifdef DRAFT_RRTYPES
+ /* 32768 */
+ {LDNS_RR_TYPE_TA, "TA", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+#else
+{LDNS_RR_TYPE_NULL, "TYPE32768", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+#endif
+ /* 32769 */
+ {LDNS_RR_TYPE_DLV, "DLV", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }
+};
+
+/**
+ * \def LDNS_RDATA_FIELD_DESCRIPTORS_COUNT
+ * computes the number of rdata fields
+ */
+#define LDNS_RDATA_FIELD_DESCRIPTORS_COUNT \
+ (sizeof(rdata_field_descriptors)/sizeof(rdata_field_descriptors[0]))
+
+const sldns_rr_descriptor *
+sldns_rr_descript(uint16_t type)
+{
+ size_t i;
+ if (type < LDNS_RDATA_FIELD_DESCRIPTORS_COMMON) {
+ return &rdata_field_descriptors[type];
+ } else {
+ /* because not all array index equals type code */
+ for (i = LDNS_RDATA_FIELD_DESCRIPTORS_COMMON;
+ i < LDNS_RDATA_FIELD_DESCRIPTORS_COUNT;
+ i++) {
+ if (rdata_field_descriptors[i]._type == type) {
+ return &rdata_field_descriptors[i];
+ }
+ }
+ return &rdata_field_descriptors[0];
+ }
+}
+
+size_t
+sldns_rr_descriptor_minimum(const sldns_rr_descriptor *descriptor)
+{
+ if (descriptor) {
+ return descriptor->_minimum;
+ } else {
+ return 0;
+ }
+}
+
+size_t
+sldns_rr_descriptor_maximum(const sldns_rr_descriptor *descriptor)
+{
+ if (descriptor) {
+ if (descriptor->_variable != LDNS_RDF_TYPE_NONE) {
+ return 65535; /* cannot be more than 64k */
+ } else {
+ return descriptor->_maximum;
+ }
+ } else {
+ return 0;
+ }
+}
+
+sldns_rdf_type
+sldns_rr_descriptor_field_type(const sldns_rr_descriptor *descriptor,
+ size_t index)
+{
+ assert(descriptor != NULL);
+ assert(index < descriptor->_maximum
+ || descriptor->_variable != LDNS_RDF_TYPE_NONE);
+ if (index < descriptor->_maximum) {
+ return descriptor->_wireformat[index];
+ } else {
+ return descriptor->_variable;
+ }
+}
+
+sldns_rr_type
+sldns_get_rr_type_by_name(const char *name)
+{
+ unsigned int i;
+ const char *desc_name;
+ const sldns_rr_descriptor *desc;
+
+ /* TYPEXX representation */
+ if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) {
+ return atoi(name + 4);
+ }
+
+ /* Normal types */
+ for (i = 0; i < (unsigned int) LDNS_RDATA_FIELD_DESCRIPTORS_COUNT; i++) {
+ desc = &rdata_field_descriptors[i];
+ desc_name = desc->_name;
+ if(desc_name &&
+ strlen(name) == strlen(desc_name) &&
+ strncasecmp(name, desc_name, strlen(desc_name)) == 0) {
+ /* because not all array index equals type code */
+ return desc->_type;
+ }
+ }
+
+ /* special cases for query types */
+ if (strlen(name) == 4 && strncasecmp(name, "IXFR", 4) == 0) {
+ return 251;
+ } else if (strlen(name) == 4 && strncasecmp(name, "AXFR", 4) == 0) {
+ return 252;
+ } else if (strlen(name) == 5 && strncasecmp(name, "MAILB", 5) == 0) {
+ return 253;
+ } else if (strlen(name) == 5 && strncasecmp(name, "MAILA", 5) == 0) {
+ return 254;
+ } else if (strlen(name) == 3 && strncasecmp(name, "ANY", 3) == 0) {
+ return 255;
+ }
+
+ return 0;
+}
+
+sldns_rr_class
+sldns_get_rr_class_by_name(const char *name)
+{
+ sldns_lookup_table *lt;
+
+ /* CLASSXX representation */
+ if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) {
+ return atoi(name + 5);
+ }
+
+ /* Normal types */
+ lt = sldns_lookup_by_name(sldns_rr_classes, name);
+ if (lt) {
+ return lt->id;
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * rrdef.h
+ *
+ * RR definitions
+ *
+ * a Net::DNS like library for C
+ *
+ * (c) NLnet Labs, 2005-2006
+ *
+ * See the file LICENSE for the license
+ */
+
+/**
+ * \file
+ *
+ * Defines resource record types and constants.
+ */
+
+#ifndef LDNS_RRDEF_H
+#define LDNS_RRDEF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Maximum length of a dname label */
+#define LDNS_MAX_LABELLEN 63
+/** Maximum length of a complete dname */
+#define LDNS_MAX_DOMAINLEN 255
+/** Maximum number of pointers in 1 dname */
+#define LDNS_MAX_POINTERS 65535
+/** The bytes TTL, CLASS and length use up in an rr */
+#define LDNS_RR_OVERHEAD 10
+
+#define LDNS_DNSSEC_KEYPROTO 3
+#define LDNS_KEY_ZONE_KEY 0x0100 /* set for ZSK&KSK, rfc 4034 */
+#define LDNS_KEY_SEP_KEY 0x0001 /* set for KSK, rfc 4034 */
+#define LDNS_KEY_REVOKE_KEY 0x0080 /* used to revoke KSK, rfc 5011 */
+
+/* The first fields are contiguous and can be referenced instantly */
+#define LDNS_RDATA_FIELD_DESCRIPTORS_COMMON 258
+
+/** lookuptable for rr classes */
+extern struct sldns_struct_lookup_table* sldns_rr_classes;
+
+/**
+ * The different RR classes.
+ */
+enum sldns_enum_rr_class
+{
+ /** the Internet */
+ LDNS_RR_CLASS_IN = 1,
+ /** Chaos class */
+ LDNS_RR_CLASS_CH = 3,
+ /** Hesiod (Dyer 87) */
+ LDNS_RR_CLASS_HS = 4,
+ /** None class, dynamic update */
+ LDNS_RR_CLASS_NONE = 254,
+ /** Any class */
+ LDNS_RR_CLASS_ANY = 255,
+
+ LDNS_RR_CLASS_FIRST = 0,
+ LDNS_RR_CLASS_LAST = 65535,
+ LDNS_RR_CLASS_COUNT = LDNS_RR_CLASS_LAST - LDNS_RR_CLASS_FIRST + 1
+};
+typedef enum sldns_enum_rr_class sldns_rr_class;
+
+/**
+ * Used to specify whether compression is allowed.
+ */
+enum sldns_enum_rr_compress
+{
+ /** compression is allowed */
+ LDNS_RR_COMPRESS,
+ LDNS_RR_NO_COMPRESS
+};
+typedef enum sldns_enum_rr_compress sldns_rr_compress;
+
+/**
+ * The different RR types.
+ */
+enum sldns_enum_rr_type
+{
+ /** a host address */
+ LDNS_RR_TYPE_A = 1,
+ /** an authoritative name server */
+ LDNS_RR_TYPE_NS = 2,
+ /** a mail destination (Obsolete - use MX) */
+ LDNS_RR_TYPE_MD = 3,
+ /** a mail forwarder (Obsolete - use MX) */
+ LDNS_RR_TYPE_MF = 4,
+ /** the canonical name for an alias */
+ LDNS_RR_TYPE_CNAME = 5,
+ /** marks the start of a zone of authority */
+ LDNS_RR_TYPE_SOA = 6,
+ /** a mailbox domain name (EXPERIMENTAL) */
+ LDNS_RR_TYPE_MB = 7,
+ /** a mail group member (EXPERIMENTAL) */
+ LDNS_RR_TYPE_MG = 8,
+ /** a mail rename domain name (EXPERIMENTAL) */
+ LDNS_RR_TYPE_MR = 9,
+ /** a null RR (EXPERIMENTAL) */
+ LDNS_RR_TYPE_NULL = 10,
+ /** a well known service description */
+ LDNS_RR_TYPE_WKS = 11,
+ /** a domain name pointer */
+ LDNS_RR_TYPE_PTR = 12,
+ /** host information */
+ LDNS_RR_TYPE_HINFO = 13,
+ /** mailbox or mail list information */
+ LDNS_RR_TYPE_MINFO = 14,
+ /** mail exchange */
+ LDNS_RR_TYPE_MX = 15,
+ /** text strings */
+ LDNS_RR_TYPE_TXT = 16,
+ /** RFC1183 */
+ LDNS_RR_TYPE_RP = 17,
+ /** RFC1183 */
+ LDNS_RR_TYPE_AFSDB = 18,
+ /** RFC1183 */
+ LDNS_RR_TYPE_X25 = 19,
+ /** RFC1183 */
+ LDNS_RR_TYPE_ISDN = 20,
+ /** RFC1183 */
+ LDNS_RR_TYPE_RT = 21,
+ /** RFC1706 */
+ LDNS_RR_TYPE_NSAP = 22,
+ /** RFC1348 */
+ LDNS_RR_TYPE_NSAP_PTR = 23,
+ /** 2535typecode */
+ LDNS_RR_TYPE_SIG = 24,
+ /** 2535typecode */
+ LDNS_RR_TYPE_KEY = 25,
+ /** RFC2163 */
+ LDNS_RR_TYPE_PX = 26,
+ /** RFC1712 */
+ LDNS_RR_TYPE_GPOS = 27,
+ /** ipv6 address */
+ LDNS_RR_TYPE_AAAA = 28,
+ /** LOC record RFC1876 */
+ LDNS_RR_TYPE_LOC = 29,
+ /** 2535typecode */
+ LDNS_RR_TYPE_NXT = 30,
+ /** draft-ietf-nimrod-dns-01.txt */
+ LDNS_RR_TYPE_EID = 31,
+ /** draft-ietf-nimrod-dns-01.txt */
+ LDNS_RR_TYPE_NIMLOC = 32,
+ /** SRV record RFC2782 */
+ LDNS_RR_TYPE_SRV = 33,
+ /** http://www.jhsoft.com/rfc/af-saa-0069.000.rtf */
+ LDNS_RR_TYPE_ATMA = 34,
+ /** RFC2915 */
+ LDNS_RR_TYPE_NAPTR = 35,
+ /** RFC2230 */
+ LDNS_RR_TYPE_KX = 36,
+ /** RFC2538 */
+ LDNS_RR_TYPE_CERT = 37,
+ /** RFC2874 */
+ LDNS_RR_TYPE_A6 = 38,
+ /** RFC2672 */
+ LDNS_RR_TYPE_DNAME = 39,
+ /** dnsind-kitchen-sink-02.txt */
+ LDNS_RR_TYPE_SINK = 40,
+ /** Pseudo OPT record... */
+ LDNS_RR_TYPE_OPT = 41,
+ /** RFC3123 */
+ LDNS_RR_TYPE_APL = 42,
+ /** RFC4034, RFC3658 */
+ LDNS_RR_TYPE_DS = 43,
+ /** SSH Key Fingerprint */
+ LDNS_RR_TYPE_SSHFP = 44, /* RFC 4255 */
+ /** IPsec Key */
+ LDNS_RR_TYPE_IPSECKEY = 45, /* RFC 4025 */
+ /** DNSSEC */
+ LDNS_RR_TYPE_RRSIG = 46, /* RFC 4034 */
+ LDNS_RR_TYPE_NSEC = 47, /* RFC 4034 */
+ LDNS_RR_TYPE_DNSKEY = 48, /* RFC 4034 */
+
+ LDNS_RR_TYPE_DHCID = 49, /* RFC 4701 */
+ /* NSEC3 */
+ LDNS_RR_TYPE_NSEC3 = 50, /* RFC 5155 */
+ LDNS_RR_TYPE_NSEC3PARAM = 51, /* RFC 5155 */
+ LDNS_RR_TYPE_NSEC3PARAMS = 51,
+ LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
+
+ LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
+
+ /** draft-reid-dnsext-zs */
+ LDNS_RR_TYPE_NINFO = 56,
+ /** draft-reid-dnsext-rkey */
+ LDNS_RR_TYPE_RKEY = 57,
+ /** draft-ietf-dnsop-trust-history */
+ LDNS_RR_TYPE_TALINK = 58,
+ LDNS_RR_TYPE_CDS = 59, /** RFC 7344 */
+ LDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */
+
+ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
+
+ LDNS_RR_TYPE_UINFO = 100,
+ LDNS_RR_TYPE_UID = 101,
+ LDNS_RR_TYPE_GID = 102,
+ LDNS_RR_TYPE_UNSPEC = 103,
+
+ LDNS_RR_TYPE_NID = 104, /* RFC 6742 */
+ LDNS_RR_TYPE_L32 = 105, /* RFC 6742 */
+ LDNS_RR_TYPE_L64 = 106, /* RFC 6742 */
+ LDNS_RR_TYPE_LP = 107, /* RFC 6742 */
+
+ /** draft-jabley-dnsext-eui48-eui64-rrtypes */
+ LDNS_RR_TYPE_EUI48 = 108,
+ LDNS_RR_TYPE_EUI64 = 109,
+
+ LDNS_RR_TYPE_TKEY = 249, /* RFC 2930 */
+ LDNS_RR_TYPE_TSIG = 250,
+ LDNS_RR_TYPE_IXFR = 251,
+ LDNS_RR_TYPE_AXFR = 252,
+ /** A request for mailbox-related records (MB, MG or MR) */
+ LDNS_RR_TYPE_MAILB = 253,
+ /** A request for mail agent RRs (Obsolete - see MX) */
+ LDNS_RR_TYPE_MAILA = 254,
+ /** any type (wildcard) */
+ LDNS_RR_TYPE_ANY = 255,
+ /** draft-faltstrom-uri-06 */
+ LDNS_RR_TYPE_URI = 256,
+ LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
+
+ /** DNSSEC Trust Authorities */
+ LDNS_RR_TYPE_TA = 32768,
+ /* RFC 4431, 5074, DNSSEC Lookaside Validation */
+ LDNS_RR_TYPE_DLV = 32769,
+
+ /* type codes from nsec3 experimental phase
+ LDNS_RR_TYPE_NSEC3 = 65324,
+ LDNS_RR_TYPE_NSEC3PARAMS = 65325, */
+ LDNS_RR_TYPE_FIRST = 0,
+ LDNS_RR_TYPE_LAST = 65535,
+ LDNS_RR_TYPE_COUNT = LDNS_RR_TYPE_LAST - LDNS_RR_TYPE_FIRST + 1
+};
+typedef enum sldns_enum_rr_type sldns_rr_type;
+
+/* RDATA */
+#define LDNS_MAX_RDFLEN 65535
+
+#define LDNS_RDF_SIZE_BYTE 1
+#define LDNS_RDF_SIZE_WORD 2
+#define LDNS_RDF_SIZE_DOUBLEWORD 4
+#define LDNS_RDF_SIZE_6BYTES 6
+#define LDNS_RDF_SIZE_8BYTES 8
+#define LDNS_RDF_SIZE_16BYTES 16
+
+#define LDNS_NSEC3_VARS_OPTOUT_MASK 0x01
+
+#define LDNS_APL_IP4 1
+#define LDNS_APL_IP6 2
+#define LDNS_APL_MASK 0x7f
+#define LDNS_APL_NEGATION 0x80
+
+/**
+ * The different types of RDATA fields.
+ */
+enum sldns_enum_rdf_type
+{
+ /** none */
+ LDNS_RDF_TYPE_NONE,
+ /** domain name */
+ LDNS_RDF_TYPE_DNAME,
+ /** 8 bits */
+ LDNS_RDF_TYPE_INT8,
+ /** 16 bits */
+ LDNS_RDF_TYPE_INT16,
+ /** 32 bits */
+ LDNS_RDF_TYPE_INT32,
+ /** A record */
+ LDNS_RDF_TYPE_A,
+ /** AAAA record */
+ LDNS_RDF_TYPE_AAAA,
+ /** txt string */
+ LDNS_RDF_TYPE_STR,
+ /** apl data */
+ LDNS_RDF_TYPE_APL,
+ /** b32 string */
+ LDNS_RDF_TYPE_B32_EXT,
+ /** b64 string */
+ LDNS_RDF_TYPE_B64,
+ /** hex string */
+ LDNS_RDF_TYPE_HEX,
+ /** nsec type codes */
+ LDNS_RDF_TYPE_NSEC,
+ /** a RR type */
+ LDNS_RDF_TYPE_TYPE,
+ /** a class */
+ LDNS_RDF_TYPE_CLASS,
+ /** certificate algorithm */
+ LDNS_RDF_TYPE_CERT_ALG,
+ /** a key algorithm */
+ LDNS_RDF_TYPE_ALG,
+ /** unknown types */
+ LDNS_RDF_TYPE_UNKNOWN,
+ /** time (32 bits) */
+ LDNS_RDF_TYPE_TIME,
+ /** period */
+ LDNS_RDF_TYPE_PERIOD,
+ /** tsig time 48 bits */
+ LDNS_RDF_TYPE_TSIGTIME,
+ /** Represents the Public Key Algorithm, HIT and Public Key fields
+ for the HIP RR types. A HIP specific rdf type is used because of
+ the unusual layout in wireformat (see RFC 5205 Section 5) */
+ LDNS_RDF_TYPE_HIP,
+ /** variable length any type rdata where the length
+ is specified by the first 2 bytes */
+ LDNS_RDF_TYPE_INT16_DATA,
+ /** protocol and port bitmaps */
+ LDNS_RDF_TYPE_SERVICE,
+ /** location data */
+ LDNS_RDF_TYPE_LOC,
+ /** well known services */
+ LDNS_RDF_TYPE_WKS,
+ /** NSAP */
+ LDNS_RDF_TYPE_NSAP,
+ /** ATMA */
+ LDNS_RDF_TYPE_ATMA,
+ /** IPSECKEY */
+ LDNS_RDF_TYPE_IPSECKEY,
+ /** nsec3 hash salt */
+ LDNS_RDF_TYPE_NSEC3_SALT,
+ /** nsec3 base32 string (with length byte on wire */
+ LDNS_RDF_TYPE_NSEC3_NEXT_OWNER,
+
+ /** 4 shorts represented as 4 * 16 bit hex numbers
+ * seperated by colons. For NID and L64.
+ */
+ LDNS_RDF_TYPE_ILNP64,
+
+ /** 6 * 8 bit hex numbers seperated by dashes. For EUI48. */
+ LDNS_RDF_TYPE_EUI48,
+ /** 8 * 8 bit hex numbers seperated by dashes. For EUI64. */
+ LDNS_RDF_TYPE_EUI64,
+
+ /** A non-zero sequence of US-ASCII letters and numbers in lower case.
+ * For CAA.
+ */
+ LDNS_RDF_TYPE_TAG,
+
+ /** A <character-string> encoding of the value field as specified
+ * [RFC1035], Section 5.1., encoded as remaining rdata.
+ * For CAA.
+ */
+ LDNS_RDF_TYPE_LONG_STR,
+
+ /* Aliases */
+ LDNS_RDF_TYPE_BITMAP = LDNS_RDF_TYPE_NSEC
+};
+typedef enum sldns_enum_rdf_type sldns_rdf_type;
+
+/**
+ * Algorithms used in dns
+ */
+enum sldns_enum_algorithm
+{
+ LDNS_RSAMD5 = 1, /* RFC 4034,4035 */
+ LDNS_DH = 2,
+ LDNS_DSA = 3,
+ LDNS_ECC = 4,
+ LDNS_RSASHA1 = 5,
+ LDNS_DSA_NSEC3 = 6,
+ LDNS_RSASHA1_NSEC3 = 7,
+ LDNS_RSASHA256 = 8, /* RFC 5702 */
+ LDNS_RSASHA512 = 10, /* RFC 5702 */
+ LDNS_ECC_GOST = 12, /* RFC 5933 */
+ LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */
+ LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */
+ LDNS_INDIRECT = 252,
+ LDNS_PRIVATEDNS = 253,
+ LDNS_PRIVATEOID = 254
+};
+typedef enum sldns_enum_algorithm sldns_algorithm;
+
+/**
+ * Hashing algorithms used in the DS record
+ */
+enum sldns_enum_hash
+{
+ LDNS_SHA1 = 1, /* RFC 4034 */
+ LDNS_SHA256 = 2, /* RFC 4509 */
+ LDNS_HASH_GOST = 3, /* RFC 5933 */
+ LDNS_SHA384 = 4 /* RFC 6605 */
+};
+typedef enum sldns_enum_hash sldns_hash;
+
+/**
+ * algorithms used in CERT rrs
+ */
+enum sldns_enum_cert_algorithm
+{
+ LDNS_CERT_PKIX = 1,
+ LDNS_CERT_SPKI = 2,
+ LDNS_CERT_PGP = 3,
+ LDNS_CERT_IPKIX = 4,
+ LDNS_CERT_ISPKI = 5,
+ LDNS_CERT_IPGP = 6,
+ LDNS_CERT_ACPKIX = 7,
+ LDNS_CERT_IACPKIX = 8,
+ LDNS_CERT_URI = 253,
+ LDNS_CERT_OID = 254
+};
+typedef enum sldns_enum_cert_algorithm sldns_cert_algorithm;
+
+/**
+ * EDNS option codes
+ */
+enum sldns_enum_edns_option
+{
+ LDNS_EDNS_LLQ = 1, /* http://files.dns-sd.org/draft-sekar-dns-llq.txt */
+ LDNS_EDNS_UL = 2, /* http://files.dns-sd.org/draft-sekar-dns-ul.txt */
+ LDNS_EDNS_NSID = 3, /* RFC5001 */
+ /* 4 draft-cheshire-edns0-owner-option */
+ LDNS_EDNS_DAU = 5, /* RFC6975 */
+ LDNS_EDNS_DHU = 6, /* RFC6975 */
+ LDNS_EDNS_N3U = 7, /* RFC6975 */
+ LDNS_EDNS_CLIENT_SUBNET = 8 /* draft-vandergaast-edns-client-subnet */
+};
+typedef enum sldns_enum_edns_option sldns_edns_option;
+
+#define LDNS_EDNS_MASK_DO_BIT 0x8000
+
+/**
+ * Contains all information about resource record types.
+ *
+ * This structure contains, for all rr types, the rdata fields that are defined.
+ */
+struct sldns_struct_rr_descriptor
+{
+ /** Type of the RR that is described here */
+ sldns_rr_type _type;
+ /** Textual name of the RR type. */
+ const char *_name;
+ /** Minimum number of rdata fields in the RRs of this type. */
+ uint8_t _minimum;
+ /** Maximum number of rdata fields in the RRs of this type. */
+ uint8_t _maximum;
+ /** Wireformat specification for the rr, i.e. the types of rdata fields in their respective order. */
+ const sldns_rdf_type *_wireformat;
+ /** Special rdf types */
+ sldns_rdf_type _variable;
+ /** Specifies whether compression can be used for dnames in this RR type. */
+ sldns_rr_compress _compress;
+ /** The number of DNAMEs in the _wireformat string, for parsing. */
+ uint8_t _dname_count;
+};
+typedef struct sldns_struct_rr_descriptor sldns_rr_descriptor;
+
+/**
+ * returns the resource record descriptor for the given rr type.
+ *
+ * \param[in] type the type value of the rr type
+ *\return the sldns_rr_descriptor for this type
+ */
+const sldns_rr_descriptor *sldns_rr_descript(uint16_t type);
+
+/**
+ * returns the minimum number of rdata fields of the rr type this descriptor describes.
+ *
+ * \param[in] descriptor for an rr type
+ * \return the minimum number of rdata fields
+ */
+size_t sldns_rr_descriptor_minimum(const sldns_rr_descriptor *descriptor);
+
+/**
+ * returns the maximum number of rdata fields of the rr type this descriptor describes.
+ *
+ * \param[in] descriptor for an rr type
+ * \return the maximum number of rdata fields
+ */
+size_t sldns_rr_descriptor_maximum(const sldns_rr_descriptor *descriptor);
+
+/**
+ * returns the rdf type for the given rdata field number of the rr type for the given descriptor.
+ *
+ * \param[in] descriptor for an rr type
+ * \param[in] field the field number
+ * \return the rdf type for the field
+ */
+sldns_rdf_type sldns_rr_descriptor_field_type(const sldns_rr_descriptor *descriptor, size_t field);
+
+/**
+ * retrieves a rrtype by looking up its name.
+ * \param[in] name a string with the name
+ * \return the type which corresponds with the name
+ */
+sldns_rr_type sldns_get_rr_type_by_name(const char *name);
+
+/**
+ * retrieves a class by looking up its name.
+ * \param[in] name string with the name
+ * \return the cass which corresponds with the name
+ */
+sldns_rr_class sldns_get_rr_class_by_name(const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_RRDEF_H */
--- /dev/null
+/*
+ * buffer.c -- generic memory buffer .
+ *
+ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+/**
+ * \file
+ *
+ * This file contains the definition of sldns_buffer, and functions to manipulate those.
+ */
+#include "config.h"
+#include "sldns/sbuffer.h"
+#include <stdarg.h>
+
+sldns_buffer *
+sldns_buffer_new(size_t capacity)
+{
+ sldns_buffer *buffer = (sldns_buffer*)malloc(sizeof(sldns_buffer));
+
+ if (!buffer) {
+ return NULL;
+ }
+
+ buffer->_data = (uint8_t *) malloc(capacity);
+ if (!buffer->_data) {
+ free(buffer);
+ return NULL;
+ }
+
+ buffer->_position = 0;
+ buffer->_limit = buffer->_capacity = capacity;
+ buffer->_fixed = 0;
+ buffer->_status_err = 0;
+
+ sldns_buffer_invariant(buffer);
+
+ return buffer;
+}
+
+void
+sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
+{
+ assert(data != NULL);
+
+ buffer->_position = 0;
+ buffer->_limit = buffer->_capacity = size;
+ buffer->_fixed = 0;
+ buffer->_data = malloc(size);
+ if(!buffer->_data) {
+ buffer->_status_err = 1;
+ return;
+ }
+ memcpy(buffer->_data, data, size);
+ buffer->_status_err = 0;
+
+ sldns_buffer_invariant(buffer);
+}
+
+void
+sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
+{
+ memset(buffer, 0, sizeof(*buffer));
+ buffer->_data = data;
+ buffer->_capacity = buffer->_limit = size;
+ buffer->_fixed = 1;
+}
+
+int
+sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
+{
+ void *data;
+
+ sldns_buffer_invariant(buffer);
+ assert(buffer->_position <= capacity);
+
+ data = (uint8_t *) realloc(buffer->_data, capacity);
+ if (!data) {
+ buffer->_status_err = 1;
+ return 0;
+ } else {
+ buffer->_data = data;
+ buffer->_limit = buffer->_capacity = capacity;
+ return 1;
+ }
+}
+
+int
+sldns_buffer_reserve(sldns_buffer *buffer, size_t amount)
+{
+ sldns_buffer_invariant(buffer);
+ assert(!buffer->_fixed);
+ if (buffer->_capacity < buffer->_position + amount) {
+ size_t new_capacity = buffer->_capacity * 3 / 2;
+
+ if (new_capacity < buffer->_position + amount) {
+ new_capacity = buffer->_position + amount;
+ }
+ if (!sldns_buffer_set_capacity(buffer, new_capacity)) {
+ buffer->_status_err = 1;
+ return 0;
+ }
+ }
+ buffer->_limit = buffer->_capacity;
+ return 1;
+}
+
+int
+sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
+{
+ va_list args;
+ int written = 0;
+ size_t remaining;
+
+ if (sldns_buffer_status_ok(buffer)) {
+ sldns_buffer_invariant(buffer);
+ assert(buffer->_limit == buffer->_capacity);
+
+ remaining = sldns_buffer_remaining(buffer);
+ va_start(args, format);
+ written = vsnprintf((char *) sldns_buffer_current(buffer), remaining,
+ format, args);
+ va_end(args);
+ if (written == -1) {
+ buffer->_status_err = 1;
+ return -1;
+ } else if ((size_t) written >= remaining) {
+ if (!sldns_buffer_reserve(buffer, (size_t) written + 1)) {
+ buffer->_status_err = 1;
+ return -1;
+ }
+ va_start(args, format);
+ written = vsnprintf((char *) sldns_buffer_current(buffer),
+ sldns_buffer_remaining(buffer), format, args);
+ va_end(args);
+ if (written == -1) {
+ buffer->_status_err = 1;
+ return -1;
+ }
+ }
+ buffer->_position += written;
+ }
+ return written;
+}
+
+void
+sldns_buffer_free(sldns_buffer *buffer)
+{
+ if (!buffer) {
+ return;
+ }
+
+ if (!buffer->_fixed)
+ free(buffer->_data);
+
+ free(buffer);
+}
+
+void *
+sldns_buffer_export(sldns_buffer *buffer)
+{
+ buffer->_fixed = 1;
+ return buffer->_data;
+}
+
+void
+sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from)
+{
+ size_t tocopy = sldns_buffer_limit(from);
+
+ if(tocopy > sldns_buffer_capacity(result))
+ tocopy = sldns_buffer_capacity(result);
+ sldns_buffer_clear(result);
+ sldns_buffer_write(result, sldns_buffer_begin(from), tocopy);
+ sldns_buffer_flip(result);
+}
--- /dev/null
+/*
+ * buffer.h -- generic memory buffer.
+ *
+ * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ *
+ * The buffer module implements a generic buffer. The API is based on
+ * the java.nio.Buffer interface.
+ */
+
+#ifndef LDNS_SBUFFER_H
+#define LDNS_SBUFFER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef S_SPLINT_S
+# define INLINE
+#else
+# ifdef SWIG
+# define INLINE static
+# else
+# define INLINE static inline
+# endif
+#endif
+
+/*
+ * Copy data allowing for unaligned accesses in network byte order
+ * (big endian).
+ */
+INLINE uint16_t
+sldns_read_uint16(const void *src)
+{
+#ifdef ALLOW_UNALIGNED_ACCESSES
+ return ntohs(*(const uint16_t *) src);
+#else
+ const uint8_t *p = (const uint8_t *) src;
+ return ((uint16_t) p[0] << 8) | (uint16_t) p[1];
+#endif
+}
+
+INLINE uint32_t
+sldns_read_uint32(const void *src)
+{
+#ifdef ALLOW_UNALIGNED_ACCESSES
+ return ntohl(*(const uint32_t *) src);
+#else
+ const uint8_t *p = (const uint8_t *) src;
+ return ( ((uint32_t) p[0] << 24)
+ | ((uint32_t) p[1] << 16)
+ | ((uint32_t) p[2] << 8)
+ | (uint32_t) p[3]);
+#endif
+}
+
+/*
+ * Copy data allowing for unaligned accesses in network byte order
+ * (big endian).
+ */
+INLINE void
+sldns_write_uint16(void *dst, uint16_t data)
+{
+#ifdef ALLOW_UNALIGNED_ACCESSES
+ * (uint16_t *) dst = htons(data);
+#else
+ uint8_t *p = (uint8_t *) dst;
+ p[0] = (uint8_t) ((data >> 8) & 0xff);
+ p[1] = (uint8_t) (data & 0xff);
+#endif
+}
+
+INLINE void
+sldns_write_uint32(void *dst, uint32_t data)
+{
+#ifdef ALLOW_UNALIGNED_ACCESSES
+ * (uint32_t *) dst = htonl(data);
+#else
+ uint8_t *p = (uint8_t *) dst;
+ p[0] = (uint8_t) ((data >> 24) & 0xff);
+ p[1] = (uint8_t) ((data >> 16) & 0xff);
+ p[2] = (uint8_t) ((data >> 8) & 0xff);
+ p[3] = (uint8_t) (data & 0xff);
+#endif
+}
+
+
+/**
+ * \file sbuffer.h
+ *
+ * This file contains the definition of sldns_buffer, and functions to manipulate those.
+ */
+
+/**
+ * implementation of buffers to ease operations
+ *
+ * sldns_buffers can contain arbitrary information, per octet. You can write
+ * to the current end of a buffer, read from the current position, and
+ * access any data within it.
+ */
+struct sldns_buffer
+{
+ /** The current position used for reading/writing */
+ size_t _position;
+
+ /** The read/write limit */
+ size_t _limit;
+
+ /** The amount of data the buffer can contain */
+ size_t _capacity;
+
+ /** The data contained in the buffer */
+ uint8_t *_data;
+
+ /** If the buffer is fixed it cannot be resized */
+ unsigned _fixed : 1;
+
+ /** The current state of the buffer. If writing to the buffer fails
+ * for any reason, this value is changed. This way, you can perform
+ * multiple writes in sequence and check for success afterwards. */
+ unsigned _status_err : 1;
+};
+typedef struct sldns_buffer sldns_buffer;
+
+#ifdef NDEBUG
+INLINE void
+sldns_buffer_invariant(sldns_buffer *ATTR_UNUSED(buffer))
+{
+}
+#else
+INLINE void
+sldns_buffer_invariant(sldns_buffer *buffer)
+{
+ assert(buffer != NULL);
+ assert(buffer->_position <= buffer->_limit);
+ assert(buffer->_limit <= buffer->_capacity);
+ assert(buffer->_data != NULL);
+}
+#endif
+
+/**
+ * creates a new buffer with the specified capacity.
+ *
+ * \param[in] capacity the size (in bytes) to allocate for the buffer
+ * \return the created buffer
+ */
+sldns_buffer *sldns_buffer_new(size_t capacity);
+
+/**
+ * creates a buffer with the specified data. The data IS copied
+ * and MEMORY allocations are done. The buffer is not fixed and can
+ * be resized using buffer_reserve().
+ *
+ * \param[in] buffer pointer to the buffer to put the data in
+ * \param[in] data the data to encapsulate in the buffer
+ * \param[in] size the size of the data
+ */
+void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
+
+/**
+ * Setup a buffer with the data pointed to. No data copied, no memory allocs.
+ * The buffer is fixed.
+ * \param[in] buffer pointer to the buffer to put the data in
+ * \param[in] data the data to encapsulate in the buffer
+ * \param[in] size the size of the data
+ */
+void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
+
+/**
+ * clears the buffer and make it ready for writing. The buffer's limit
+ * is set to the capacity and the position is set to 0.
+ * \param[in] buffer the buffer to clear
+ */
+INLINE void sldns_buffer_clear(sldns_buffer *buffer)
+{
+ sldns_buffer_invariant(buffer);
+
+ /* reset status here? */
+
+ buffer->_position = 0;
+ buffer->_limit = buffer->_capacity;
+}
+
+/**
+ * makes the buffer ready for reading the data that has been written to
+ * the buffer. The buffer's limit is set to the current position and
+ * the position is set to 0.
+ *
+ * \param[in] buffer the buffer to flip
+ * \return void
+ */
+INLINE void sldns_buffer_flip(sldns_buffer *buffer)
+{
+ sldns_buffer_invariant(buffer);
+
+ buffer->_limit = buffer->_position;
+ buffer->_position = 0;
+}
+
+/**
+ * make the buffer ready for re-reading the data. The buffer's
+ * position is reset to 0.
+ * \param[in] buffer the buffer to rewind
+ */
+INLINE void sldns_buffer_rewind(sldns_buffer *buffer)
+{
+ sldns_buffer_invariant(buffer);
+
+ buffer->_position = 0;
+}
+
+/**
+ * returns the current position in the buffer (as a number of bytes)
+ * \param[in] buffer the buffer
+ * \return the current position
+ */
+INLINE size_t
+sldns_buffer_position(sldns_buffer *buffer)
+{
+ return buffer->_position;
+}
+
+/**
+ * sets the buffer's position to MARK. The position must be less than
+ * or equal to the buffer's limit.
+ * \param[in] buffer the buffer
+ * \param[in] mark the mark to use
+ */
+INLINE void
+sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
+{
+ assert(mark <= buffer->_limit);
+ buffer->_position = mark;
+}
+
+/**
+ * changes the buffer's position by COUNT bytes. The position must not
+ * be moved behind the buffer's limit or before the beginning of the
+ * buffer.
+ * \param[in] buffer the buffer
+ * \param[in] count the count to use
+ */
+INLINE void
+sldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
+{
+ assert(buffer->_position + count <= buffer->_limit);
+ buffer->_position += count;
+}
+
+/**
+ * returns the maximum size of the buffer
+ * \param[in] buffer
+ * \return the size
+ */
+INLINE size_t
+sldns_buffer_limit(sldns_buffer *buffer)
+{
+ return buffer->_limit;
+}
+
+/**
+ * changes the buffer's limit. If the buffer's position is greater
+ * than the new limit the position is set to the limit.
+ * \param[in] buffer the buffer
+ * \param[in] limit the new limit
+ */
+INLINE void
+sldns_buffer_set_limit(sldns_buffer *buffer, size_t limit)
+{
+ assert(limit <= buffer->_capacity);
+ buffer->_limit = limit;
+ if (buffer->_position > buffer->_limit)
+ buffer->_position = buffer->_limit;
+}
+
+/**
+ * returns the number of bytes the buffer can hold.
+ * \param[in] buffer the buffer
+ * \return the number of bytes
+ */
+INLINE size_t
+sldns_buffer_capacity(sldns_buffer *buffer)
+{
+ return buffer->_capacity;
+}
+
+/**
+ * changes the buffer's capacity. The data is reallocated so any
+ * pointers to the data may become invalid. The buffer's limit is set
+ * to the buffer's new capacity.
+ * \param[in] buffer the buffer
+ * \param[in] capacity the capacity to use
+ * \return whether this failed or succeeded
+ */
+int sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity);
+
+/**
+ * ensures BUFFER can contain at least AMOUNT more bytes. The buffer's
+ * capacity is increased if necessary using buffer_set_capacity().
+ *
+ * The buffer's limit is always set to the (possibly increased)
+ * capacity.
+ * \param[in] buffer the buffer
+ * \param[in] amount amount to use
+ * \return whether this failed or succeeded
+ */
+int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
+
+/**
+ * returns a pointer to the data at the indicated position.
+ * \param[in] buffer the buffer
+ * \param[in] at position
+ * \return the pointer to the data
+ */
+INLINE uint8_t *
+sldns_buffer_at(const sldns_buffer *buffer, size_t at)
+{
+ assert(at <= buffer->_limit);
+ return buffer->_data + at;
+}
+
+/**
+ * returns a pointer to the beginning of the buffer (the data at
+ * position 0).
+ * \param[in] buffer the buffer
+ * \return the pointer
+ */
+INLINE uint8_t *
+sldns_buffer_begin(const sldns_buffer *buffer)
+{
+ return sldns_buffer_at(buffer, 0);
+}
+
+/**
+ * returns a pointer to the end of the buffer (the data at the buffer's
+ * limit).
+ * \param[in] buffer the buffer
+ * \return the pointer
+ */
+INLINE uint8_t *
+sldns_buffer_end(sldns_buffer *buffer)
+{
+ return sldns_buffer_at(buffer, buffer->_limit);
+}
+
+/**
+ * returns a pointer to the data at the buffer's current position.
+ * \param[in] buffer the buffer
+ * \return the pointer
+ */
+INLINE uint8_t *
+sldns_buffer_current(sldns_buffer *buffer)
+{
+ return sldns_buffer_at(buffer, buffer->_position);
+}
+
+/**
+ * returns the number of bytes remaining between the indicated position and
+ * the limit.
+ * \param[in] buffer the buffer
+ * \param[in] at indicated position
+ * \return number of bytes
+ */
+INLINE size_t
+sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
+{
+ sldns_buffer_invariant(buffer);
+ assert(at <= buffer->_limit);
+ return buffer->_limit - at;
+}
+
+/**
+ * returns the number of bytes remaining between the buffer's position and
+ * limit.
+ * \param[in] buffer the buffer
+ * \return the number of bytes
+ */
+INLINE size_t
+sldns_buffer_remaining(sldns_buffer *buffer)
+{
+ return sldns_buffer_remaining_at(buffer, buffer->_position);
+}
+
+/**
+ * checks if the buffer has at least COUNT more bytes available.
+ * Before reading or writing the caller needs to ensure enough space
+ * is available!
+ * \param[in] buffer the buffer
+ * \param[in] at indicated position
+ * \param[in] count how much is available
+ * \return true or false (as int?)
+ */
+INLINE int
+sldns_buffer_available_at(sldns_buffer *buffer, size_t at, size_t count)
+{
+ return count <= sldns_buffer_remaining_at(buffer, at);
+}
+
+/**
+ * checks if the buffer has count bytes available at the current position
+ * \param[in] buffer the buffer
+ * \param[in] count how much is available
+ * \return true or false (as int?)
+ */
+INLINE int
+sldns_buffer_available(sldns_buffer *buffer, size_t count)
+{
+ return sldns_buffer_available_at(buffer, buffer->_position, count);
+}
+
+/**
+ * writes the given data to the buffer at the specified position
+ * \param[in] buffer the buffer
+ * \param[in] at the position (in number of bytes) to write the data at
+ * \param[in] data pointer to the data to write to the buffer
+ * \param[in] count the number of bytes of data to write
+ */
+INLINE void
+sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
+{
+ assert(sldns_buffer_available_at(buffer, at, count));
+ memcpy(buffer->_data + at, data, count);
+}
+
+/**
+ * writes count bytes of data to the current position of the buffer
+ * \param[in] buffer the buffer
+ * \param[in] data the data to write
+ * \param[in] count the lenght of the data to write
+ */
+INLINE void
+sldns_buffer_write(sldns_buffer *buffer, const void *data, size_t count)
+{
+ sldns_buffer_write_at(buffer, buffer->_position, data, count);
+ buffer->_position += count;
+}
+
+/**
+ * copies the given (null-delimited) string to the specified position at the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at the position in the buffer
+ * \param[in] str the string to write
+ */
+INLINE void
+sldns_buffer_write_string_at(sldns_buffer *buffer, size_t at, const char *str)
+{
+ sldns_buffer_write_at(buffer, at, str, strlen(str));
+}
+
+/**
+ * copies the given (null-delimited) string to the current position at the buffer
+ * \param[in] buffer the buffer
+ * \param[in] str the string to write
+ */
+INLINE void
+sldns_buffer_write_string(sldns_buffer *buffer, const char *str)
+{
+ sldns_buffer_write(buffer, str, strlen(str));
+}
+
+/**
+ * writes the given byte of data at the given position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at the position in the buffer
+ * \param[in] data the 8 bits to write
+ */
+INLINE void
+sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
+{
+ assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
+ buffer->_data[at] = data;
+}
+
+/**
+ * writes the given byte of data at the current position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] data the 8 bits to write
+ */
+INLINE void
+sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
+{
+ sldns_buffer_write_u8_at(buffer, buffer->_position, data);
+ buffer->_position += sizeof(data);
+}
+
+/**
+ * writes the given 2 byte integer at the given position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at the position in the buffer
+ * \param[in] data the 16 bits to write
+ */
+INLINE void
+sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
+{
+ assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
+ sldns_write_uint16(buffer->_data + at, data);
+}
+
+/**
+ * writes the given 2 byte integer at the current position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] data the 16 bits to write
+ */
+INLINE void
+sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
+{
+ sldns_buffer_write_u16_at(buffer, buffer->_position, data);
+ buffer->_position += sizeof(data);
+}
+
+/**
+ * writes the given 4 byte integer at the given position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at the position in the buffer
+ * \param[in] data the 32 bits to write
+ */
+INLINE void
+sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
+{
+ assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
+ sldns_write_uint32(buffer->_data + at, data);
+}
+
+/**
+ * writes the given 4 byte integer at the current position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] data the 32 bits to write
+ */
+INLINE void
+sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
+{
+ sldns_buffer_write_u32_at(buffer, buffer->_position, data);
+ buffer->_position += sizeof(data);
+}
+
+/**
+ * copies count bytes of data at the given position to the given data-array
+ * \param[in] buffer the buffer
+ * \param[in] at the position in the buffer to start
+ * \param[out] data buffer to copy to
+ * \param[in] count the length of the data to copy
+ */
+INLINE void
+sldns_buffer_read_at(sldns_buffer *buffer, size_t at, void *data, size_t count)
+{
+ assert(sldns_buffer_available_at(buffer, at, count));
+ memcpy(data, buffer->_data + at, count);
+}
+
+/**
+ * copies count bytes of data at the current position to the given data-array
+ * \param[in] buffer the buffer
+ * \param[out] data buffer to copy to
+ * \param[in] count the length of the data to copy
+ */
+INLINE void
+sldns_buffer_read(sldns_buffer *buffer, void *data, size_t count)
+{
+ sldns_buffer_read_at(buffer, buffer->_position, data, count);
+ buffer->_position += count;
+}
+
+/**
+ * returns the byte value at the given position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at the position in the buffer
+ * \return 1 byte integer
+ */
+INLINE uint8_t
+sldns_buffer_read_u8_at(sldns_buffer *buffer, size_t at)
+{
+ assert(sldns_buffer_available_at(buffer, at, sizeof(uint8_t)));
+ return buffer->_data[at];
+}
+
+/**
+ * returns the byte value at the current position in the buffer
+ * \param[in] buffer the buffer
+ * \return 1 byte integer
+ */
+INLINE uint8_t
+sldns_buffer_read_u8(sldns_buffer *buffer)
+{
+ uint8_t result = sldns_buffer_read_u8_at(buffer, buffer->_position);
+ buffer->_position += sizeof(uint8_t);
+ return result;
+}
+
+/**
+ * returns the 2-byte integer value at the given position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at position in the buffer
+ * \return 2 byte integer
+ */
+INLINE uint16_t
+sldns_buffer_read_u16_at(sldns_buffer *buffer, size_t at)
+{
+ assert(sldns_buffer_available_at(buffer, at, sizeof(uint16_t)));
+ return sldns_read_uint16(buffer->_data + at);
+}
+
+/**
+ * returns the 2-byte integer value at the current position in the buffer
+ * \param[in] buffer the buffer
+ * \return 2 byte integer
+ */
+INLINE uint16_t
+sldns_buffer_read_u16(sldns_buffer *buffer)
+{
+ uint16_t result = sldns_buffer_read_u16_at(buffer, buffer->_position);
+ buffer->_position += sizeof(uint16_t);
+ return result;
+}
+
+/**
+ * returns the 4-byte integer value at the given position in the buffer
+ * \param[in] buffer the buffer
+ * \param[in] at position in the buffer
+ * \return 4 byte integer
+ */
+INLINE uint32_t
+sldns_buffer_read_u32_at(sldns_buffer *buffer, size_t at)
+{
+ assert(sldns_buffer_available_at(buffer, at, sizeof(uint32_t)));
+ return sldns_read_uint32(buffer->_data + at);
+}
+
+/**
+ * returns the 4-byte integer value at the current position in the buffer
+ * \param[in] buffer the buffer
+ * \return 4 byte integer
+ */
+INLINE uint32_t
+sldns_buffer_read_u32(sldns_buffer *buffer)
+{
+ uint32_t result = sldns_buffer_read_u32_at(buffer, buffer->_position);
+ buffer->_position += sizeof(uint32_t);
+ return result;
+}
+
+/**
+ * returns the status of the buffer
+ * \param[in] buffer
+ * \return the status
+ */
+INLINE int
+sldns_buffer_status(sldns_buffer *buffer)
+{
+ return (int)buffer->_status_err;
+}
+
+/**
+ * returns true if the status of the buffer is LDNS_STATUS_OK, false otherwise
+ * \param[in] buffer the buffer
+ * \return true or false
+ */
+INLINE int
+sldns_buffer_status_ok(sldns_buffer *buffer)
+{
+ if (buffer) {
+ return sldns_buffer_status(buffer) == 0;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * prints to the buffer, increasing the capacity if required using
+ * buffer_reserve(). The buffer's position is set to the terminating '\\0'
+ * Returns the number of characters written (not including the
+ * terminating '\\0') or -1 on failure.
+ */
+int sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
+ ATTR_FORMAT(printf, 2, 3);
+
+/**
+ * frees the buffer.
+ * \param[in] *buffer the buffer to be freed
+ * \return void
+ */
+void sldns_buffer_free(sldns_buffer *buffer);
+
+/**
+ * Makes the buffer fixed and returns a pointer to the data. The
+ * caller is responsible for free'ing the result.
+ * \param[in] *buffer the buffer to be exported
+ * \return void
+ */
+void *sldns_buffer_export(sldns_buffer *buffer);
+
+/**
+ * Copy contents of the from buffer to the result buffer and then flips
+ * the result buffer. Data will be silently truncated if the result buffer is
+ * too small.
+ * \param[out] *result resulting buffer which is copied to.
+ * \param[in] *from what to copy to result.
+ */
+void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_SBUFFER_H */
--- /dev/null
+/**
+ * str2wire.c - read txt presentation of RRs
+ *
+ * (c) NLnet Labs, 2005-2006
+ *
+ * See the file LICENSE for the license
+ */
+
+/**
+ * \file
+ *
+ * Parses text to wireformat.
+ */
+#include "config.h"
+#include "sldns/str2wire.h"
+#include "sldns/wire2str.h"
+#include "sldns/sbuffer.h"
+#include "sldns/parse.h"
+#include "sldns/parseutil.h"
+#include <ctype.h>
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+/** return an error */
+#define RET_ERR(e, off) ((int)((e)|((off)<<LDNS_WIREPARSE_SHIFT)))
+/** Move parse error but keep its ID */
+#define RET_ERR_SHIFT(e, move) RET_ERR(LDNS_WIREPARSE_ERROR(e), LDNS_WIREPARSE_OFFSET(e)+(move));
+#define LDNS_IP6ADDRLEN (128/8)
+
+/*
+ * No special care is taken, all dots are translated into
+ * label separators.
+ * @param rel: true if the domain is not absolute (not terminated in .).
+ * The output is then still terminated with a '0' rootlabel.
+ */
+static int sldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf,
+ size_t* olen, int* rel)
+{
+ size_t len;
+
+ const char *s;
+ uint8_t *q, *pq, label_len;
+
+ if(rel) *rel = 0;
+ len = strlen((char*)str);
+ /* octet representation can make strings a lot longer than actual length */
+ if (len > LDNS_MAX_DOMAINLEN * 4) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 0);
+ }
+ if (0 == len) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, 0);
+ }
+
+ /* root label */
+ if (1 == len && *str == '.') {
+ if(*olen < 1)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0);
+ buf[0] = 0;
+ *olen = 1;
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ /* get on with the rest */
+
+ /* s is on the current character in the string
+ * pq points to where the labellength is going to go
+ * label_len keeps track of the current label's length
+ * q builds the dname inside the buf array
+ */
+ len = 0;
+ if(*olen < 1)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0);
+ q = buf+1;
+ pq = buf;
+ label_len = 0;
+ for (s = str; *s; s++, q++) {
+ if (q >= buf + *olen)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf);
+ if (q > buf + LDNS_MAX_DOMAINLEN)
+ return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf);
+ switch (*s) {
+ case '.':
+ if (label_len > LDNS_MAX_LABELLEN) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf);
+ }
+ if (label_len == 0) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf);
+ }
+ len += label_len + 1;
+ *q = 0;
+ *pq = label_len;
+ label_len = 0;
+ pq = q;
+ break;
+ case '\\':
+ /* octet value or literal char */
+ s += 1;
+ if (!sldns_parse_escape(q, &s)) {
+ *q = 0;
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, q-buf);
+ }
+ s -= 1;
+ label_len++;
+ break;
+ default:
+ *q = (uint8_t)*s;
+ label_len++;
+ }
+ }
+
+ /* add root label if last char was not '.' */
+ if(label_len != 0) {
+ if(rel) *rel = 1;
+ if (q >= buf + *olen)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf);
+ if (q > buf + LDNS_MAX_DOMAINLEN) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf);
+ }
+ if (label_len > LDNS_MAX_LABELLEN) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf);
+ }
+ if (label_len == 0) { /* label_len 0 but not . at end? */
+ return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf);
+ }
+ len += label_len + 1;
+ *pq = label_len;
+ *q = 0;
+ }
+ len++;
+ *olen = len;
+
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len)
+{
+ return sldns_str2wire_dname_buf_rel(str, buf, len, NULL);
+}
+
+int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len,
+ uint8_t* origin, size_t origin_len)
+{
+ size_t dlen = *len;
+ int rel = 0;
+ int s = sldns_str2wire_dname_buf_rel(str, buf, &dlen, &rel);
+ if(s) return s;
+
+ if(rel && origin && dlen > 0) {
+ if(dlen + origin_len - 1 > LDNS_MAX_DOMAINLEN)
+ return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW,
+ LDNS_MAX_DOMAINLEN);
+ if(dlen + origin_len - 1 > *len)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ *len);
+ memmove(buf+dlen-1, origin, origin_len);
+ *len = dlen + origin_len - 1;
+ } else
+ *len = dlen;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+uint8_t* sldns_str2wire_dname(const char* str, size_t* len)
+{
+ uint8_t dname[LDNS_MAX_DOMAINLEN+1];
+ *len = sizeof(dname);
+ if(sldns_str2wire_dname_buf(str, dname, len) == 0) {
+ uint8_t* r = (uint8_t*)malloc(*len);
+ if(r) return memcpy(r, dname, *len);
+ }
+ *len = 0;
+ return NULL;
+}
+
+/** read owner name */
+static int
+rrinternal_get_owner(sldns_buffer* strbuf, uint8_t* rr, size_t* len,
+ size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev,
+ size_t prev_len, char* token, size_t token_len)
+{
+ /* split the rr in its parts -1 signals trouble */
+ if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
+ sldns_buffer_position(strbuf));
+ }
+
+ if(strcmp(token, "@") == 0) {
+ uint8_t* tocopy;
+ if (origin) {
+ *dname_len = origin_len;
+ tocopy = origin;
+ } else if (prev) {
+ *dname_len = prev_len;
+ tocopy = prev;
+ } else {
+ /* default to root */
+ *dname_len = 1;
+ tocopy = (uint8_t*)"\0";
+ }
+ if(*len < *dname_len)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(strbuf));
+ memmove(rr, tocopy, *dname_len);
+ } else if(strlen(token) == 0) {
+ /* no ownername was given, try prev, if that fails
+ * origin, else default to root */
+ uint8_t* tocopy;
+ if(prev) {
+ *dname_len = prev_len;
+ tocopy = prev;
+ } else if(origin) {
+ *dname_len = origin_len;
+ tocopy = origin;
+ } else {
+ *dname_len = 1;
+ tocopy = (uint8_t*)"\0";
+ }
+ if(*len < *dname_len)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(strbuf));
+ memmove(rr, tocopy, *dname_len);
+ } else {
+ size_t dlen = *len;
+ int s = sldns_str2wire_dname_buf_origin(token, rr, &dlen,
+ origin, origin_len);
+ if(s) return RET_ERR_SHIFT(s,
+ sldns_buffer_position(strbuf)-strlen(token));
+ *dname_len = dlen;
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** read ttl */
+static int
+rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len,
+ int* not_there, uint32_t* ttl, uint32_t default_ttl)
+{
+ const char* endptr;
+ if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL,
+ sldns_buffer_position(strbuf));
+ }
+ *ttl = (uint32_t) sldns_str2period(token, &endptr);
+
+ if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) {
+ *not_there = 1;
+ /* ah, it's not there or something */
+ if (default_ttl == 0) {
+ *ttl = LDNS_DEFAULT_TTL;
+ } else {
+ *ttl = default_ttl;
+ }
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** read class */
+static int
+rrinternal_get_class(sldns_buffer* strbuf, char* token, size_t token_len,
+ int* not_there, uint16_t* cl)
+{
+ /* if 'not_there' then we got token from previous parse routine */
+ if(!*not_there) {
+ /* parse new token for class */
+ if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_CLASS,
+ sldns_buffer_position(strbuf));
+ }
+ } else *not_there = 0;
+ *cl = sldns_get_rr_class_by_name(token);
+ /* class can be left out too, assume IN, current token must be type */
+ if(*cl == 0 && strcmp(token, "CLASS0") != 0) {
+ *not_there = 1;
+ *cl = LDNS_RR_CLASS_IN;
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** read type */
+static int
+rrinternal_get_type(sldns_buffer* strbuf, char* token, size_t token_len,
+ int* not_there, uint16_t* tp)
+{
+ /* if 'not_there' then we got token from previous parse routine */
+ if(!*not_there) {
+ /* parse new token for type */
+ if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE,
+ sldns_buffer_position(strbuf));
+ }
+ }
+ *tp = sldns_get_rr_type_by_name(token);
+ if(*tp == 0 && strcmp(token, "TYPE0") != 0) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE,
+ sldns_buffer_position(strbuf));
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** put type, class, ttl into rr buffer */
+static int
+rrinternal_write_typeclassttl(sldns_buffer* strbuf, uint8_t* rr, size_t len,
+ size_t dname_len, uint16_t tp, uint16_t cl, uint32_t ttl, int question)
+{
+ if(question) {
+ /* question is : name, type, class */
+ if(dname_len + 4 > len)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(strbuf));
+ sldns_write_uint16(rr+dname_len, tp);
+ sldns_write_uint16(rr+dname_len+2, cl);
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ /* type(2), class(2), ttl(4), rdatalen(2 (later)) = 10 */
+ if(dname_len + 10 > len)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(strbuf));
+ sldns_write_uint16(rr+dname_len, tp);
+ sldns_write_uint16(rr+dname_len+2, cl);
+ sldns_write_uint32(rr+dname_len+4, ttl);
+ sldns_write_uint16(rr+dname_len+8, 0); /* rdatalen placeholder */
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** find delimiters for type */
+static const char*
+rrinternal_get_delims(sldns_rdf_type rdftype, uint16_t r_cnt, uint16_t r_max)
+{
+ switch(rdftype) {
+ case LDNS_RDF_TYPE_B64 :
+ case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */
+ case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */
+ case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */
+ case LDNS_RDF_TYPE_IPSECKEY :
+ case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) {
+ return "\n";
+ }
+ break;
+ default : break;
+ }
+ return "\n\t ";
+}
+
+/* Syntactic sugar for sldns_rr_new_frm_str_internal */
+static int
+sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type)
+{
+ return rdf_type == LDNS_RDF_TYPE_STR ||
+ rdf_type == LDNS_RDF_TYPE_LONG_STR;
+}
+
+/** see if rdata is quoted */
+static int
+rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters,
+ sldns_rdf_type rdftype)
+{
+ if(sldns_rdf_type_maybe_quoted(rdftype) &&
+ sldns_buffer_remaining(strbuf) > 0) {
+
+ /* skip spaces */
+ while(sldns_buffer_remaining(strbuf) > 0 &&
+ *(sldns_buffer_current(strbuf)) == ' ') {
+ sldns_buffer_skip(strbuf, 1);
+ }
+
+ if(sldns_buffer_remaining(strbuf) > 0 &&
+ *(sldns_buffer_current(strbuf)) == '\"') {
+ *delimiters = "\"\0";
+ sldns_buffer_skip(strbuf, 1);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/** spool hex data into rdata */
+static int
+rrinternal_spool_hex(char* token, uint8_t* rr, size_t rr_len,
+ size_t rr_cur_len, size_t* cur_hex_data_size, size_t hex_data_size)
+{
+ char* p = token;
+ while(*p) {
+ if(isspace((unsigned char)*p)) {
+ p++;
+ continue;
+ }
+ if(!isxdigit((unsigned char)*p))
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA,
+ p-token);
+ if(*cur_hex_data_size >= hex_data_size)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA,
+ p-token);
+ /* extra robust check */
+ if(rr_cur_len+(*cur_hex_data_size)/2 >= rr_len)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ p-token);
+ /* see if 16s or 1s */
+ if( ((*cur_hex_data_size)&1) == 0) {
+ rr[rr_cur_len+(*cur_hex_data_size)/2] =
+ (uint8_t)sldns_hexdigit_to_int(*p)*16;
+ } else {
+ rr[rr_cur_len+(*cur_hex_data_size)/2] +=
+ (uint8_t)sldns_hexdigit_to_int(*p);
+ }
+ p++;
+ (*cur_hex_data_size)++;
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** read unknown rr type format */
+static int
+rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len,
+ uint8_t* rr, size_t* rr_len, size_t* rr_cur_len, size_t pre_data_pos)
+{
+ const char* delim = "\n\t ";
+ size_t hex_data_size, cur_hex_data_size;
+ /* go back to before \#
+ * and skip it while setting delimiters better
+ */
+ sldns_buffer_set_position(strbuf, pre_data_pos);
+ if(sldns_bget_token(strbuf, token, delim, token_len) == -1)
+ return LDNS_WIREPARSE_ERR_GENERAL; /* should not fail */
+ /* read rdata octet length */
+ if(sldns_bget_token(strbuf, token, delim, token_len) == -1) {
+ /* something goes very wrong here */
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA,
+ sldns_buffer_position(strbuf));
+ }
+ hex_data_size = (size_t)atoi(token);
+ if(hex_data_size > LDNS_MAX_RDFLEN ||
+ *rr_cur_len + hex_data_size > *rr_len) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(strbuf));
+ }
+ /* copy hex chars into hex str (2 chars per byte) */
+ hex_data_size *= 2;
+ cur_hex_data_size = 0;
+ while(cur_hex_data_size < hex_data_size) {
+ int status;
+ ssize_t c = sldns_bget_token(strbuf, token, delim, token_len);
+ if((status = rrinternal_spool_hex(token, rr, *rr_len,
+ *rr_cur_len, &cur_hex_data_size, hex_data_size)) != 0)
+ return RET_ERR_SHIFT(status,
+ sldns_buffer_position(strbuf)-strlen(token));
+ if(c == -1) {
+ if(cur_hex_data_size != hex_data_size)
+ return RET_ERR(
+ LDNS_WIREPARSE_ERR_SYNTAX_RDATA,
+ sldns_buffer_position(strbuf));
+ break;
+ }
+ }
+ *rr_cur_len += hex_data_size/2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** parse normal RR rdata element */
+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,
+ uint8_t* origin, size_t origin_len)
+{
+ size_t len;
+ int status;
+
+ switch(rdftype) {
+ case LDNS_RDF_TYPE_DNAME:
+ /* check if the origin should be used or concatenated */
+ if(strcmp(token, "@") == 0) {
+ uint8_t* tocopy;
+ size_t copylen;
+ if(origin) {
+ copylen = origin_len;
+ tocopy = origin;
+ } else if(rr_type == LDNS_RR_TYPE_SOA) {
+ copylen = dname_len;
+ tocopy = rr; /* copy rr owner name */
+ } else {
+ copylen = 1;
+ tocopy = (uint8_t*)"\0";
+ }
+ if((*rr_cur_len) + copylen > rr_len)
+ return RET_ERR(
+ LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(strbuf));
+ memmove(rr+*rr_cur_len, tocopy, copylen);
+ (*rr_cur_len) += copylen;
+ } else {
+ size_t dlen = rr_len - (*rr_cur_len);
+ int s = sldns_str2wire_dname_buf_origin(token,
+ rr+*rr_cur_len, &dlen, origin, origin_len);
+ if(s) return RET_ERR_SHIFT(s,
+ sldns_buffer_position(strbuf)-strlen(token));
+ (*rr_cur_len) += dlen;
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+
+ case LDNS_RDF_TYPE_HEX:
+ case LDNS_RDF_TYPE_B64:
+ /* When this is the last rdata field, then the
+ * rest should be read in (cause then these
+ * rdf types may contain spaces). */
+ if(r_cnt == r_max - 1) {
+ size_t tlen = strlen(token);
+ (void)sldns_bget_token(strbuf, token+tlen, "\n",
+ token_len - tlen);
+ }
+ break;
+ default:
+ break;
+ }
+
+ len = rr_len - (*rr_cur_len);
+ if((status=sldns_str2wire_rdf_buf(token, rr+(*rr_cur_len), &len,
+ rdftype)) != 0)
+ return RET_ERR_SHIFT(status,
+ sldns_buffer_position(strbuf)-strlen(token));
+ *rr_cur_len += len;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/**
+ * Parse one rdf token. Takes care of quotes and parenthesis.
+ */
+static int
+sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len,
+ int* quoted, int* parens, size_t* pre_data_pos,
+ const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen)
+{
+ size_t slen;
+
+ /* skip spaces */
+ while(sldns_buffer_remaining(strbuf) > 0 && !*quoted &&
+ *(sldns_buffer_current(strbuf)) == ' ') {
+ sldns_buffer_skip(strbuf, 1);
+ }
+
+ *pre_data_pos = sldns_buffer_position(strbuf);
+ if(sldns_bget_token_par(strbuf, token, (*quoted)?"\"":delimiters,
+ token_len, parens, (*quoted)?NULL:" \t") == -1) {
+ return 0;
+ }
+ slen = strlen(token);
+ /* check if not quoted yet, and we have encountered quotes */
+ if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
+ slen >= 2 &&
+ (token[0] == '"' || token[0] == '\'') &&
+ (token[slen-1] == '"' || token[slen-1] == '\'')) {
+ /* move token two smaller (quotes) with endnull */
+ memmove(token, token+1, slen-2);
+ token[slen-2] = 0;
+ slen -= 2;
+ *quoted = 1;
+ } else if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
+ slen >= 2 &&
+ (token[0] == '"' || token[0] == '\'')) {
+ /* got the start quote (remove it) but read remainder
+ * of quoted string as well into remainder of token */
+ memmove(token, token+1, slen-1);
+ token[slen-1] = 0;
+ slen -= 1;
+ *quoted = 1;
+ /* rewind buffer over skipped whitespace */
+ while(sldns_buffer_position(strbuf) > 0 &&
+ (sldns_buffer_current(strbuf)[-1] == ' ' ||
+ sldns_buffer_current(strbuf)[-1] == '\t')) {
+ sldns_buffer_skip(strbuf, -1);
+ }
+ if(sldns_bget_token_par(strbuf, token+slen,
+ "\"", token_len-slen,
+ parens, NULL) == -1) {
+ return 0;
+ }
+ slen = strlen(token);
+ }
+ *token_strlen = slen;
+ return 1;
+}
+
+/** Add space and one more rdf token onto the existing token string. */
+static int
+sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len,
+ int* quoted, int* parens, size_t* pre_data_pos,
+ const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen)
+{
+ size_t addlen = *token_len - *token_strlen;
+ size_t addstrlen = 0;
+
+ /* add space */
+ if(addlen < 1) return 0;
+ token[*token_strlen] = ' ';
+ token[++(*token_strlen)] = 0;
+
+ /* read another token */
+ addlen = *token_len - *token_strlen;
+ if(!sldns_parse_rdf_token(strbuf, token+*token_strlen, addlen, quoted,
+ parens, pre_data_pos, delimiters, rdftype, &addstrlen))
+ return 0;
+ (*token_strlen) += addstrlen;
+ return 1;
+}
+
+/** parse rdata from string into rr buffer(-remainder after dname). */
+static int
+rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
+ uint8_t* rr, size_t* rr_len, size_t dname_len, uint16_t rr_type,
+ 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 rr_cur_len = dname_len + 10, pre_data_pos, token_strlen;
+ int was_unknown_rr_format = 0, parens = 0, status, quoted;
+ const char* delimiters;
+ sldns_rdf_type rdftype;
+ /* a desc is always returned */
+ if(!desc) return LDNS_WIREPARSE_ERR_GENERAL;
+ r_max = sldns_rr_descriptor_maximum(desc);
+ r_min = sldns_rr_descriptor_minimum(desc);
+ /* robust check */
+ if(rr_cur_len > *rr_len)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(strbuf));
+
+ /* because number of fields can be variable, we can't rely on
+ * _maximum() only */
+ for(r_cnt=0; r_cnt < r_max; r_cnt++) {
+ rdftype = sldns_rr_descriptor_field_type(desc, r_cnt);
+ delimiters = rrinternal_get_delims(rdftype, r_cnt, r_max);
+ quoted = rrinternal_get_quoted(strbuf, &delimiters, rdftype);
+
+ if(!sldns_parse_rdf_token(strbuf, token, token_len, "ed,
+ &parens, &pre_data_pos, delimiters, rdftype,
+ &token_strlen))
+ break;
+
+ /* rfc3597 specifies that any type can be represented
+ * with \# method, which can contain spaces...
+ * it does specify size though... */
+
+ /* unknown RR data */
+ if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 &&
+ !quoted && (token_strlen == 2 || token[2]==' ')) {
+ was_unknown_rr_format = 1;
+ if((status=rrinternal_parse_unknown(strbuf, token,
+ token_len, rr, rr_len, &rr_cur_len,
+ pre_data_pos)) != 0)
+ return status;
+ } else if(token_strlen > 0 || quoted) {
+ if(rdftype == LDNS_RDF_TYPE_HIP) {
+ /* affix the HIT and PK fields, with a space */
+ if(!sldns_affix_token(strbuf, token,
+ &token_len, "ed, &parens,
+ &pre_data_pos, delimiters,
+ rdftype, &token_strlen))
+ break;
+ if(!sldns_affix_token(strbuf, token,
+ &token_len, "ed, &parens,
+ &pre_data_pos, delimiters,
+ rdftype, &token_strlen))
+ break;
+ }
+
+ /* normal RR */
+ if((status=rrinternal_parse_rdf(strbuf, token,
+ token_len, rr, *rr_len, &rr_cur_len, rdftype,
+ rr_type, r_cnt, r_max, dname_len, origin,
+ origin_len)) != 0) {
+ return status;
+ }
+ }
+ }
+ if(!was_unknown_rr_format && r_cnt+1 < r_min) {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE,
+ sldns_buffer_position(strbuf));
+ }
+ while(parens != 0) {
+ /* read remainder, must be "" */
+ if(sldns_bget_token_par(strbuf, token, "\n", token_len,
+ &parens, " \t") == -1) {
+ if(parens != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS,
+ sldns_buffer_position(strbuf));
+ break;
+ }
+ if(strcmp(token, "") != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS,
+ sldns_buffer_position(strbuf));
+ }
+ /* write rdata length */
+ sldns_write_uint16(rr+dname_len+8, rr_cur_len-dname_len-10);
+ *rr_len = rr_cur_len;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/*
+ * trailing spaces are allowed
+ * leading spaces are not allowed
+ * allow ttl to be optional
+ * class is optional too
+ * if ttl is missing, and default_ttl is 0, use DEF_TTL
+ * allow ttl to be written as 1d3h
+ * So the RR should look like. e.g.
+ * miek.nl. 3600 IN MX 10 elektron.atoom.net
+ * or
+ * miek.nl. 1h IN MX 10 elektron.atoom.net
+ * or
+ * miek.nl. IN MX 10 elektron.atoom.net
+ */
+static int
+sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len,
+ size_t* dname_len, uint32_t default_ttl, uint8_t* origin,
+ size_t origin_len, uint8_t* prev, size_t prev_len, int question)
+{
+ int status;
+ int not_there = 0;
+ char token[LDNS_MAX_RDFLEN+1];
+ uint32_t ttl = 0;
+ uint16_t tp = 0, cl = 0;
+ size_t ddlen = 0;
+
+ /* string in buffer */
+ sldns_buffer strbuf;
+ sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str));
+ if(!dname_len) dname_len = &ddlen;
+
+ /* parse the owner */
+ if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin,
+ origin_len, prev, prev_len, token, sizeof(token))) != 0)
+ return status;
+
+ /* parse the [ttl] [class] <type> */
+ if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token),
+ ¬_there, &ttl, default_ttl)) != 0)
+ return status;
+ if((status=rrinternal_get_class(&strbuf, token, sizeof(token),
+ ¬_there, &cl)) != 0)
+ return status;
+ if((status=rrinternal_get_type(&strbuf, token, sizeof(token),
+ ¬_there, &tp)) != 0)
+ return status;
+ /* put ttl, class, type into the rr result */
+ if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl,
+ ttl, question)) != 0)
+ return status;
+ /* for a question-RR we are done, no rdata */
+ if(question) {
+ *len = *dname_len + 4;
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ /* rdata */
+ if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token),
+ rr, len, *dname_len, tp, origin, origin_len)) != 0)
+ return status;
+
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len,
+ size_t* dname_len, uint32_t default_ttl, uint8_t* origin,
+ size_t origin_len, uint8_t* prev, size_t prev_len)
+{
+ return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len,
+ default_ttl, origin, origin_len, prev, prev_len, 0);
+}
+
+int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len,
+ size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev,
+ size_t prev_len)
+{
+ return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len,
+ 0, origin, origin_len, prev, prev_len, 1);
+}
+
+uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len)
+{
+ if(len < dname_len+2)
+ return 0;
+ return sldns_read_uint16(rr+dname_len);
+}
+
+uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len)
+{
+ if(len < dname_len+4)
+ return 0;
+ return sldns_read_uint16(rr+dname_len+2);
+}
+
+uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len)
+{
+ if(len < dname_len+8)
+ return 0;
+ return sldns_read_uint32(rr+dname_len+4);
+}
+
+uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len)
+{
+ if(len < dname_len+10)
+ return 0;
+ return sldns_read_uint16(rr+dname_len+8);
+}
+
+uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len)
+{
+ if(len < dname_len+10)
+ return NULL;
+ return rr+dname_len+10;
+}
+
+uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len)
+{
+ if(len < dname_len+10)
+ return NULL;
+ return rr+dname_len+8;
+}
+
+const char* sldns_get_errorstr_parse(int e)
+{
+ sldns_lookup_table *lt;
+ lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e));
+ return lt?lt->name:"unknown error";
+}
+
+/* Strip whitespace from the start and the end of <line>. */
+static char *
+sldns_strip_ws(char *line)
+{
+ char *s = line, *e;
+
+ for (s = line; *s && isspace((unsigned char)*s); s++)
+ ;
+ for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--)
+ ;
+ *e = 0;
+ return s;
+}
+
+int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
+ struct sldns_file_parse_state* parse_state)
+{
+ char line[LDNS_RR_BUF_SIZE+1];
+ ssize_t size;
+
+ /* read an entire line in from the file */
+ if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE,
+ LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL))
+ == -1) {
+ /* if last line was empty, we are now at feof, which is not
+ * always a parse error (happens when for instance last line
+ * was a comment)
+ */
+ return LDNS_WIREPARSE_ERR_SYNTAX;
+ }
+
+ /* we can have the situation, where we've read ok, but still got
+ * no bytes to play with, in this case size is 0 */
+ if(size == 0) {
+ *len = 0;
+ *dname_len = 0;
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) {
+ int s;
+ *len = 0;
+ *dname_len = 0;
+ if(!parse_state) return LDNS_WIREPARSE_ERR_OK;
+ parse_state->origin_len = sizeof(parse_state->origin);
+ s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8),
+ parse_state->origin, &parse_state->origin_len);
+ if(s) parse_state->origin_len = 0;
+ return s;
+ } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) {
+ const char* end = NULL;
+ *len = 0;
+ *dname_len = 0;
+ if(!parse_state) return LDNS_WIREPARSE_ERR_OK;
+ parse_state->default_ttl = sldns_str2period(
+ sldns_strip_ws(line+5), &end);
+ } else if (strncmp(line, "$INCLUDE", 8) == 0) {
+ *len = 0;
+ *dname_len = 0;
+ return LDNS_WIREPARSE_ERR_INCLUDE;
+ } else {
+ return sldns_str2wire_rr_buf(line, rr, len, dname_len,
+ parse_state?parse_state->default_ttl:0,
+ (parse_state&&parse_state->origin_len)?
+ parse_state->origin:NULL,
+ parse_state->origin_len,
+ (parse_state&&parse_state->prev_rr_len)?
+ parse_state->prev_rr:NULL,
+ parse_state->prev_rr_len);
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
+ sldns_rdf_type rdftype)
+{
+ switch (rdftype) {
+ case LDNS_RDF_TYPE_DNAME:
+ return sldns_str2wire_dname_buf(str, rd, len);
+ case LDNS_RDF_TYPE_INT8:
+ return sldns_str2wire_int8_buf(str, rd, len);
+ case LDNS_RDF_TYPE_INT16:
+ return sldns_str2wire_int16_buf(str, rd, len);
+ case LDNS_RDF_TYPE_INT32:
+ return sldns_str2wire_int32_buf(str, rd, len);
+ case LDNS_RDF_TYPE_A:
+ return sldns_str2wire_a_buf(str, rd, len);
+ case LDNS_RDF_TYPE_AAAA:
+ return sldns_str2wire_aaaa_buf(str, rd, len);
+ case LDNS_RDF_TYPE_STR:
+ return sldns_str2wire_str_buf(str, rd, len);
+ case LDNS_RDF_TYPE_APL:
+ return sldns_str2wire_apl_buf(str, rd, len);
+ case LDNS_RDF_TYPE_B64:
+ return sldns_str2wire_b64_buf(str, rd, len);
+ case LDNS_RDF_TYPE_B32_EXT:
+ return sldns_str2wire_b32_ext_buf(str, rd, len);
+ case LDNS_RDF_TYPE_HEX:
+ return sldns_str2wire_hex_buf(str, rd, len);
+ case LDNS_RDF_TYPE_NSEC:
+ return sldns_str2wire_nsec_buf(str, rd, len);
+ case LDNS_RDF_TYPE_TYPE:
+ return sldns_str2wire_type_buf(str, rd, len);
+ case LDNS_RDF_TYPE_CLASS:
+ return sldns_str2wire_class_buf(str, rd, len);
+ case LDNS_RDF_TYPE_CERT_ALG:
+ return sldns_str2wire_cert_alg_buf(str, rd, len);
+ case LDNS_RDF_TYPE_ALG:
+ return sldns_str2wire_alg_buf(str, rd, len);
+ case LDNS_RDF_TYPE_TIME:
+ return sldns_str2wire_time_buf(str, rd, len);
+ case LDNS_RDF_TYPE_PERIOD:
+ return sldns_str2wire_period_buf(str, rd, len);
+ case LDNS_RDF_TYPE_LOC:
+ return sldns_str2wire_loc_buf(str, rd, len);
+ case LDNS_RDF_TYPE_WKS:
+ return sldns_str2wire_wks_buf(str, rd, len);
+ case LDNS_RDF_TYPE_NSAP:
+ return sldns_str2wire_nsap_buf(str, rd, len);
+ case LDNS_RDF_TYPE_ATMA:
+ return sldns_str2wire_atma_buf(str, rd, len);
+ case LDNS_RDF_TYPE_IPSECKEY:
+ return sldns_str2wire_ipseckey_buf(str, rd, len);
+ case LDNS_RDF_TYPE_NSEC3_SALT:
+ return sldns_str2wire_nsec3_salt_buf(str, rd, len);
+ case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
+ return sldns_str2wire_b32_ext_buf(str, rd, len);
+ case LDNS_RDF_TYPE_ILNP64:
+ return sldns_str2wire_ilnp64_buf(str, rd, len);
+ case LDNS_RDF_TYPE_EUI48:
+ return sldns_str2wire_eui48_buf(str, rd, len);
+ case LDNS_RDF_TYPE_EUI64:
+ return sldns_str2wire_eui64_buf(str, rd, len);
+ case LDNS_RDF_TYPE_TAG:
+ return sldns_str2wire_tag_buf(str, rd, len);
+ case LDNS_RDF_TYPE_LONG_STR:
+ return sldns_str2wire_long_str_buf(str, rd, len);
+ case LDNS_RDF_TYPE_HIP:
+ return sldns_str2wire_hip_buf(str, rd, len);
+ case LDNS_RDF_TYPE_INT16_DATA:
+ return sldns_str2wire_int16_data_buf(str, rd, len);
+ case LDNS_RDF_TYPE_UNKNOWN:
+ case LDNS_RDF_TYPE_SERVICE:
+ return LDNS_WIREPARSE_ERR_NOT_IMPL;
+ case LDNS_RDF_TYPE_NONE:
+ default:
+ break;
+ }
+ return LDNS_WIREPARSE_ERR_GENERAL;
+}
+
+int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ char* end;
+ uint8_t r = (uint8_t)strtol((char*)str, &end, 10);
+ if(*end != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str);
+ if(*len < 1)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ rd[0] = r;
+ *len = 1;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ char* end;
+ uint16_t r = (uint16_t)strtol((char*)str, &end, 10);
+ if(*end != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str);
+ if(*len < 2)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ sldns_write_uint16(rd, r);
+ *len = 2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ char* end;
+ uint32_t r;
+ errno = 0; /* must set to zero before call,
+ note race condition on errno */
+ if(*str == '-')
+ r = (uint32_t)strtol((char*)str, &end, 10);
+ else r = (uint32_t)strtoul((char*)str, &end, 10);
+ if(*end != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str);
+ if(errno == ERANGE)
+ return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW;
+ if(*len < 4)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ sldns_write_uint32(rd, r);
+ *len = 4;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ struct in_addr address;
+ if(inet_pton(AF_INET, (char*)str, &address) != 1)
+ return LDNS_WIREPARSE_ERR_SYNTAX_IP4;
+ if(*len < sizeof(address))
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ memmove(rd, &address, sizeof(address));
+ *len = sizeof(address);
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len)
+{
+#ifdef AF_INET6
+ uint8_t address[LDNS_IP6ADDRLEN + 1];
+ if(inet_pton(AF_INET6, (char*)str, address) != 1)
+ return LDNS_WIREPARSE_ERR_SYNTAX_IP6;
+ if(*len < LDNS_IP6ADDRLEN)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ memmove(rd, address, LDNS_IP6ADDRLEN);
+ *len = LDNS_IP6ADDRLEN;
+ return LDNS_WIREPARSE_ERR_OK;
+#else
+ return LDNS_WIREPARSE_ERR_NOT_IMPL;
+#endif
+}
+
+int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ uint8_t ch = 0;
+ size_t sl = 0;
+ const char* s = str;
+ /* skip length byte */
+ if(*len < 1)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+
+ /* read characters */
+ while(sldns_parse_char(&ch, &s)) {
+ if(sl >= 255)
+ return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str);
+ if(*len < sl+1)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ s-str);
+ rd[++sl] = ch;
+ }
+ if(!s)
+ return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE;
+ rd[0] = (uint8_t)sl;
+ *len = sl+1;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ const char *my_str = str;
+
+ char my_ip_str[64];
+ size_t ip_str_len;
+
+ uint16_t family;
+ int negation;
+ size_t adflength = 0;
+ uint8_t data[16+4];
+ uint8_t prefix;
+ size_t i;
+
+ if(strlen(my_str) == 0) {
+ /* empty APL element, no data, no string */
+ *len = 0;
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ /* [!]afi:address/prefix */
+ if (strlen(my_str) < 2
+ || strchr(my_str, ':') == NULL
+ || strchr(my_str, '/') == NULL
+ || strchr(my_str, ':') > strchr(my_str, '/')) {
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ if (my_str[0] == '!') {
+ negation = 1;
+ my_str += 1;
+ } else {
+ negation = 0;
+ }
+
+ family = (uint16_t) atoi(my_str);
+
+ my_str = strchr(my_str, ':') + 1;
+
+ /* need ip addr and only ip addr for inet_pton */
+ ip_str_len = (size_t) (strchr(my_str, '/') - my_str);
+ if(ip_str_len+1 > sizeof(my_ip_str))
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str));
+ my_ip_str[ip_str_len] = 0;
+
+ if (family == 1) {
+ /* ipv4 */
+ if(inet_pton(AF_INET, my_ip_str, data+4) == 0)
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ for (i = 0; i < 4; i++) {
+ if (data[i+4] != 0) {
+ adflength = i + 1;
+ }
+ }
+ } else if (family == 2) {
+ /* ipv6 */
+ if (inet_pton(AF_INET6, my_ip_str, data+4) == 0)
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ for (i = 0; i < 16; i++) {
+ if (data[i+4] != 0) {
+ adflength = i + 1;
+ }
+ }
+ } else {
+ /* unknown family */
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ my_str = strchr(my_str, '/') + 1;
+ prefix = (uint8_t) atoi(my_str);
+
+ sldns_write_uint16(data, family);
+ data[2] = prefix;
+ data[3] = (uint8_t)adflength;
+ if (negation) {
+ /* set bit 1 of byte 3 */
+ data[3] = data[3] | 0x80;
+ }
+
+ if(*len < 4+adflength)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ memmove(rd, data, 4+adflength);
+ *len = 4+adflength;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ size_t sz = sldns_b64_pton_calculate_size(strlen(str));
+ int n;
+ if(*len < sz)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ n = sldns_b64_pton(str, rd, *len);
+ if(n < 0)
+ return LDNS_WIREPARSE_ERR_SYNTAX_B64;
+ *len = (size_t)n;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ size_t slen = strlen(str);
+ size_t sz = sldns_b32_pton_calculate_size(slen);
+ int n;
+ if(*len < 1+sz)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ rd[0] = (uint8_t)sz;
+ n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1);
+ if(n < 0)
+ return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT;
+ *len = (size_t)n+1;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ const char* s = str;
+ size_t dlen = 0; /* number of hexdigits parsed */
+ while(*s) {
+ if(isspace((unsigned char)*s)) {
+ s++;
+ continue;
+ }
+ if(!isxdigit((unsigned char)*s))
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
+ if(*len < dlen/2 + 1)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ s-str);
+ if((dlen&1)==0)
+ rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
+ else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++);
+ dlen++;
+ }
+ if((dlen&1)!=0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
+ *len = dlen/2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ const char *delim = "\n\t ";
+ char token[64]; /* for a type name */
+ size_t type_count = 0;
+ int block;
+ size_t used = 0;
+ uint16_t maxtype = 0;
+ uint8_t typebits[8192]; /* 65536 bits */
+ uint8_t window_in_use[256];
+
+ /* string in buffer */
+ sldns_buffer strbuf;
+ sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str));
+
+ /* parse the types */
+ memset(typebits, 0, sizeof(typebits));
+ memset(window_in_use, 0, sizeof(window_in_use));
+ while(sldns_buffer_remaining(&strbuf) > 0 &&
+ sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) {
+ uint16_t t = sldns_get_rr_type_by_name(token);
+ if(token[0] == 0)
+ continue;
+ if(t == 0 && strcmp(token, "TYPE0") != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE,
+ sldns_buffer_position(&strbuf));
+ typebits[t/8] |= (0x80>>(t%8));
+ window_in_use[t/256] = 1;
+ type_count++;
+ if(t > maxtype) maxtype = t;
+ }
+
+ /* empty NSEC bitmap */
+ if(type_count == 0) {
+ *len = 0;
+ return LDNS_WIREPARSE_ERR_OK;
+ }
+
+ /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap},
+ * block is 0-255 upper octet of types, length if 0-32. */
+ for(block = 0; block <= (int)maxtype/256; block++) {
+ int i, blocklen = 0;
+ if(!window_in_use[block])
+ continue;
+ for(i=0; i<32; i++) {
+ if(typebits[block*32+i] != 0)
+ blocklen = i+1;
+ }
+ if(blocklen == 0)
+ continue; /* empty window should have been !in_use */
+ if(used+blocklen+2 > *len)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ rd[used+0] = (uint8_t)block;
+ rd[used+1] = (uint8_t)blocklen;
+ for(i=0; i<blocklen; i++) {
+ rd[used+2+i] = typebits[block*32+i];
+ }
+ used += blocklen+2;
+ }
+ *len = used;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ uint16_t t = sldns_get_rr_type_by_name(str);
+ if(t == 0 && strcmp(str, "TYPE0") != 0)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TYPE;
+ if(*len < 2)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ sldns_write_uint16(rd, t);
+ *len = 2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ uint16_t c = sldns_get_rr_class_by_name(str);
+ if(c == 0 && strcmp(str, "CLASS0") != 0)
+ return LDNS_WIREPARSE_ERR_SYNTAX_CLASS;
+ if(*len < 2)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ sldns_write_uint16(rd, c);
+ *len = 2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/* An certificate alg field can either be specified as a 8 bits number
+ * or by its symbolic name. Handle both */
+int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ sldns_lookup_table *lt = sldns_lookup_by_name(sldns_cert_algorithms,
+ str);
+ if(*len < 2)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ if(lt) {
+ sldns_write_uint16(rd, (uint16_t)lt->id);
+ } else {
+ int s = sldns_str2wire_int16_buf(str, rd, len);
+ if(s) return s;
+ if(sldns_read_uint16(rd) == 0)
+ return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM;
+ }
+ *len = 2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/* An alg field can either be specified as a 8 bits number
+ * or by its symbolic name. Handle both */
+int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str);
+ if(*len < 1)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ if(lt) {
+ rd[0] = (uint8_t)lt->id;
+ *len = 1;
+ } else {
+ /* try as-is (a number) */
+ return sldns_str2wire_int8_buf(str, rd, len);
+ }
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ /* convert a time YYYYDDMMHHMMSS to wireformat */
+ struct tm tm;
+ if(*len < 4)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+
+ /* Try to scan the time... */
+ memset(&tm, 0, sizeof(tm));
+ if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
+ &tm.tm_min, &tm.tm_sec) == 6) {
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+ /* Check values */
+ if (tm.tm_year < 70)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TIME;
+ if (tm.tm_mon < 0 || tm.tm_mon > 11)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TIME;
+ if (tm.tm_mday < 1 || tm.tm_mday > 31)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TIME;
+ if (tm.tm_hour < 0 || tm.tm_hour > 23)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TIME;
+ if (tm.tm_min < 0 || tm.tm_min > 59)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TIME;
+ if (tm.tm_sec < 0 || tm.tm_sec > 59)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TIME;
+
+ sldns_write_uint32(rd, sldns_mktime_from_utc(&tm));
+ } else {
+ /* handle it as 32 bits timestamp */
+ char *end;
+ uint32_t l = (uint32_t)strtol((char*)str, &end, 10);
+ if(*end != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME,
+ end-(char*)str);
+ sldns_write_uint32(rd, l);
+ }
+ *len = 4;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ const char* end;
+ uint32_t p = sldns_str2period(str, &end);
+ if(*end != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str);
+ if(*len < 4)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ sldns_write_uint32(rd, p);
+ *len = 4;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+/** read "<digits>[.<digits>][mM]" into mantissa exponent format for LOC type */
+static int
+loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e)
+{
+ uint32_t meters = 0, cm = 0, val;
+ while (isblank((unsigned char)*my_str)) {
+ my_str++;
+ }
+ meters = (uint32_t)strtol(my_str, &my_str, 10);
+ if (*my_str == '.') {
+ my_str++;
+ cm = (uint32_t)strtol(my_str, &my_str, 10);
+ }
+ if (meters >= 1) {
+ *e = 2;
+ val = meters;
+ } else {
+ *e = 0;
+ val = cm;
+ }
+ while(val >= 10) {
+ (*e)++;
+ val /= 10;
+ }
+ *m = (uint8_t)val;
+
+ if (*e > 9)
+ return 0;
+ if (*my_str == 'm' || *my_str == 'M') {
+ my_str++;
+ }
+ *endstr = my_str;
+ return 1;
+}
+
+int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ uint32_t latitude = 0;
+ uint32_t longitude = 0;
+ uint32_t altitude = 0;
+
+ uint32_t equator = (uint32_t)1<<31; /* 2**31 */
+
+ /* only support version 0 */
+ uint32_t h = 0;
+ uint32_t m = 0;
+ uint8_t size_b = 1, size_e = 2;
+ uint8_t horiz_pre_b = 1, horiz_pre_e = 6;
+ uint8_t vert_pre_b = 1, vert_pre_e = 3;
+
+ double s = 0.0;
+ int northerness;
+ int easterness;
+
+ char *my_str = (char *) str;
+
+ if (isdigit((unsigned char) *my_str)) {
+ h = (uint32_t) strtol(my_str, &my_str, 10);
+ } else {
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ while (isblank((unsigned char) *my_str)) {
+ my_str++;
+ }
+
+ if (isdigit((unsigned char) *my_str)) {
+ m = (uint32_t) strtol(my_str, &my_str, 10);
+ } else if (*my_str == 'N' || *my_str == 'S') {
+ goto north;
+ } else {
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ while (isblank((unsigned char) *my_str)) {
+ my_str++;
+ }
+
+ if (isdigit((unsigned char) *my_str)) {
+ s = strtod(my_str, &my_str);
+ }
+
+ /* skip blanks before norterness */
+ while (isblank((unsigned char) *my_str)) {
+ my_str++;
+ }
+
+north:
+ if (*my_str == 'N') {
+ northerness = 1;
+ } else if (*my_str == 'S') {
+ northerness = 0;
+ } else {
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ my_str++;
+
+ /* store number */
+ s = 1000.0 * s;
+ /* add a little to make floor in conversion a round */
+ s += 0.0005;
+ latitude = (uint32_t) s;
+ latitude += 1000 * 60 * m;
+ latitude += 1000 * 60 * 60 * h;
+ if (northerness) {
+ latitude = equator + latitude;
+ } else {
+ latitude = equator - latitude;
+ }
+ while (isblank((unsigned char)*my_str)) {
+ my_str++;
+ }
+
+ if (isdigit((unsigned char) *my_str)) {
+ h = (uint32_t) strtol(my_str, &my_str, 10);
+ } else {
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ while (isblank((unsigned char) *my_str)) {
+ my_str++;
+ }
+
+ if (isdigit((unsigned char) *my_str)) {
+ m = (uint32_t) strtol(my_str, &my_str, 10);
+ } else if (*my_str == 'E' || *my_str == 'W') {
+ goto east;
+ } else {
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ while (isblank((unsigned char)*my_str)) {
+ my_str++;
+ }
+
+ if (isdigit((unsigned char) *my_str)) {
+ s = strtod(my_str, &my_str);
+ }
+
+ /* skip blanks before easterness */
+ while (isblank((unsigned char)*my_str)) {
+ my_str++;
+ }
+
+east:
+ if (*my_str == 'E') {
+ easterness = 1;
+ } else if (*my_str == 'W') {
+ easterness = 0;
+ } else {
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ my_str++;
+
+ /* store number */
+ s *= 1000.0;
+ /* add a little to make floor in conversion a round */
+ s += 0.0005;
+ longitude = (uint32_t) s;
+ longitude += 1000 * 60 * m;
+ longitude += 1000 * 60 * 60 * h;
+
+ if (easterness) {
+ longitude += equator;
+ } else {
+ longitude = equator - longitude;
+ }
+
+ altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
+ 10000000.0 + 0.5);
+ if (*my_str == 'm' || *my_str == 'M') {
+ my_str++;
+ }
+
+ if (strlen(my_str) > 0) {
+ if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e))
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ if (strlen(my_str) > 0) {
+ if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e))
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ if (strlen(my_str) > 0) {
+ if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e))
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ }
+
+ if(*len < 16)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ rd[0] = 0;
+ rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f);
+ rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f);
+ rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f);
+ sldns_write_uint32(rd + 4, latitude);
+ sldns_write_uint32(rd + 8, longitude);
+ sldns_write_uint32(rd + 12, altitude);
+ *len = 16;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+static void
+ldns_tolower_str(char* s)
+{
+ if(s) {
+ while(*s) {
+ *s = (char)tolower((unsigned char)*s);
+ s++;
+ }
+ }
+}
+
+int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ int rd_len = 1;
+ int have_proto = 0;
+ char token[50], proto_str[50];
+ sldns_buffer strbuf;
+ sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str));
+ proto_str[0]=0;
+
+ /* check we have one byte for proto */
+ if(*len < 1)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+
+ while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) {
+ ldns_tolower_str(token);
+ if(!have_proto) {
+ struct protoent *p = getprotobyname(token);
+ have_proto = 1;
+ if(p) rd[0] = (uint8_t)p->p_proto;
+ else rd[0] = (uint8_t)atoi(token);
+ (void)strlcpy(proto_str, token, sizeof(proto_str));
+ } else {
+ int serv_port;
+ struct servent *serv = getservbyname(token, proto_str);
+ if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port);
+ else {
+ serv_port = atoi(token);
+ if(serv_port == 0 && strcmp(token, "0") != 0) {
+#ifdef HAVE_ENDSERVENT
+ endservent();
+#endif
+#ifdef HAVE_ENDPROTOENT
+ endprotoent();
+#endif
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
+ sldns_buffer_position(&strbuf));
+ }
+ if(serv_port < 0 || serv_port > 65535) {
+#ifdef HAVE_ENDSERVENT
+ endservent();
+#endif
+#ifdef HAVE_ENDPROTOENT
+ endprotoent();
+#endif
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
+ sldns_buffer_position(&strbuf));
+ }
+ }
+ if(rd_len < 1+serv_port/8+1) {
+ /* bitmap is larger, init new bytes at 0 */
+ if(*len < 1+(size_t)serv_port/8+1) {
+#ifdef HAVE_ENDSERVENT
+ endservent();
+#endif
+#ifdef HAVE_ENDPROTOENT
+ endprotoent();
+#endif
+ return RET_ERR(
+ LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(&strbuf));
+ }
+ memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len);
+ rd_len = 1+serv_port/8+1;
+ }
+ rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8));
+ }
+ }
+ *len = (size_t)rd_len;
+
+#ifdef HAVE_ENDSERVENT
+ endservent();
+#endif
+#ifdef HAVE_ENDPROTOENT
+ endprotoent();
+#endif
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ const char* s = str;
+ size_t slen;
+ size_t dlen = 0; /* number of hexdigits parsed */
+
+ /* just a hex string with optional dots? */
+ if (s[0] != '0' || s[1] != 'x')
+ return LDNS_WIREPARSE_ERR_INVALID_STR;
+ s += 2;
+ slen = strlen(s);
+ if(slen > LDNS_MAX_RDFLEN*2)
+ return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW;
+ while(*s) {
+ if(isspace((unsigned char)*s) || *s == '.') {
+ s++;
+ continue;
+ }
+ if(!isxdigit((unsigned char)*s))
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
+ if(*len < dlen/2 + 1)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ s-str);
+ if((dlen&1)==0)
+ rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
+ else rd[dlen/2] += sldns_hexdigit_to_int(*s++);
+ dlen++;
+ }
+ if((dlen&1)!=0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
+ *len = dlen/2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ const char* s = str;
+ size_t slen = strlen(str);
+ size_t dlen = 0; /* number of hexdigits parsed */
+
+ /* just a hex string with optional dots? */
+ /* notimpl e.164 format */
+ if(slen > LDNS_MAX_RDFLEN*2)
+ return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW;
+ while(*s) {
+ if(isspace((unsigned char)*s) || *s == '.') {
+ s++;
+ continue;
+ }
+ if(!isxdigit((unsigned char)*s))
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
+ if(*len < dlen/2 + 1)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ s-str);
+ if((dlen&1)==0)
+ rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
+ else rd[dlen/2] += sldns_hexdigit_to_int(*s++);
+ dlen++;
+ }
+ if((dlen&1)!=0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
+ *len = dlen/2;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ size_t gwlen = 0, keylen = 0;
+ int s;
+ uint8_t gwtype;
+ char token[512];
+ sldns_buffer strbuf;
+ sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str));
+
+ if(*len < 3)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ /* precedence */
+ if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR,
+ sldns_buffer_position(&strbuf));
+ rd[0] = (uint8_t)atoi(token);
+ /* gateway_type */
+ if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR,
+ sldns_buffer_position(&strbuf));
+ rd[1] = (uint8_t)atoi(token);
+ gwtype = rd[1];
+ /* algorithm */
+ if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR,
+ sldns_buffer_position(&strbuf));
+ rd[2] = (uint8_t)atoi(token);
+
+ /* gateway */
+ if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR,
+ sldns_buffer_position(&strbuf));
+ if(gwtype == 0) {
+ /* NOGATEWAY */
+ if(strcmp(token, ".") != 0)
+ return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR,
+ sldns_buffer_position(&strbuf));
+ gwlen = 0;
+ } else if(gwtype == 1) {
+ /* IP4 */
+ gwlen = *len - 3;
+ s = sldns_str2wire_a_buf(token, rd+3, &gwlen);
+ if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf));
+ } else if(gwtype == 2) {
+ /* IP6 */
+ gwlen = *len - 3;
+ s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen);
+ if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf));
+ } else if(gwtype == 3) {
+ /* DNAME */
+ gwlen = *len - 3;
+ s = sldns_str2wire_dname_buf(token, rd+3, &gwlen);
+ if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf));
+ } else {
+ /* unknown gateway type */
+ return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR,
+ sldns_buffer_position(&strbuf));
+ }
+ /* double check for size */
+ if(*len < 3 + gwlen)
+ return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
+ sldns_buffer_position(&strbuf));
+
+ /* publickey in remainder of strbuf */
+ keylen = *len - 3 - gwlen;
+ s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf),
+ rd+3+gwlen, &keylen);
+ if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf));
+
+ *len = 3 + gwlen + keylen;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ int i, salt_length_str = (int)strlen(str);
+ if (salt_length_str == 1 && str[0] == '-') {
+ salt_length_str = 0;
+ } else if (salt_length_str % 2 != 0) {
+ return LDNS_WIREPARSE_ERR_SYNTAX_HEX;
+ }
+ if (salt_length_str > 512)
+ return LDNS_WIREPARSE_ERR_SYNTAX_HEX;
+ if(*len < 1+(size_t)salt_length_str / 2)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ rd[0] = (uint8_t) (salt_length_str / 2);
+ for (i = 0; i < salt_length_str; i += 2) {
+ if (isxdigit((unsigned char)str[i]) &&
+ isxdigit((unsigned char)str[i+1])) {
+ rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16
+ + sldns_hexdigit_to_int(str[i+1]));
+ } else {
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i);
+ }
+ }
+ *len = 1 + (size_t)rd[0];
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ unsigned int a, b, c, d;
+ uint16_t shorts[4];
+ int l;
+ if(*len < sizeof(shorts))
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+
+ if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 ||
+ l != (int)strlen(str) || /* more data to read */
+ strpbrk(str, "+-") /* signed hexes */
+ )
+ return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64;
+ shorts[0] = htons(a);
+ shorts[1] = htons(b);
+ shorts[2] = htons(c);
+ shorts[3] = htons(d);
+ memmove(rd, &shorts, sizeof(shorts));
+ *len = sizeof(shorts);
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ unsigned int a, b, c, d, e, f;
+ int l;
+
+ if(*len < 6)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n",
+ &a, &b, &c, &d, &e, &f, &l) != 6 ||
+ l != (int)strlen(str))
+ return LDNS_WIREPARSE_ERR_SYNTAX_EUI48;
+ rd[0] = a;
+ rd[1] = b;
+ rd[2] = c;
+ rd[3] = d;
+ rd[4] = e;
+ rd[5] = f;
+ *len = 6;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ unsigned int a, b, c, d, e, f, g, h;
+ int l;
+
+ if(*len < 8)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n",
+ &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 ||
+ l != (int)strlen(str))
+ return LDNS_WIREPARSE_ERR_SYNTAX_EUI64;
+ rd[0] = a;
+ rd[1] = b;
+ rd[2] = c;
+ rd[3] = d;
+ rd[4] = e;
+ rd[5] = f;
+ rd[6] = g;
+ rd[7] = h;
+ *len = 8;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ size_t slen = strlen(str);
+ const char* ptr;
+
+ if (slen > 255)
+ return LDNS_WIREPARSE_ERR_SYNTAX_TAG;
+ if(*len < slen+1)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ for (ptr = str; *ptr; ptr++) {
+ if(!isalnum((unsigned char)*ptr))
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str);
+ }
+ rd[0] = slen;
+ memmove(rd+1, str, slen);
+ *len = slen+1;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ uint8_t ch = 0;
+ const char* pstr = str;
+ size_t length = 0;
+
+ /* Fill data with parsed bytes */
+ while (sldns_parse_char(&ch, &pstr)) {
+ if(*len < length+1)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ rd[length++] = ch;
+ }
+ if(!pstr)
+ return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE;
+ *len = length;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ char* s, *end;
+ int e;
+ size_t hitlen, pklen = 0;
+ /* presentation format:
+ * pk-algo HIThex pubkeybase64
+ * wireformat:
+ * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */
+ if(*len < 4)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+
+ /* read PK algorithm */
+ rd[1] = (uint8_t)strtol((char*)str, &s, 10);
+ if(*s != ' ')
+ return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str);
+ s++;
+ while(*s == ' ')
+ s++;
+
+ /* read HIT hex tag */
+ /* zero terminate the tag (replace later) */
+ end = strchr(s, ' ');
+ if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str);
+ *end = 0;
+ hitlen = *len - 4;
+ if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) {
+ *end = ' ';
+ return RET_ERR_SHIFT(e, s-(char*)str);
+ }
+ if(hitlen > 255) {
+ *end = ' ';
+ return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2);
+ }
+ rd[0] = (uint8_t)hitlen;
+ *end = ' ';
+ s = end+1;
+
+ /* read pubkey base64 sequence */
+ pklen = *len - 4 - hitlen;
+ if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0)
+ 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);
+
+ *len = 4 + hitlen + pklen;
+ return LDNS_WIREPARSE_ERR_OK;
+}
+
+int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len)
+{
+ size_t sz = sldns_b64_pton_calculate_size(strlen(str));
+ int n;
+ if(*len < sz+2)
+ return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
+ if(sz > 65535)
+ return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW;
+ n = sldns_b64_pton(str, rd+2, (*len)-2);
+ if(n < 0)
+ return LDNS_WIREPARSE_ERR_SYNTAX_B64;
+ sldns_write_uint16(rd, (uint16_t)n);
+ *len = (size_t)n;
+ return LDNS_WIREPARSE_ERR_OK;
+}
--- /dev/null
+/**
+ * str2wire.h - read txt presentation of RRs
+ *
+ * (c) NLnet Labs, 2005-2006
+ *
+ * See the file LICENSE for the license
+ */
+
+/**
+ * \file
+ *
+ * Parses text to wireformat.
+ */
+
+#ifndef LDNS_STR2WIRE_H
+#define LDNS_STR2WIRE_H
+
+/* include rrdef for MAX_DOMAINLEN constant */
+#include <sldns/rrdef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct sldns_struct_lookup_table;
+
+/** buffer to read an RR, cannot be larger than 64K because of packet size */
+#define LDNS_RR_BUF_SIZE 65535 /* bytes */
+#define LDNS_DEFAULT_TTL 3600
+
+/*
+ * To convert class and type to string see
+ * sldns_get_rr_class_by_name(str)
+ * sldns_get_rr_type_by_name(str)
+ * from rrdef.h
+ */
+
+/**
+ * Convert text string into dname wireformat, mallocless, with user buffer.
+ * @param str: the text string with the domain name.
+ * @param buf: the result buffer, suggested size LDNS_MAX_DOMAINLEN+1
+ * @param len: length of the buffer on input, length of the result on output.
+ * @return 0 on success, otherwise an error.
+ */
+int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len);
+
+/**
+ * Same as sldns_str2wire_dname_buf, but concatenates origin if the domain
+ * name is relative (does not end in '.').
+ * @param str: the text string with the domain name.
+ * @param buf: the result buffer, suggested size LDNS_MAX_DOMAINLEN+1
+ * @param len: length of the buffer on input, length of the result on output.
+ * @param origin: the origin to append or NULL (nothing is appended).
+ * @param origin_len: length of origin.
+ * @return 0 on success, otherwise an error.
+ */
+int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len,
+ uint8_t* origin, size_t origin_len);
+
+/**
+ * Convert text string into dname wireformat
+ * @param str: the text string with the domain name.
+ * @param len: returned length of wireformat.
+ * @return wireformat dname (malloced) or NULL on failure.
+ */
+uint8_t* sldns_str2wire_dname(const char* str, size_t* len);
+
+/**
+ * Convert text RR to wireformat, with user buffer.
+ * @param str: the RR data in text presentation format.
+ * @param rr: the buffer where the result is stored into. This buffer has
+ * the wire-dname(uncompressed), type, class, ttl, rdatalen, rdata.
+ * These values are probably not aligned, and in network format.
+ * Use the sldns_wirerr_get_xxx functions to access them safely.
+ * buffer size LDNS_RR_BUF_SIZE is suggested.
+ * @param len: on input the length of the buffer, on output the amount of
+ * the buffer used for the rr.
+ * @param dname_len: if non-NULL, filled with the dname length as result.
+ * Because after the dname you find the type, class, ttl, rdatalen, rdata.
+ * @param default_ttl: TTL used if no TTL available.
+ * @param origin: used for origin dname (if not NULL)
+ * @param origin_len: length of origin.
+ * @param prev: used for prev_rr dname (if not NULL)
+ * @param prev_len: length of prev.
+ * @return 0 on success, an error on failure.
+ */
+int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len,
+ size_t* dname_len, uint32_t default_ttl, uint8_t* origin,
+ size_t origin_len, uint8_t* prev, size_t prev_len);
+
+/**
+ * Same as sldns_str2wire_rr_buf, but there is no rdata, it returns an RR
+ * with zero rdata and no ttl. It has name, type, class.
+ * You can access those with the sldns_wirerr_get_type and class functions.
+ * @param str: the RR data in text presentation format.
+ * @param rr: the buffer where the result is stored into.
+ * @param len: on input the length of the buffer, on output the amount of
+ * the buffer used for the rr.
+ * @param dname_len: if non-NULL, filled with the dname length as result.
+ * Because after the dname you find the type, class, ttl, rdatalen, rdata.
+ * @param origin: used for origin dname (if not NULL)
+ * @param origin_len: length of origin.
+ * @param prev: used for prev_rr dname (if not NULL)
+ * @param prev_len: length of prev.
+ * @return 0 on success, an error on failure.
+ */
+int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len,
+ size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev,
+ size_t prev_len);
+
+/**
+ * Get the type of the RR.
+ * @param rr: the RR in wire format.
+ * @param len: rr length.
+ * @param dname_len: dname length to skip.
+ * @return type in host byteorder
+ */
+uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len);
+
+/**
+ * Get the class of the RR.
+ * @param rr: the RR in wire format.
+ * @param len: rr length.
+ * @param dname_len: dname length to skip.
+ * @return class in host byteorder
+ */
+uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len);
+
+/**
+ * Get the ttl of the RR.
+ * @param rr: the RR in wire format.
+ * @param len: rr length.
+ * @param dname_len: dname length to skip.
+ * @return ttl in host byteorder
+ */
+uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len);
+
+/**
+ * Get the rdata length of the RR.
+ * @param rr: the RR in wire format.
+ * @param len: rr length.
+ * @param dname_len: dname length to skip.
+ * @return rdata length in host byteorder
+ * If the rdata length is larger than the rr-len allows, it is truncated.
+ * So, that it is safe to read the data length returned
+ * from this function from the rdata pointer of sldns_wirerr_get_rdata.
+ */
+uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len);
+
+/**
+ * Get the rdata pointer of the RR.
+ * @param rr: the RR in wire format.
+ * @param len: rr length.
+ * @param dname_len: dname length to skip.
+ * @return rdata pointer
+ */
+uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len);
+
+/**
+ * Get the rdata pointer of the RR. prefixed with rdata length.
+ * @param rr: the RR in wire format.
+ * @param len: rr length.
+ * @param dname_len: dname length to skip.
+ * @return pointer to rdatalength, followed by the rdata.
+ */
+uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len);
+
+/**
+ * Parse result codes
+ */
+#define LDNS_WIREPARSE_MASK 0x0fff
+#define LDNS_WIREPARSE_SHIFT 12
+#define LDNS_WIREPARSE_ERROR(e) ((e)&LDNS_WIREPARSE_MASK)
+#define LDNS_WIREPARSE_OFFSET(e) (((e)&~LDNS_WIREPARSE_MASK)>>LDNS_WIREPARSE_SHIFT)
+/* use lookuptable to get error string, sldns_wireparse_errors */
+#define LDNS_WIREPARSE_ERR_OK 0
+#define LDNS_WIREPARSE_ERR_GENERAL 342
+#define LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW 343
+#define LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW 344
+#define LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL 345
+#define LDNS_WIREPARSE_ERR_LABEL_OVERFLOW 346
+#define LDNS_WIREPARSE_ERR_EMPTY_LABEL 347
+#define LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE 348
+#define LDNS_WIREPARSE_ERR_SYNTAX 349
+#define LDNS_WIREPARSE_ERR_SYNTAX_TTL 350
+#define LDNS_WIREPARSE_ERR_SYNTAX_TYPE 351
+#define LDNS_WIREPARSE_ERR_SYNTAX_CLASS 352
+#define LDNS_WIREPARSE_ERR_SYNTAX_RDATA 353
+#define LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE 354
+#define LDNS_WIREPARSE_ERR_INVALID_STR 355
+#define LDNS_WIREPARSE_ERR_SYNTAX_B64 356
+#define LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT 357
+#define LDNS_WIREPARSE_ERR_SYNTAX_HEX 358
+#define LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM 359
+#define LDNS_WIREPARSE_ERR_SYNTAX_TIME 360
+#define LDNS_WIREPARSE_ERR_SYNTAX_PERIOD 361
+#define LDNS_WIREPARSE_ERR_SYNTAX_ILNP64 362
+#define LDNS_WIREPARSE_ERR_SYNTAX_EUI48 363
+#define LDNS_WIREPARSE_ERR_SYNTAX_EUI64 364
+#define LDNS_WIREPARSE_ERR_SYNTAX_TAG 365
+#define LDNS_WIREPARSE_ERR_NOT_IMPL 366
+#define LDNS_WIREPARSE_ERR_SYNTAX_INT 367
+#define LDNS_WIREPARSE_ERR_SYNTAX_IP4 368
+#define LDNS_WIREPARSE_ERR_SYNTAX_IP6 369
+#define LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW 370
+#define LDNS_WIREPARSE_ERR_INCLUDE 371
+#define LDNS_WIREPARSE_ERR_PARENTHESIS 372
+
+/**
+ * Get reference to a constant string for the (parse) error.
+ * @param e: error return value
+ * @return string.
+ */
+const char* sldns_get_errorstr_parse(int e);
+
+/**
+ * wire parse state for parsing files
+ */
+struct sldns_file_parse_state {
+ /** the origin domain name, if len!=0. uncompressed wireformat */
+ uint8_t origin[LDNS_MAX_DOMAINLEN+1];
+ /** length of origin domain name, in bytes. 0 if not set. */
+ size_t origin_len;
+ /** the previous domain name, if len!=0. uncompressed wireformat*/
+ uint8_t prev_rr[LDNS_MAX_DOMAINLEN+1];
+ /** length of the previous domain name, in bytes. 0 if not set. */
+ size_t prev_rr_len;
+ /** default TTL, this is used if the text does not specify a TTL,
+ * host byteorder */
+ uint32_t default_ttl;
+ /** line number information */
+ int lineno;
+};
+
+/**
+ * Read one RR from zonefile with buffer for the data.
+ * @param in: file that is read from (one RR, multiple lines if it spans them).
+ * @param rr: this is malloced by the user and the result is stored here,
+ * if an RR is read. If no RR is read this is signalled with the
+ * return len set to 0 (for ORIGIN, TTL directives).
+ * @param len: on input, the length of the rr buffer. on output the rr len.
+ * Buffer size of 64k should be enough.
+ * @param dname_len: returns the length of the dname initial part of the rr.
+ * @param parse_state: pass a pointer to user-allocated struct.
+ * Contents are maintained by this function.
+ * If you pass NULL then ORIGIN and TTL directives are not honored.
+ * You can start out with a particular origin by pre-filling it.
+ * otherwise, zero the structure before passing it.
+ * lineno is incremented when a newline is passed by the parser,
+ * you should initialize it at 1 at the start of the file.
+ * @return 0 on success, error on failure.
+ */
+int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
+ struct sldns_file_parse_state* parse_state);
+
+/**
+ * Convert one rdf in rdata to wireformat and parse from string.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @param rdftype: the type of the rdf.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
+ sldns_rdf_type rdftype);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_INT8 from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_INT16 from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_INT32 from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_A from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_AAAA from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_STR from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_APL from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_B64 from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_B32_EXT from string to wireformat.
+ * And also LDNS_RDF_TYPE_NSEC3_NEXT_OWNER.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_HEX from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_NSEC from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_TYPE from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_CLASS from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_CERT_ALG from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_ALG from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_TIME from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_PERIOD from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_LOC from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_WKS from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_NSAP from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_ATMA from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_IPSECKEY from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_NSEC3_SALT from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_ILNP64 from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_EUI48 from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_EUI64 from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_TAG from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_LONG_STR from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_HIP from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len);
+
+/**
+ * Convert rdf of type LDNS_RDF_TYPE_INT16_DATA from string to wireformat.
+ * @param str: the text to convert for this rdata element.
+ * @param rd: rdata buffer for the wireformat.
+ * @param len: length of rd buffer on input, used length on output.
+ * @return 0 on success, error on failure.
+ */
+int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_STR2WIRE_H */
--- /dev/null
+/*
+ * wire2str.c
+ *
+ * conversion routines from the wire format
+ * to the presentation format (strings)
+ *
+ * (c) NLnet Labs, 2004-2006
+ *
+ * See the file LICENSE for the license
+ */
+/**
+ * \file
+ *
+ * Contains functions to translate the wireformat to text
+ * representation, as well as functions to print them.
+ */
+#include "config.h"
+#include "sldns/wire2str.h"
+#include "sldns/str2wire.h"
+#include "sldns/rrdef.h"
+#include "sldns/pkthdr.h"
+#include "sldns/parseutil.h"
+#include "sldns/sbuffer.h"
+#include "sldns/keyraw.h"
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#include <sys/time.h>
+#include <stdarg.h>
+#include <ctype.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+/* lookup tables for standard DNS stuff */
+/* Taken from RFC 2535, section 7. */
+static sldns_lookup_table sldns_algorithms_data[] = {
+ { LDNS_RSAMD5, "RSAMD5" },
+ { LDNS_DH, "DH" },
+ { LDNS_DSA, "DSA" },
+ { LDNS_ECC, "ECC" },
+ { LDNS_RSASHA1, "RSASHA1" },
+ { LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
+ { LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
+ { LDNS_RSASHA256, "RSASHA256"},
+ { LDNS_RSASHA512, "RSASHA512"},
+ { LDNS_ECC_GOST, "ECC-GOST"},
+ { LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
+ { LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
+ { LDNS_INDIRECT, "INDIRECT" },
+ { LDNS_PRIVATEDNS, "PRIVATEDNS" },
+ { LDNS_PRIVATEOID, "PRIVATEOID" },
+ { 0, NULL }
+};
+sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
+
+/* hash algorithms in DS record */
+static sldns_lookup_table sldns_hashes_data[] = {
+ { LDNS_SHA1, "SHA1" },
+ { LDNS_SHA256, "SHA256" },
+ { LDNS_HASH_GOST, "HASH-GOST" },
+ { LDNS_SHA384, "SHA384" },
+ { 0, NULL }
+};
+sldns_lookup_table* sldns_hashes = sldns_hashes_data;
+
+/* Taken from RFC 4398 */
+static sldns_lookup_table sldns_cert_algorithms_data[] = {
+ { LDNS_CERT_PKIX, "PKIX" },
+ { LDNS_CERT_SPKI, "SPKI" },
+ { LDNS_CERT_PGP, "PGP" },
+ { LDNS_CERT_IPKIX, "IPKIX" },
+ { LDNS_CERT_ISPKI, "ISPKI" },
+ { LDNS_CERT_IPGP, "IPGP" },
+ { LDNS_CERT_ACPKIX, "ACPKIX" },
+ { LDNS_CERT_IACPKIX, "IACPKIX" },
+ { LDNS_CERT_URI, "URI" },
+ { LDNS_CERT_OID, "OID" },
+ { 0, NULL }
+};
+sldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data;
+
+/* if these are used elsewhere */
+static sldns_lookup_table sldns_rcodes_data[] = {
+ { LDNS_RCODE_NOERROR, "NOERROR" },
+ { LDNS_RCODE_FORMERR, "FORMERR" },
+ { LDNS_RCODE_SERVFAIL, "SERVFAIL" },
+ { LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
+ { LDNS_RCODE_NOTIMPL, "NOTIMPL" },
+ { LDNS_RCODE_REFUSED, "REFUSED" },
+ { LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
+ { LDNS_RCODE_YXRRSET, "YXRRSET" },
+ { LDNS_RCODE_NXRRSET, "NXRRSET" },
+ { LDNS_RCODE_NOTAUTH, "NOTAUTH" },
+ { LDNS_RCODE_NOTZONE, "NOTZONE" },
+ { 0, NULL }
+};
+sldns_lookup_table* sldns_rcodes = sldns_rcodes_data;
+
+static sldns_lookup_table sldns_opcodes_data[] = {
+ { LDNS_PACKET_QUERY, "QUERY" },
+ { LDNS_PACKET_IQUERY, "IQUERY" },
+ { LDNS_PACKET_STATUS, "STATUS" },
+ { LDNS_PACKET_NOTIFY, "NOTIFY" },
+ { LDNS_PACKET_UPDATE, "UPDATE" },
+ { 0, NULL }
+};
+sldns_lookup_table* sldns_opcodes = sldns_opcodes_data;
+
+static sldns_lookup_table sldns_wireparse_errors_data[] = {
+ { LDNS_WIREPARSE_ERR_OK, "no parse error" },
+ { LDNS_WIREPARSE_ERR_GENERAL, "parse error" },
+ { LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, "Domainname length overflow" },
+ { LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" },
+ { LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, "buffer too small" },
+ { LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, "Label length overflow" },
+ { LDNS_WIREPARSE_ERR_EMPTY_LABEL, "Empty label" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" },
+ { LDNS_WIREPARSE_ERR_SYNTAX, "Syntax error, could not parse the RR" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_TTL, "Syntax error, could not parse the RR's TTL" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_TYPE, "Syntax error, could not parse the RR's type" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_CLASS, "Syntax error, could not parse the RR's class" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_RDATA, "Syntax error, could not parse the RR's rdata" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, "Syntax error, value expected" },
+ { LDNS_WIREPARSE_ERR_INVALID_STR, "Conversion error, string expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_B64, "Conversion error, b64 encoding expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT, "Conversion error, b32 ext encoding expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_HEX, "Conversion error, hex encoding expected" },
+ { LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_TIME, "Conversion error, time encoding expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, "Conversion error, time period encoding expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_ILNP64, "Conversion error, 4 colon separated hex numbers expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_EUI48,
+ "Conversion error, 6 two character hex numbers "
+ "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_EUI64,
+ "Conversion error, 8 two character hex numbers "
+ "separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_TAG,
+ "Conversion error, a non-zero sequence of US-ASCII letters "
+ "and numbers in lower case expected" },
+ { LDNS_WIREPARSE_ERR_NOT_IMPL, "not implemented" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_INT, "Conversion error, integer expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_IP4, "Conversion error, ip4 addr expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_IP6, "Conversion error, ip6 addr expected" },
+ { LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer overflow" },
+ { LDNS_WIREPARSE_ERR_INCLUDE, "$INCLUDE directive was seen in the zone" },
+ { LDNS_WIREPARSE_ERR_PARENTHESIS, "Parse error, parenthesis mismatch" },
+ { 0, NULL }
+};
+sldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data;
+
+static sldns_lookup_table sldns_edns_flags_data[] = {
+ { 3600, "do"},
+ { 0, NULL}
+};
+sldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data;
+
+static sldns_lookup_table sldns_edns_options_data[] = {
+ { 1, "LLQ" },
+ { 2, "UL" },
+ { 3, "NSID" },
+ /* 4 draft-cheshire-edns0-owner-option */
+ { 5, "DAU" },
+ { 6, "DHU" },
+ { 7, "N3U" },
+ { 8, "edns-client-subnet" },
+ { 0, NULL}
+};
+sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
+
+char* sldns_wire2str_pkt(uint8_t* data, size_t len)
+{
+ size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0);
+ char* result = (char*)malloc(slen+1);
+ if(!result) return NULL;
+ sldns_wire2str_pkt_buf(data, len, result, slen+1);
+ return result;
+}
+
+char* sldns_wire2str_rr(uint8_t* rr, size_t len)
+{
+ size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0);
+ char* result = (char*)malloc(slen+1);
+ if(!result) return NULL;
+ sldns_wire2str_rr_buf(rr, len, result, slen+1);
+ return result;
+}
+
+char* sldns_wire2str_type(uint16_t rrtype)
+{
+ char buf[16];
+ sldns_wire2str_type_buf(rrtype, buf, sizeof(buf));
+ return strdup(buf);
+}
+
+char* sldns_wire2str_class(uint16_t rrclass)
+{
+ char buf[16];
+ sldns_wire2str_class_buf(rrclass, buf, sizeof(buf));
+ return strdup(buf);
+}
+
+char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len)
+{
+ size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0);
+ char* result = (char*)malloc(slen+1);
+ if(!result) return NULL;
+ sldns_wire2str_dname_buf(dname, dname_len, result, slen+1);
+ return result;
+}
+
+char* sldns_wire2str_rcode(int rcode)
+{
+ char buf[16];
+ sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf));
+ return strdup(buf);
+}
+
+int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen);
+}
+
+int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0);
+}
+
+int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
+ size_t str_len, uint16_t rrtype)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len,
+ rrtype, NULL, 0);
+}
+
+int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0);
+}
+
+int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len,
+ char* s, size_t slen)
+{
+ uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len);
+ return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len,
+ rrtype);
+}
+
+int sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_type_print(&s, &slen, rrtype);
+}
+
+int sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_class_print(&s, &slen, rrclass);
+}
+
+int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_rcode_print(&s, &slen, rcode);
+}
+
+int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0);
+}
+
+int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args)
+{
+ int w = vsnprintf(*str, *slen, format, args);
+ if(w < 0) {
+ /* error in printout */
+ return 0;
+ } else if((size_t)w >= *slen) {
+ *str = NULL; /* we do not want str to point outside of buffer*/
+ *slen = 0;
+ } else {
+ *str += w;
+ *slen -= w;
+ }
+ return w;
+}
+
+int sldns_str_print(char** str, size_t* slen, const char* format, ...)
+{
+ int w;
+ va_list args;
+ va_start(args, format);
+ w = sldns_str_vprint(str, slen, format, args);
+ va_end(args);
+ return w;
+}
+
+/** print hex format into text buffer for specified length */
+static int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len)
+{
+ const char* hex = "0123456789ABCDEF";
+ size_t i;
+ for(i=0; i<len; i++) {
+ (void)sldns_str_print(s, slen, "%c%c", hex[(buf[i]&0xf0)>>4],
+ hex[buf[i]&0x0f]);
+ }
+ return (int)len*2;
+}
+
+/** print remainder of buffer in hex format with prefixed text */
+static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen,
+ char** s, size_t* slen)
+{
+ int w = 0;
+ w += sldns_str_print(s, slen, "%s", pref);
+ w += print_hex_buf(s, slen, *d, *dlen);
+ *d += *dlen;
+ *dlen = 0;
+ return w;
+}
+
+int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
+{
+ int w = 0;
+ unsigned qdcount, ancount, nscount, arcount, i;
+ uint8_t* pkt = *d;
+ size_t pktlen = *dlen;
+ if(*dlen >= LDNS_HEADER_SIZE) {
+ qdcount = (unsigned)LDNS_QDCOUNT(*d);
+ ancount = (unsigned)LDNS_ANCOUNT(*d);
+ nscount = (unsigned)LDNS_NSCOUNT(*d);
+ arcount = (unsigned)LDNS_ARCOUNT(*d);
+ } else {
+ qdcount = ancount = nscount = arcount = 0;
+ }
+ w += sldns_wire2str_header_scan(d, dlen, s, slen);
+ w += sldns_str_print(s, slen, "\n");
+ w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n");
+ for(i=0; i<qdcount; i++) {
+ w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen,
+ pkt, pktlen);
+ if(!*dlen) break;
+ }
+ w += sldns_str_print(s, slen, "\n");
+ w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n");
+ for(i=0; i<ancount; i++) {
+ w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen);
+ if(!*dlen) break;
+ }
+ w += sldns_str_print(s, slen, "\n");
+ w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n");
+ for(i=0; i<nscount; i++) {
+ w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen);
+ if(!*dlen) break;
+ }
+ w += sldns_str_print(s, slen, "\n");
+ w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n");
+ for(i=0; i<arcount; i++) {
+ w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen);
+ if(!*dlen) break;
+ }
+ /* other fields: WHEN(time), SERVER(IP) not available here. */
+ w += sldns_str_print(s, slen, ";; MSG SIZE rcvd: %d\n", (int)pktlen);
+ if(*dlen > 0) {
+ w += print_remainder_hex(";; trailing garbage 0x",
+ d, dlen, s, slen);
+ w += sldns_str_print(s, slen, "\n");
+ }
+ return w;
+}
+
+/** scan type, class and ttl and printout, for rr */
+static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w = 0;
+ uint16_t t, c;
+ uint32_t ttl;
+ if(*dl < 8) {
+ if(*dl < 4)
+ return w + print_remainder_hex("; Error malformed 0x",
+ d, dl, s, sl);
+ /* these print values or 0x.. if none left */
+ t = sldns_read_uint16(*d);
+ c = sldns_read_uint16((*d)+2);
+ (*d)+=4;
+ (*dl)-=4;
+ w += sldns_wire2str_class_print(s, sl, c);
+ w += sldns_str_print(s, sl, "\t");
+ w += sldns_wire2str_type_print(s, sl, t);
+ if(*dl == 0)
+ return w + sldns_str_print(s, sl, "; Error no ttl");
+ return w + print_remainder_hex(
+ "; Error malformed ttl 0x", d, dl, s, sl);
+ }
+ t = sldns_read_uint16(*d);
+ c = sldns_read_uint16((*d)+2);
+ ttl = sldns_read_uint32((*d)+4);
+ (*d)+=8;
+ (*dl)-=8;
+ w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl);
+ w += sldns_wire2str_class_print(s, sl, c);
+ w += sldns_str_print(s, sl, "\t");
+ w += sldns_wire2str_type_print(s, sl, t);
+ return w;
+}
+
+int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
+ uint8_t* pkt, size_t pktlen)
+{
+ int w = 0;
+ uint8_t* rr = *d;
+ size_t rrlen = *dlen, dname_off, rdlen, ordlen;
+ uint16_t rrtype = 0;
+
+ if(*dlen >= 3 && (*d)[0]==0 &&
+ sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) {
+ /* perform EDNS OPT processing */
+ return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen);
+ }
+
+ /* try to scan the rdata with pretty-printing, but if that fails, then
+ * scan the rdata as an unknown RR type */
+ w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
+ w += sldns_str_print(s, slen, "\t");
+ dname_off = rrlen-(*dlen);
+ if(*dlen == 4) {
+ /* like a question-RR */
+ uint16_t t = sldns_read_uint16(*d);
+ uint16_t c = sldns_read_uint16((*d)+2);
+ (*d)+=4;
+ (*dlen)-=4;
+ w += sldns_wire2str_class_print(s, slen, c);
+ w += sldns_str_print(s, slen, "\t");
+ w += sldns_wire2str_type_print(s, slen, t);
+ w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n");
+ return w;
+ }
+ if(*dlen < 8) {
+ if(*dlen == 0)
+ return w + sldns_str_print(s, slen, ";Error missing RR\n");
+ w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen);
+ return w + sldns_str_print(s, slen, "\n");
+ }
+ rrtype = sldns_read_uint16(*d);
+ w += sldns_rr_tcttl_scan(d, dlen, s, slen);
+ w += sldns_str_print(s, slen, "\t");
+
+ /* rdata */
+ if(*dlen < 2) {
+ if(*dlen == 0)
+ return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
+ w += print_remainder_hex(";Error missing rdatalen 0x",
+ d, dlen, s, slen);
+ return w + sldns_str_print(s, slen, "\n");
+ }
+ rdlen = sldns_read_uint16(*d);
+ ordlen = rdlen;
+ (*d)+=2;
+ (*dlen)-=2;
+ if(*dlen < rdlen) {
+ w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
+ if(*dlen == 0)
+ return w + sldns_str_print(s, slen, ";Error missing rdata\n");
+ w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
+ return w + sldns_str_print(s, slen, "\n");
+ }
+ w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen);
+ (*dlen) -= (ordlen-rdlen);
+
+ /* default comment */
+ w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off,
+ rrtype);
+ w += sldns_str_print(s, slen, "\n");
+ return w;
+}
+
+int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s,
+ size_t* slen, uint8_t* pkt, size_t pktlen)
+{
+ int w = 0;
+ uint16_t t, c;
+ w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
+ w += sldns_str_print(s, slen, "\t");
+ if(*dlen < 4) {
+ if(*dlen == 0)
+ return w + sldns_str_print(s, slen, "Error malformed\n");
+ w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
+ return w + sldns_str_print(s, slen, "\n");
+ }
+ t = sldns_read_uint16(*d);
+ c = sldns_read_uint16((*d)+2);
+ (*d)+=4;
+ (*dlen)-=4;
+ w += sldns_wire2str_class_print(s, slen, c);
+ w += sldns_str_print(s, slen, "\t");
+ w += sldns_wire2str_type_print(s, slen, t);
+ w += sldns_str_print(s, slen, "\n");
+ return w;
+}
+
+int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s,
+ size_t* slen, uint8_t* pkt, size_t pktlen)
+{
+ size_t rdlen, ordlen;
+ int w = 0;
+ w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
+ w += sldns_str_print(s, slen, "\t");
+ w += sldns_rr_tcttl_scan(d, dlen, s, slen);
+ w += sldns_str_print(s, slen, "\t");
+ if(*dlen < 2) {
+ if(*dlen == 0)
+ return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
+ w += print_remainder_hex(";Error missing rdatalen 0x",
+ d, dlen, s, slen);
+ return w + sldns_str_print(s, slen, "\n");
+ }
+ rdlen = sldns_read_uint16(*d);
+ ordlen = rdlen;
+ (*d) += 2;
+ (*dlen) -= 2;
+ if(*dlen < rdlen) {
+ w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
+ if(*dlen == 0)
+ return w + sldns_str_print(s, slen, ";Error missing rdata\n");
+ w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
+ return w + sldns_str_print(s, slen, "\n");
+ }
+ w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen);
+ (*dlen) -= (ordlen-rdlen);
+ w += sldns_str_print(s, slen, "\n");
+ return w;
+}
+
+/** print rr comment for type DNSKEY */
+static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr,
+ size_t rrlen, size_t dname_off)
+{
+ size_t rdlen;
+ uint8_t* rdata;
+ int flags, w = 0;
+ if(rrlen < dname_off + 10) return 0;
+ rdlen = sldns_read_uint16(rr+dname_off+8);
+ if(rrlen < dname_off + 10 + rdlen) return 0;
+ rdata = rr + dname_off + 10;
+ flags = (int)sldns_read_uint16(rdata);
+ w += sldns_str_print(s, slen, " ;{");
+
+ /* id */
+ w += sldns_str_print(s, slen, "id = %u",
+ sldns_calc_keytag_raw(rdata, rdlen));
+
+ /* flags */
+ if((flags&LDNS_KEY_ZONE_KEY)) {
+ if((flags&LDNS_KEY_SEP_KEY))
+ w += sldns_str_print(s, slen, " (ksk)");
+ else w += sldns_str_print(s, slen, " (zsk)");
+ }
+
+ /* keysize */
+ if(rdlen > 4) {
+ w += sldns_str_print(s, slen, ", ");
+ w += sldns_str_print(s, slen, "size = %db",
+ (int)sldns_rr_dnskey_key_size_raw(
+ (unsigned char*)rdata+4, rdlen-4, (int)(rdata[3])));
+ }
+
+ w += sldns_str_print(s, slen, "}");
+ return w;
+}
+
+/** print rr comment for type RRSIG */
+static int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr,
+ size_t rrlen, size_t dname_off)
+{
+ size_t rdlen;
+ uint8_t* rdata;
+ if(rrlen < dname_off + 10) return 0;
+ rdlen = sldns_read_uint16(rr+dname_off+8);
+ if(rrlen < dname_off + 10 + rdlen) return 0;
+ rdata = rr + dname_off + 10;
+ if(rdlen < 18) return 0;
+ return sldns_str_print(s, slen, " ;{id = %d}",
+ (int)sldns_read_uint16(rdata+16));
+}
+
+/** print rr comment for type NSEC3 */
+static int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr,
+ size_t rrlen, size_t dname_off)
+{
+ size_t rdlen;
+ uint8_t* rdata;
+ int w = 0;
+ if(rrlen < dname_off + 10) return 0;
+ rdlen = sldns_read_uint16(rr+dname_off+8);
+ if(rrlen < dname_off + 10 + rdlen) return 0;
+ rdata = rr + dname_off + 10;
+ if(rdlen < 2) return 0;
+ if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK))
+ w += sldns_str_print(s, slen, " ;{flags: optout}");
+ return w;
+}
+
+int sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr,
+ size_t rrlen, size_t dname_off, uint16_t rrtype)
+{
+ if(rrtype == LDNS_RR_TYPE_DNSKEY) {
+ return rr_comment_dnskey(s, slen, rr, rrlen, dname_off);
+ } else if(rrtype == LDNS_RR_TYPE_RRSIG) {
+ return rr_comment_rrsig(s, slen, rr, rrlen, dname_off);
+ } else if(rrtype == LDNS_RR_TYPE_NSEC3) {
+ return rr_comment_nsec3(s, slen, rr, rrlen, dname_off);
+ }
+ return 0;
+}
+
+int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s,
+ size_t* slen)
+{
+ int w = 0;
+ int opcode, rcode;
+ w += sldns_str_print(s, slen, ";; ->>HEADER<<- ");
+ if(*dlen == 0)
+ return w+sldns_str_print(s, slen, "Error empty packet");
+ if(*dlen < 4)
+ return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
+ opcode = (int)LDNS_OPCODE_WIRE(*d);
+ rcode = (int)LDNS_RCODE_WIRE(*d);
+ w += sldns_str_print(s, slen, "opcode: ");
+ w += sldns_wire2str_opcode_print(s, slen, opcode);
+ w += sldns_str_print(s, slen, ", ");
+ w += sldns_str_print(s, slen, "rcode: ");
+ w += sldns_wire2str_rcode_print(s, slen, rcode);
+ w += sldns_str_print(s, slen, ", ");
+ w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d));
+ w += sldns_str_print(s, slen, ";; flags:");
+ if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr");
+ if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa");
+ if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc");
+ if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd");
+ if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd");
+ if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra");
+ if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad");
+ if(LDNS_Z_WIRE(*d)) w += sldns_str_print(s, slen, " z");
+ w += sldns_str_print(s, slen, " ; ");
+ if(*dlen < LDNS_HEADER_SIZE)
+ return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
+ w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d));
+ w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d));
+ w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d));
+ w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d));
+ *d += LDNS_HEADER_SIZE;
+ *dlen -= LDNS_HEADER_SIZE;
+ return w;
+}
+
+int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s,
+ size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen)
+{
+ /* try to prettyprint, but if that fails, use unknown format */
+ uint8_t* origd = *d;
+ char* origs = *s;
+ size_t origdlen = *dlen, origslen = *slen;
+ uint16_t r_cnt, r_max;
+ sldns_rdf_type rdftype;
+ int w = 0, n;
+
+ const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype);
+ if(!desc) /* unknown format */
+ return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen);
+ /* dlen equals the rdatalen for the rdata */
+
+ r_max = sldns_rr_descriptor_maximum(desc);
+ for(r_cnt=0; r_cnt < r_max; r_cnt++) {
+ if(*dlen == 0) {
+ if(r_cnt < sldns_rr_descriptor_minimum(desc))
+ goto failed;
+ break; /* nothing more to print */
+ }
+ rdftype = sldns_rr_descriptor_field_type(desc, r_cnt);
+ if(r_cnt != 0)
+ w += sldns_str_print(s, slen, " ");
+ n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype,
+ pkt, pktlen);
+ if(n == -1) {
+ failed:
+ /* failed, use unknown format */
+ *d = origd; *s = origs;
+ *dlen = origdlen; *slen = origslen;
+ return sldns_wire2str_rdata_unknown_scan(d, dlen,
+ s, slen);
+ }
+ w += n;
+ }
+ return w;
+}
+
+int sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s,
+ size_t* slen)
+{
+ int w = 0;
+
+ /* print length */
+ w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen);
+
+ /* print rdlen in hex */
+ if(*dlen != 0)
+ w += sldns_str_print(s, slen, " ");
+ w += print_hex_buf(s, slen, *d, *dlen);
+ (*d) += *dlen;
+ (*dlen) = 0;
+ return w;
+}
+
+/** print and escape one character for a domain dname */
+static int dname_char_print(char** s, size_t* slen, uint8_t c)
+{
+ if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\')
+ return sldns_str_print(s, slen, "\\%c", c);
+ else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c)))
+ return sldns_str_print(s, slen, "\\%03u", (unsigned)c);
+ /* plain printout */
+ if(*slen) {
+ **s = (char)c;
+ (*s)++;
+ (*slen)--;
+ }
+ return 1;
+}
+
+int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
+ uint8_t* pkt, size_t pktlen)
+{
+ int w = 0;
+ /* spool labels onto the string, use compression if its there */
+ uint8_t* pos = *d;
+ unsigned i, counter=0;
+ const unsigned maxcompr = 1000; /* loop detection, max compr ptrs */
+ int in_buf = 1;
+ if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname");
+ if(*pos == 0) {
+ (*d)++;
+ (*dlen)--;
+ return sldns_str_print(s, slen, ".");
+ }
+ while(*pos) {
+ /* read label length */
+ uint8_t labellen = *pos++;
+ if(in_buf) { (*d)++; (*dlen)--; }
+
+ /* find out what sort of label we have */
+ if((labellen&0xc0) == 0xc0) {
+ /* compressed */
+ uint16_t target = 0;
+ if(in_buf && *dlen == 0)
+ return w + sldns_str_print(s, slen,
+ "ErrorPartialDname");
+ else if(!in_buf && pos+1 > pkt+pktlen)
+ return w + sldns_str_print(s, slen,
+ "ErrorPartialDname");
+ target = ((labellen&0x3f)<<8) | *pos;
+ if(in_buf) { (*d)++; (*dlen)--; }
+ /* move to target, if possible */
+ if(!pkt || target >= pktlen)
+ return w + sldns_str_print(s, slen,
+ "ErrorComprPtrOutOfBounds");
+ if(counter++ > maxcompr)
+ return w + sldns_str_print(s, slen,
+ "ErrorComprPtrLooped");
+ in_buf = 0;
+ pos = pkt+target;
+ continue;
+ } else if((labellen&0xc0)) {
+ /* notimpl label type */
+ w += sldns_str_print(s, slen,
+ "ErrorLABELTYPE%xIsUnknown",
+ (int)(labellen&0xc0));
+ return w;
+ }
+
+ /* spool label characters, end with '.' */
+ if(in_buf && *dlen < labellen) labellen = *dlen;
+ else if(!in_buf && pos+labellen > pkt+pktlen)
+ labellen = (uint8_t)(pkt + pktlen - pos);
+ for(i=0; i<(unsigned)labellen; i++) {
+ w += dname_char_print(s, slen, *pos++);
+ }
+ if(in_buf) {
+ (*d) += labellen;
+ (*dlen) -= labellen;
+ if(*dlen == 0) break;
+ }
+ w += sldns_str_print(s, slen, ".");
+ }
+ /* skip over final root label */
+ if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; }
+ /* in case we printed no labels, terminate dname */
+ if(w == 0) w += sldns_str_print(s, slen, ".");
+ return w;
+}
+
+int sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode)
+{
+ sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode);
+ if (lt && lt->name) {
+ return sldns_str_print(s, slen, "%s", lt->name);
+ }
+ return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode);
+}
+
+int sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode)
+{
+ sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode);
+ if (lt && lt->name) {
+ return sldns_str_print(s, slen, "%s", lt->name);
+ }
+ return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode);
+}
+
+int sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass)
+{
+ sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes,
+ (int)rrclass);
+ if (lt && lt->name) {
+ return sldns_str_print(s, slen, "%s", lt->name);
+ }
+ return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass);
+}
+
+int sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype)
+{
+ const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype);
+ if (descriptor && descriptor->_name) {
+ return sldns_str_print(s, slen, "%s", descriptor->_name);
+ }
+ return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype);
+}
+
+int sldns_wire2str_edns_option_code_print(char** s, size_t* slen,
+ uint16_t opcode)
+{
+ sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options,
+ (int)opcode);
+ if (lt && lt->name) {
+ return sldns_str_print(s, slen, "%s", lt->name);
+ }
+ return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode);
+}
+
+int sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
+{
+ uint16_t c;
+ if(*dlen == 0) return 0;
+ if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
+ c = sldns_read_uint16(*d);
+ (*d)+=2;
+ (*dlen)-=2;
+ return sldns_wire2str_class_print(s, slen, c);
+}
+
+int sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
+{
+ uint16_t t;
+ if(*dlen == 0) return 0;
+ if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
+ t = sldns_read_uint16(*d);
+ (*d)+=2;
+ (*dlen)-=2;
+ return sldns_wire2str_type_print(s, slen, t);
+}
+
+int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
+{
+ uint32_t ttl;
+ if(*dlen == 0) return 0;
+ if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
+ ttl = sldns_read_uint32(*d);
+ (*d)+=4;
+ (*dlen)-=4;
+ return sldns_str_print(s, slen, "%u", (unsigned)ttl);
+}
+
+int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
+ int rdftype, uint8_t* pkt, size_t pktlen)
+{
+ if(*dlen == 0) return 0;
+ switch(rdftype) {
+ case LDNS_RDF_TYPE_NONE:
+ return 0;
+ case LDNS_RDF_TYPE_DNAME:
+ return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen);
+ case LDNS_RDF_TYPE_INT8:
+ return sldns_wire2str_int8_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_INT16:
+ return sldns_wire2str_int16_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_INT32:
+ return sldns_wire2str_int32_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_PERIOD:
+ return sldns_wire2str_period_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_TSIGTIME:
+ return sldns_wire2str_tsigtime_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_A:
+ return sldns_wire2str_a_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_AAAA:
+ return sldns_wire2str_aaaa_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_STR:
+ return sldns_wire2str_str_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_APL:
+ return sldns_wire2str_apl_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_B32_EXT:
+ return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_B64:
+ return sldns_wire2str_b64_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_HEX:
+ return sldns_wire2str_hex_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_NSEC:
+ return sldns_wire2str_nsec_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_NSEC3_SALT:
+ return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_TYPE:
+ return sldns_wire2str_type_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_CLASS:
+ return sldns_wire2str_class_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_CERT_ALG:
+ return sldns_wire2str_cert_alg_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_ALG:
+ return sldns_wire2str_alg_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_UNKNOWN:
+ return sldns_wire2str_unknown_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_TIME:
+ return sldns_wire2str_time_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_LOC:
+ return sldns_wire2str_loc_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_WKS:
+ case LDNS_RDF_TYPE_SERVICE:
+ return sldns_wire2str_wks_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_NSAP:
+ return sldns_wire2str_nsap_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_ATMA:
+ return sldns_wire2str_atma_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_IPSECKEY:
+ return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt,
+ pktlen);
+ case LDNS_RDF_TYPE_HIP:
+ return sldns_wire2str_hip_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_INT16_DATA:
+ return sldns_wire2str_int16_data_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
+ return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_ILNP64:
+ return sldns_wire2str_ilnp64_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_EUI48:
+ return sldns_wire2str_eui48_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_EUI64:
+ return sldns_wire2str_eui64_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_TAG:
+ return sldns_wire2str_tag_scan(d, dlen, s, slen);
+ case LDNS_RDF_TYPE_LONG_STR:
+ return sldns_wire2str_long_str_scan(d, dlen, s, slen);
+ }
+ /* unknown rdf type */
+ return -1;
+}
+
+int sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ if(*dl < 1) return -1;
+ w = sldns_str_print(s, sl, "%u", (unsigned)**d);
+ (*d)++;
+ (*dl)--;
+ return w;
+}
+
+int sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ if(*dl < 2) return -1;
+ w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d));
+ (*d)+=2;
+ (*dl)-=2;
+ return w;
+}
+
+int sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ if(*dl < 4) return -1;
+ w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d));
+ (*d)+=4;
+ (*dl)-=4;
+ return w;
+}
+
+int sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ if(*dl < 4) return -1;
+ w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d));
+ (*d)+=4;
+ (*dl)-=4;
+ return w;
+}
+
+int sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ /* tsigtime is 48 bits network order unsigned integer */
+ int w;
+ uint64_t tsigtime = 0;
+ uint64_t d0, d1, d2, d3, d4, d5;
+ if(*dl < 6) return -1;
+ d0 = (*d)[0]; /* cast to uint64 for shift operations */
+ d1 = (*d)[1];
+ d2 = (*d)[2];
+ d3 = (*d)[3];
+ d4 = (*d)[4];
+ d5 = (*d)[5];
+ tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
+#ifndef USE_WINSOCK
+ w = sldns_str_print(s, sl, "%llu", (long long)tsigtime);
+#else
+ w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime);
+#endif
+ (*d)+=6;
+ (*dl)-=6;
+ return w;
+}
+
+int sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ char buf[32];
+ int w;
+ if(*dl < 4) return -1;
+ if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf)))
+ return -1;
+ w = sldns_str_print(s, sl, "%s", buf);
+ (*d)+=4;
+ (*dl)-=4;
+ return w;
+}
+
+int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+#ifdef AF_INET6
+ char buf[64];
+ int w;
+ if(*dl < 16) return -1;
+ if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf)))
+ return -1;
+ w = sldns_str_print(s, sl, "%s", buf);
+ (*d)+=16;
+ (*dl)-=16;
+ return w;
+#else
+ return -1;
+#endif
+}
+
+/** printout escaped TYPE_STR character */
+static int str_char_print(char** s, size_t* sl, uint8_t c)
+{
+ if(isprint((unsigned char)c) || c == '\t') {
+ if(c == '\"' || c == '\\')
+ return sldns_str_print(s, sl, "\\%c", c);
+ if(*sl) {
+ **s = (char)c;
+ (*s)++;
+ (*sl)--;
+ }
+ return 1;
+ }
+ return sldns_str_print(s, sl, "\\%03u", (unsigned)c);
+}
+
+int sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w = 0;
+ size_t i, len;
+ if(*dl < 1) return -1;
+ len = **d;
+ if(*dl < 1+len) return -1;
+ (*d)++;
+ (*dl)--;
+ w += sldns_str_print(s, sl, "\"");
+ for(i=0; i<len; i++)
+ w += str_char_print(s, sl, (*d)[i]);
+ w += sldns_str_print(s, sl, "\"");
+ (*d)+=len;
+ (*dl)-=len;
+ return w;
+}
+
+int sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int i, w = 0;
+ uint16_t family;
+ uint8_t negation, prefix, adflength;
+ if(*dl < 4) return -1;
+ family = sldns_read_uint16(*d);
+ prefix = (*d)[2];
+ negation = ((*d)[3] & LDNS_APL_NEGATION);
+ adflength = ((*d)[3] & LDNS_APL_MASK);
+ if(*dl < 4+(size_t)adflength) return -1;
+ if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6)
+ return -1; /* unknown address family */
+ if(negation)
+ w += sldns_str_print(s, sl, "!");
+ w += sldns_str_print(s, sl, "%u:", (unsigned)family);
+ if(family == LDNS_APL_IP4) {
+ /* check if prefix <32 ? */
+ /* address is variable length 0 - 4 */
+ for(i=0; i<4; i++) {
+ if(i > 0)
+ w += sldns_str_print(s, sl, ".");
+ if(i < (int)adflength)
+ w += sldns_str_print(s, sl, "%d", (*d)[4+i]);
+ else w += sldns_str_print(s, sl, "0");
+ }
+ } else if(family == LDNS_APL_IP6) {
+ /* check if prefix <128 ? */
+ /* address is variable length 0 - 16 */
+ for(i=0; i<16; i++) {
+ if(i%2 == 0 && i>0)
+ w += sldns_str_print(s, sl, ":");
+ if(i < (int)adflength)
+ w += sldns_str_print(s, sl, "%02x", (*d)[4+i]);
+ else w += sldns_str_print(s, sl, "00");
+ }
+ }
+ w += sldns_str_print(s, sl, "/%u", (unsigned)prefix);
+ (*d) += 4+adflength;
+ (*dl) -= 4+adflength;
+ return w;
+}
+
+int sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ size_t datalen;
+ size_t sz;
+ if(*dl < 1) return -1;
+ datalen = (*d)[0];
+ if(*dl < 1+datalen) return -1;
+ sz = sldns_b32_ntop_calculate_size(datalen);
+ if(*sl < sz+1) {
+ (*d) += datalen+1;
+ (*dl) -= (datalen+1);
+ return (int)sz; /* out of space really, but would need buffer
+ in order to truncate the output */
+ }
+ sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl);
+ (*d) += datalen+1;
+ (*dl) -= (datalen+1);
+ (*s) += sz;
+ (*sl) -= sz;
+ return (int)sz;
+}
+
+/** scan number of bytes from wire into b64 presentation format */
+static int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s,
+ size_t* sl, size_t num)
+{
+ /* b64_ntop_calculate size includes null at the end */
+ size_t sz = sldns_b64_ntop_calculate_size(num)-1;
+ if(*sl < sz+1) {
+ (*d) += num;
+ (*dl) -= num;
+ return (int)sz; /* out of space really, but would need buffer
+ in order to truncate the output */
+ }
+ sldns_b64_ntop(*d, num, *s, *sl);
+ (*d) += num;
+ (*dl) -= num;
+ (*s) += sz;
+ (*sl) -= sz;
+ return (int)sz;
+}
+
+int sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
+}
+
+int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ return print_remainder_hex("", d, dl, s, sl);
+}
+
+int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ uint8_t* p = *d;
+ size_t pl = *dl;
+ unsigned i, bit, window, block_len;
+ uint16_t t;
+ int w = 0;
+
+ /* check for errors */
+ while(pl) {
+ if(pl < 2) return -1;
+ block_len = (unsigned)p[1];
+ if(pl < 2+block_len) return -1;
+ p += block_len+2;
+ pl -= block_len+2;
+ }
+
+ /* do it */
+ p = *d;
+ pl = *dl;
+ while(pl) {
+ if(pl < 2) return -1; /* cannot happen */
+ window = (unsigned)p[0];
+ block_len = (unsigned)p[1];
+ if(pl < 2+block_len) return -1; /* cannot happen */
+ p += 2;
+ for(i=0; i<block_len; i++) {
+ if(p[i] == 0) continue;
+ /* base type number for this octet */
+ t = ((window)<<8) | (i << 3);
+ for(bit=0; bit<8; bit++) {
+ if((p[i]&(0x80>>bit))) {
+ if(w) w += sldns_str_print(s, sl, " ");
+ w += sldns_wire2str_type_print(s, sl,
+ t+bit);
+ }
+ }
+ }
+ p += block_len;
+ pl -= block_len+2;
+ }
+ (*d) += *dl;
+ (*dl) = 0;
+ return w;
+}
+
+int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ size_t salt_len;
+ int w;
+ if(*dl < 1) return -1;
+ salt_len = (size_t)(*d)[0];
+ if(*dl < 1+salt_len) return -1;
+ (*d)++;
+ (*dl)--;
+ if(salt_len == 0) {
+ return sldns_str_print(s, sl, "-");
+ }
+ w = print_hex_buf(s, sl, *d, salt_len);
+ (*dl)-=salt_len;
+ (*d)+=salt_len;
+ return w;
+}
+
+int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ sldns_lookup_table *lt;
+ int data, w;
+ if(*dl < 2) return -1;
+ data = (int)sldns_read_uint16(*d);
+ lt = sldns_lookup_by_id(sldns_cert_algorithms, data);
+ if(lt && lt->name)
+ w = sldns_str_print(s, sl, "%s", lt->name);
+ else w = sldns_str_print(s, sl, "%d", data);
+ (*dl)-=2;
+ (*d)+=2;
+ return w;
+}
+
+int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ /* don't use algorithm mnemonics in the presentation format
+ * this kind of got sneaked into the rfc's */
+ return sldns_wire2str_int8_scan(d, dl, s, sl);
+}
+
+int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl);
+}
+
+int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ /* create a YYYYMMDDHHMMSS string if possible */
+ struct tm tm;
+ char date_buf[16];
+ uint32_t t;
+ memset(&tm, 0, sizeof(tm));
+ if(*dl < 4) return -1;
+ t = sldns_read_uint32(*d);
+ date_buf[15]=0;
+ if(sldns_serial_arithmitics_gmtime_r(t, time(NULL), &tm) &&
+ strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
+ (*d) += 4;
+ (*dl) -= 4;
+ return sldns_str_print(s, sl, "%s", date_buf);
+ }
+ return -1;
+}
+
+static int
+loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent)
+{
+ int w = 0;
+ uint8_t i;
+ /* is it 0.<two digits> ? */
+ if(exponent < 2) {
+ if(exponent == 1)
+ mantissa *= 10;
+ return sldns_str_print(str, sl, "0.%02ld", (long)mantissa);
+ }
+ /* always <digit><string of zeros> */
+ w += sldns_str_print(str, sl, "%d", (int)mantissa);
+ for(i=0; i<exponent-2; i++)
+ w += sldns_str_print(str, sl, "0");
+ return w;
+}
+
+int sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl)
+{
+ /* we could do checking (ie degrees < 90 etc)? */
+ uint8_t version;
+ uint8_t size;
+ uint8_t horizontal_precision;
+ uint8_t vertical_precision;
+ uint32_t longitude;
+ uint32_t latitude;
+ uint32_t altitude;
+ char northerness;
+ char easterness;
+ uint32_t h;
+ uint32_t m;
+ double s;
+ uint32_t equator = (uint32_t)1 << 31; /* 2**31 */
+ int w = 0;
+
+ if(*dl < 16) return -1;
+ version = (*d)[0];
+ if(version != 0)
+ return sldns_wire2str_hex_scan(d, dl, str, sl);
+ size = (*d)[1];
+ horizontal_precision = (*d)[2];
+ vertical_precision = (*d)[3];
+
+ latitude = sldns_read_uint32((*d)+4);
+ longitude = sldns_read_uint32((*d)+8);
+ altitude = sldns_read_uint32((*d)+12);
+
+ if (latitude > equator) {
+ northerness = 'N';
+ latitude = latitude - equator;
+ } else {
+ northerness = 'S';
+ latitude = equator - latitude;
+ }
+ h = latitude / (1000 * 60 * 60);
+ latitude = latitude % (1000 * 60 * 60);
+ m = latitude / (1000 * 60);
+ latitude = latitude % (1000 * 60);
+ s = (double) latitude / 1000.0;
+ w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
+ h, m, s, northerness);
+
+ if (longitude > equator) {
+ easterness = 'E';
+ longitude = longitude - equator;
+ } else {
+ easterness = 'W';
+ longitude = equator - longitude;
+ }
+ h = longitude / (1000 * 60 * 60);
+ longitude = longitude % (1000 * 60 * 60);
+ m = longitude / (1000 * 60);
+ longitude = longitude % (1000 * 60);
+ s = (double) longitude / (1000.0);
+ w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
+ h, m, s, easterness);
+
+ s = ((double) altitude) / 100;
+ s -= 100000;
+
+ if(altitude%100 != 0)
+ w += sldns_str_print(str, sl, "%.2f", s);
+ else
+ w += sldns_str_print(str, sl, "%.0f", s);
+
+ w += sldns_str_print(str, sl, "m ");
+
+ w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f);
+ w += sldns_str_print(str, sl, "m ");
+
+ w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4,
+ horizontal_precision & 0x0f);
+ w += sldns_str_print(str, sl, "m ");
+
+ w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4,
+ vertical_precision & 0x0f);
+ w += sldns_str_print(str, sl, "m");
+
+ (*d)+=16;
+ (*dl)-=16;
+ return w;
+}
+
+int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ /* protocol, followed by bitmap of services */
+ const char* proto_name = NULL;
+ struct protoent *protocol;
+ struct servent *service;
+ uint8_t protocol_nr;
+ int bit, port, w = 0;
+ size_t i;
+ /* we cannot print with strings because they
+ * are not portable, the presentation format may
+ * not be able to be read in on another computer. */
+ int print_symbols = 0;
+
+ /* protocol */
+ if(*dl < 1) return -1;
+ protocol_nr = (*d)[0];
+ (*d)++;
+ (*dl)--;
+ protocol = getprotobynumber((int)protocol_nr);
+ if(protocol && (protocol->p_name != NULL)) {
+ w += sldns_str_print(s, sl, "%s", protocol->p_name);
+ proto_name = protocol->p_name;
+ } else {
+ w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr);
+ }
+
+ for(i=0; i<*dl; i++) {
+ if((*d)[i] == 0)
+ continue;
+ for(bit=0; bit<8; bit++) {
+ if(!(((*d)[i])&(0x80>>bit)))
+ continue;
+ port = (int)i*8 + bit;
+
+ if(!print_symbols)
+ service = NULL;
+ else
+ service = getservbyport(
+ (int)htons((uint16_t)port), proto_name);
+ if(service && service->s_name)
+ w += sldns_str_print(s, sl, " %s",
+ service->s_name);
+ else w += sldns_str_print(s, sl, " %u",
+ (unsigned)port);
+ }
+ }
+
+#ifdef HAVE_ENDSERVENT
+ endservent();
+#endif
+#ifdef HAVE_ENDPROTOENT
+ endprotoent();
+#endif
+ (*d) += *dl;
+ (*dl) = 0;
+ return w;
+}
+
+int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ return print_remainder_hex("0x", d, dl, s, sl);
+}
+
+int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ return print_remainder_hex("", d, dl, s, sl);
+}
+
+/* internal scan routine that can modify arguments on failure */
+static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl,
+ char** s, size_t* sl, uint8_t* pkt, size_t pktlen)
+{
+ /* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/
+ uint8_t precedence, gateway_type, algorithm;
+ int w = 0;
+
+ if(*dl < 3) return -1;
+ precedence = (*d)[0];
+ gateway_type = (*d)[1];
+ algorithm = (*d)[2];
+ if(gateway_type > 3)
+ return -1; /* unknown */
+ (*d)+=3;
+ (*dl)-=3;
+ w += sldns_str_print(s, sl, "%d %d %d ",
+ (int)precedence, (int)gateway_type, (int)algorithm);
+
+ switch(gateway_type) {
+ case 0: /* no gateway */
+ w += sldns_str_print(s, sl, ".");
+ break;
+ case 1: /* ip4 */
+ w += sldns_wire2str_a_scan(d, dl, s, sl);
+ break;
+ case 2: /* ip6 */
+ w += sldns_wire2str_aaaa_scan(d, dl, s, sl);
+ break;
+ case 3: /* dname */
+ w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen);
+ break;
+ default: /* unknown */
+ return -1;
+ }
+
+ if(*dl < 1)
+ return -1;
+ w += sldns_str_print(s, sl, " ");
+ w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
+ return w;
+}
+
+int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl,
+ uint8_t* pkt, size_t pktlen)
+{
+ uint8_t* od = *d;
+ char* os = *s;
+ size_t odl = *dl, osl = *sl;
+ int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen);
+ if(w == -1) {
+ *d = od;
+ *s = os;
+ *dl = odl;
+ *sl = osl;
+ return -1;
+ }
+ return w;
+}
+
+int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ uint8_t algo, hitlen;
+ uint16_t pklen;
+
+ /* read lengths */
+ if(*dl < 4)
+ return -1;
+ hitlen = (*d)[0];
+ algo = (*d)[1];
+ pklen = sldns_read_uint16((*d)+2);
+ if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen)
+ return -1;
+
+ /* write: algo hit pubkey */
+ w = sldns_str_print(s, sl, "%u ", (unsigned)algo);
+ w += print_hex_buf(s, sl, (*d)+4, hitlen);
+ w += sldns_str_print(s, sl, " ");
+ (*d)+=4+hitlen;
+ (*dl)-= (4+hitlen);
+ w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen);
+ return w;
+}
+
+int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ uint16_t n;
+ if(*dl < 2)
+ return -1;
+ n = sldns_read_uint16(*d);
+ if(*dl < 2+(size_t)n)
+ return -1;
+ (*d)+=2;
+ (*dl)-=2;
+ return sldns_wire2str_b64_scan_num(d, dl, s, sl, n);
+}
+
+int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s,
+ size_t* sl)
+{
+ return sldns_wire2str_b32_ext_scan(d, dl, s, sl);
+}
+
+int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ if(*dl < 8)
+ return -1;
+ w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x",
+ sldns_read_uint16(*d), sldns_read_uint16((*d)+2),
+ sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6));
+ (*d)+=8;
+ (*dl)-=8;
+ return w;
+}
+
+int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ if(*dl < 6)
+ return -1;
+ w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
+ (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]);
+ (*d)+=6;
+ (*dl)-=6;
+ return w;
+}
+
+int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ int w;
+ if(*dl < 8)
+ return -1;
+ w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
+ (*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5],
+ (*d)[6], (*d)[7]);
+ (*d)+=8;
+ (*dl)-=8;
+ return w;
+}
+
+int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ size_t i, n;
+ int w = 0;
+ if(*dl < 1)
+ return -1;
+ n = (size_t)((*d)[0]);
+ if(*dl < 1+n)
+ return -1;
+ for(i=0; i<n; i++)
+ if(!isalnum((unsigned char)(*d)[i]))
+ return -1;
+ for(i=0; i<n; i++)
+ w += sldns_str_print(s, sl, "%c", (char)(*d)[i]);
+ (*d)+=n+1;
+ (*dl)-=(n+1);
+ return w;
+}
+
+int sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
+{
+ size_t i;
+ int w = 0;
+ w += sldns_str_print(s, sl, "\"");
+ for(i=0; i<*dl; i++)
+ w += str_char_print(s, sl, (*d)[i]);
+ w += sldns_str_print(s, sl, "\"");
+ (*d)+=*dl;
+ (*dl)=0;
+ return w;
+}
+
+int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
+ size_t len)
+{
+ /* LLQ constants */
+ const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC",
+ "FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"};
+ const unsigned int llq_errors_num = 7;
+ const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"};
+ const unsigned int llq_opcodes_num = 3;
+ uint16_t version, llq_opcode, error_code;
+ uint64_t llq_id;
+ uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */
+ int w = 0;
+
+ /* read the record */
+ if(len != 18) {
+ w += sldns_str_print(s, sl, "malformed LLQ ");
+ w += print_hex_buf(s, sl, data, len);
+ return w;
+ }
+ version = sldns_read_uint16(data);
+ llq_opcode = sldns_read_uint16(data+2);
+ error_code = sldns_read_uint16(data+4);
+ memmove(&llq_id, data+6, sizeof(llq_id));
+ lease_life = sldns_read_uint32(data+14);
+
+ /* print it */
+ w += sldns_str_print(s, sl, "v%d ", (int)version);
+ if(llq_opcode < llq_opcodes_num)
+ w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]);
+ else w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode);
+ if(error_code < llq_errors_num)
+ w += sldns_str_print(s, sl, " %s", llq_errors[error_code]);
+ else w += sldns_str_print(s, sl, " error %d", (int)error_code);
+#ifndef USE_WINSOCK
+ w += sldns_str_print(s, sl, " id %llx lease-life %lu",
+ (unsigned long long)llq_id, (unsigned long)lease_life);
+#else
+ w += sldns_str_print(s, sl, " id %I64x lease-life %lu",
+ (unsigned long long)llq_id, (unsigned long)lease_life);
+#endif
+ return w;
+}
+
+int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data,
+ size_t len)
+{
+ uint32_t lease;
+ int w = 0;
+ if(len != 4) {
+ w += sldns_str_print(s, sl, "malformed UL ");
+ w += print_hex_buf(s, sl, data, len);
+ return w;
+ }
+ lease = sldns_read_uint32(data);
+ w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease);
+ return w;
+}
+
+int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data,
+ size_t len)
+{
+ int w = 0;
+ size_t i, printed=0;
+ w += print_hex_buf(s, sl, data, len);
+ for(i=0; i<len; i++) {
+ if(isprint((unsigned char)data[i]) || data[i] == '\t') {
+ if(!printed) {
+ w += sldns_str_print(s, sl, " (");
+ printed = 1;
+ }
+ w += sldns_str_print(s, sl, "%c", (char)data[i]);
+ }
+ }
+ if(printed)
+ w += sldns_str_print(s, sl, ")");
+ return w;
+}
+
+int sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data,
+ size_t len)
+{
+ sldns_lookup_table *lt;
+ size_t i;
+ int w = 0;
+ for(i=0; i<len; i++) {
+ lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]);
+ if(lt && lt->name)
+ w += sldns_str_print(s, sl, " %s", lt->name);
+ else w += sldns_str_print(s, sl, " %d", (int)data[i]);
+ }
+ return w;
+}
+
+int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data,
+ size_t len)
+{
+ sldns_lookup_table *lt;
+ size_t i;
+ int w = 0;
+ for(i=0; i<len; i++) {
+ lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]);
+ if(lt && lt->name)
+ w += sldns_str_print(s, sl, " %s", lt->name);
+ else w += sldns_str_print(s, sl, " %d", (int)data[i]);
+ }
+ return w;
+}
+
+int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data,
+ size_t len)
+{
+ size_t i;
+ int w = 0;
+ for(i=0; i<len; i++) {
+ if(data[i] == 1)
+ w += sldns_str_print(s, sl, " SHA1");
+ else w += sldns_str_print(s, sl, " %d", (int)data[i]);
+ }
+ return w;
+}
+
+int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
+ size_t len)
+{
+ int w = 0;
+ uint16_t family;
+ uint8_t source, scope;
+ if(len < 4) {
+ w += sldns_str_print(s, sl, "malformed subnet ");
+ w += print_hex_buf(s, sl, data, len);
+ return w;
+ }
+ family = sldns_read_uint16(data);
+ source = data[2];
+ scope = data[3];
+ if(family == 1) {
+ /* IP4 */
+ char buf[64];
+ uint8_t ip4[4];
+ memset(ip4, 0, sizeof(ip4));
+ if(len-4 > 4) {
+ w += sldns_str_print(s, sl, "trailingdata:");
+ w += print_hex_buf(s, sl, data+4+4, len-4-4);
+ w += sldns_str_print(s, sl, " ");
+ len = 4+4;
+ }
+ memmove(ip4, data+4, len-4);
+ if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) {
+ w += sldns_str_print(s, sl, "ip4ntoperror ");
+ w += print_hex_buf(s, sl, data+4+4, len-4-4);
+ } else {
+ w += sldns_str_print(s, sl, "%s", buf);
+ }
+ } else if(family == 2) {
+ /* IP6 */
+ char buf[64];
+ uint8_t ip6[16];
+ memset(ip6, 0, sizeof(ip6));
+ if(len-4 > 16) {
+ w += sldns_str_print(s, sl, "trailingdata:");
+ w += print_hex_buf(s, sl, data+4+16, len-4-16);
+ w += sldns_str_print(s, sl, " ");
+ len = 4+16;
+ }
+ memmove(ip6, data+4, len-4);
+#ifdef AF_INET6
+ if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) {
+ w += sldns_str_print(s, sl, "ip6ntoperror ");
+ w += print_hex_buf(s, sl, data+4+4, len-4-4);
+ } else {
+ w += sldns_str_print(s, sl, "%s", buf);
+ }
+#else
+ w += print_hex_buf(s, sl, data+4+4, len-4-4);
+#endif
+ } else {
+ /* unknown */
+ w += sldns_str_print(s, sl, "family %d ",
+ (int)family);
+ w += print_hex_buf(s, sl, data, len);
+ }
+ w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope);
+ return w;
+}
+
+int sldns_wire2str_edns_option_print(char** s, size_t* sl,
+ uint16_t option_code, uint8_t* optdata, size_t optlen)
+{
+ int w = 0;
+ w += sldns_wire2str_edns_option_code_print(s, sl, option_code);
+ w += sldns_str_print(s, sl, ": ");
+ switch(option_code) {
+ case LDNS_EDNS_LLQ:
+ w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen);
+ break;
+ case LDNS_EDNS_UL:
+ w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen);
+ break;
+ case LDNS_EDNS_NSID:
+ w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen);
+ break;
+ case LDNS_EDNS_DAU:
+ w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen);
+ break;
+ case LDNS_EDNS_DHU:
+ w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen);
+ break;
+ case LDNS_EDNS_N3U:
+ w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen);
+ break;
+ case LDNS_EDNS_CLIENT_SUBNET:
+ w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
+ break;
+ default:
+ /* unknown option code */
+ w += print_hex_buf(s, sl, optdata, optlen);
+ break;
+ }
+ return w;
+}
+
+/** print the edns options to string */
+static int
+print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen)
+{
+ uint16_t option_code, option_len;
+ int w = 0;
+ while(rdatalen > 0) {
+ /* option name */
+ if(rdatalen < 4) {
+ w += sldns_str_print(s, sl, " ; malformed: ");
+ w += print_hex_buf(s, sl, rdata, rdatalen);
+ return w;
+ }
+ option_code = sldns_read_uint16(rdata);
+ option_len = sldns_read_uint16(rdata+2);
+ rdata += 4;
+ rdatalen -= 4;
+
+ /* option value */
+ if(rdatalen < (size_t)option_len) {
+ w += sldns_str_print(s, sl, " ; malformed ");
+ w += sldns_wire2str_edns_option_code_print(s, sl,
+ option_code);
+ w += sldns_str_print(s, sl, ": ");
+ w += print_hex_buf(s, sl, rdata, rdatalen);
+ return w;
+ }
+ w += sldns_str_print(s, sl, " ; ");
+ w += sldns_wire2str_edns_option_print(s, sl, option_code,
+ rdata, option_len);
+ rdata += option_len;
+ rdatalen -= option_len;
+ }
+ return w;
+}
+
+int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint8_t* pkt, size_t pktlen)
+{
+ int w = 0;
+ uint8_t ext_rcode, edns_version;
+ uint16_t udpsize, edns_bits, rdatalen;
+ w += sldns_str_print(str, str_len, "; EDNS:");
+
+ /* some input checks, domain name */
+ if(*data_len < 1+10)
+ return w + print_remainder_hex("Error malformed 0x",
+ data, data_len, str, str_len);
+ if(*data[0] != 0) {
+ return w + print_remainder_hex("Error nonrootdname 0x",
+ data, data_len, str, str_len);
+ }
+ (*data)++;
+ (*data_len)--;
+
+ /* check type and read fixed contents */
+ if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) {
+ return w + print_remainder_hex("Error nottypeOPT 0x",
+ data, data_len, str, str_len);
+ }
+ udpsize = sldns_read_uint16((*data)+2);
+ ext_rcode = (*data)[4];
+ edns_version = (*data)[5];
+ edns_bits = sldns_read_uint16((*data)+6);
+ rdatalen = sldns_read_uint16((*data)+8);
+ (*data)+=10;
+ (*data_len)-=10;
+
+ w += sldns_str_print(str, str_len, " version: %u;",
+ (unsigned)edns_version);
+ w += sldns_str_print(str, str_len, " flags:");
+ if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
+ w += sldns_str_print(str, str_len, " do");
+ /* the extended rcode is the value set, shifted four bits,
+ * and or'd with the original rcode */
+ if(ext_rcode) {
+ int rc = ((int)ext_rcode)<<4;
+ if(pkt && pktlen >= LDNS_HEADER_SIZE)
+ rc |= LDNS_RCODE_WIRE(pkt);
+ w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc);
+ }
+ w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize);
+
+ if(rdatalen) {
+ if(*data_len < rdatalen) {
+ w += sldns_str_print(str, str_len,
+ " ; Error EDNS rdata too short; ");
+ rdatalen = *data_len;
+ }
+ w += print_edns_opts(str, str_len, *data, rdatalen);
+ (*data) += rdatalen;
+ (*data_len) -= rdatalen;
+ }
+ w += sldns_str_print(str, str_len, "\n");
+ return w;
+}
--- /dev/null
+/**
+ * wire2str.h - txt presentation of RRs
+ *
+ * (c) NLnet Labs, 2005-2006
+ *
+ * See the file LICENSE for the license
+ */
+
+/**
+ * \file
+ *
+ * Contains functions to translate the wireformat to text
+ * representation, as well as functions to print them.
+ */
+
+#ifndef LDNS_WIRE2STR_H
+#define LDNS_WIRE2STR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+struct sldns_struct_lookup_table;
+
+/* lookup tables for standard DNS stuff */
+/** Taken from RFC 2535, section 7. */
+extern struct sldns_struct_lookup_table* sldns_algorithms;
+/** DS record hash algorithms */
+extern struct sldns_struct_lookup_table* sldns_hashes;
+/** Taken from RFC 2538, section 2.1. */
+extern struct sldns_struct_lookup_table* sldns_cert_algorithms;
+/** Response codes */
+extern struct sldns_struct_lookup_table* sldns_rcodes;
+/** Operation codes */
+extern struct sldns_struct_lookup_table* sldns_opcodes;
+/** EDNS flags */
+extern struct sldns_struct_lookup_table* sldns_edns_flags;
+/** EDNS option codes */
+extern struct sldns_struct_lookup_table* sldns_edns_options;
+/** error string from wireparse */
+extern struct sldns_struct_lookup_table* sldns_wireparse_errors;
+
+/**
+ * Convert wireformat packet to a string representation
+ * @param data: wireformat packet data (starting at ID bytes).
+ * @param len: length of packet.
+ * @return string(malloced) or NULL on failure.
+ */
+char* sldns_wire2str_pkt(uint8_t* data, size_t len);
+
+/**
+ * Convert wireformat RR to a string representation.
+ * @param rr: the wireformat RR, in uncompressed form. Starts at the domain
+ * name start, ends with the rdata of the RR.
+ * @param len: length of the rr wireformat.
+ * @return string(malloced) or NULL on failure.
+ */
+char* sldns_wire2str_rr(uint8_t* rr, size_t len);
+
+/**
+ * Conver wire dname to a string.
+ * @param dname: the dname in uncompressed wireformat.
+ * @param dname_len: length of the dname.
+ * @return string or NULL on failure.
+ */
+char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len);
+
+/**
+ * Convert wire RR type to a string, 'MX', 'TYPE1234'...
+ * @param rrtype: the RR type in host order.
+ * @return malloced string with the RR type or NULL on malloc failure.
+ */
+char* sldns_wire2str_type(uint16_t rrtype);
+
+/**
+ * Convert wire RR class to a string, 'IN', 'CLASS1'.
+ * @param rrclass: the RR class in host order.
+ * @return malloced string with the RR class or NULL on malloc failure.
+ */
+char* sldns_wire2str_class(uint16_t rrclass);
+
+/**
+ * Convert wire packet rcode to a string, 'NOERROR', 'NXDOMAIN'...
+ * @param rcode: as integer, host order
+ * @return malloced string with the rcode or NULL on malloc failure.
+ */
+char* sldns_wire2str_rcode(int rcode);
+
+/**
+ * Print to string, move string along for next content. With va_list.
+ * @param str: string buffer. Adjusted at end to after the output.
+ * @param slen: length of the string buffer. Adjusted at end.
+ * @param format: printf format string.
+ * @param args: arguments for printf.
+ * @return number of characters needed. Can be larger than slen.
+ */
+int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args);
+
+/**
+ * Print to string, move string along for next content.
+ * @param str: string buffer. Adjusted at end to after the output.
+ * @param slen: length of the string buffer. Adjusted at end.
+ * @param format: printf format string and arguments for it.
+ * @return number of characters needed. Can be larger than slen.
+ */
+int sldns_str_print(char** str, size_t* slen, const char* format, ...)
+ ATTR_FORMAT(printf, 3, 4);
+
+/**
+ * Convert wireformat packet to a string representation with user buffer
+ * It appends every RR with default comments.
+ * For more formatter options use the function: TBD(TODO)
+ * @param data: wireformat packet data (starting at ID bytes).
+ * @param data_len: length of packet.
+ * @param str: the string buffer for the output.
+ * If you pass NULL as the str the return value of the function is
+ * the str_len you need for the entire packet. It does not include
+ * the 0 byte at the end.
+ * @param str_len: the size of the string buffer. If more is needed, it'll
+ * silently truncate the output to fit in the buffer.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_pkt_buf(uint8_t* data, size_t data_len, char* str,
+ size_t str_len);
+
+/**
+ * Scan wireformat packet to a string representation with user buffer
+ * It appends every RR with default comments.
+ * For more formatter options use the function: TBD(TODO)
+ * @param data: wireformat packet data (starting at ID bytes).
+ * @param data_len: length of packet.
+ * @param str: the string buffer for the output.
+ * @param str_len: the size of the string buffer.
+ * @return number of characters for string.
+ * returns the number of characters that are needed (except terminating null),
+ * so it may return a value larger than str_len.
+ * On error you get less output (i.e. shorter output in str (null terminated))
+ * On exit the data, data_len, str and str_len values are adjusted to move them
+ * from their original position along the input and output for the content
+ * that has been consumed (and produced) by this function. If the end of the
+ * output string is reached, *str_len is set to 0. The output string is null
+ * terminated (shortening the output if necessary). If the end of the input
+ * is reached *data_len is set to 0.
+ */
+int sldns_wire2str_pkt_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat rr to string, with user buffers. It shifts the arguments
+ * to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param pkt: packet for decompression, if NULL no decompression.
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_rr_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint8_t* pkt, size_t pktlen);
+
+/**
+ * Scan wireformat question rr to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param pkt: packet for decompression, if NULL no decompression.
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_rrquestion_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint8_t* pkt, size_t pktlen);
+
+/**
+ * Scan wireformat RR to string in unknown RR format, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param pkt: packet for decompression, if NULL no decompression.
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_rr_unknown_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint8_t* pkt, size_t pktlen);
+
+/**
+ * Print to string the RR-information comment in default format,
+ * with user buffers. Moves string along.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param rr: wireformat data.
+ * @param rrlen: length of data buffer.
+ * @param dname_off: offset in buffer behind owner dname, the compressed size
+ * of the owner name.
+ * @param rrtype: type of the RR, host format.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_rr_comment_print(char** str, size_t* str_len, uint8_t* rr,
+ size_t rrlen, size_t dname_off, uint16_t rrtype);
+
+/**
+ * Scan wireformat packet header to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_header_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat rdata to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer. The length of the rdata in the
+ * buffer. The rdatalen itself has already been scanned, the data
+ * points to the rdata after the rdatalen.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param rrtype: RR type of Rdata, host format.
+ * @param pkt: packet for decompression, if NULL no decompression.
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_rdata_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint16_t rrtype, uint8_t* pkt, size_t pktlen);
+
+/**
+ * Scan wireformat rdata to string in unknown format, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer, the length of the rdata in buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_rdata_unknown_scan(uint8_t** data, size_t* data_len,
+ char** str, size_t* str_len);
+
+/**
+ * Scan wireformat domain name to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param pkt: packet for decompression, if NULL no decompression.
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_dname_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint8_t* pkt, size_t pktlen);
+
+/**
+ * Scan wireformat rr type to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_type_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat rr class to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_class_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat rr ttl to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_ttl_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+
+/**
+ * Print host format rr type to string. Moves string along, user buffers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param rrtype: host format rr type.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_type_print(char** str, size_t* str_len, uint16_t rrtype);
+
+/**
+ * Print host format rr class to string. Moves string along, user buffers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param rrclass: host format rr class.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_class_print(char** str, size_t* str_len, uint16_t rrclass);
+
+/**
+ * Print host format rcode to string. Moves string along, user buffers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param rcode: host format rcode number.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_rcode_print(char** str, size_t* str_len, int rcode);
+
+/**
+ * Print host format opcode to string. Moves string along, user buffers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param opcode: host format opcode number.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_opcode_print(char** str, size_t* str_len, int opcode);
+
+/**
+ * Print host format EDNS0 option to string. Moves string along, user buffers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param opcode: host format option number.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_option_code_print(char** str, size_t* str_len,
+ uint16_t opcode);
+
+/**
+ * Convert RR to string presentation format, on one line. User buffer.
+ * @param rr: wireformat RR data
+ * @param rr_len: length of the rr wire data.
+ * @param str: the string buffer to write to.
+ * If you pass NULL as the str, the return value of the function is
+ * the str_len you need for the entire packet. It does not include
+ * the 0 byte at the end.
+ * @param str_len: the size of the string buffer. If more is needed, it'll
+ * silently truncate the output to fit in the buffer.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
+ size_t str_len);
+
+/**
+ * 3597 printout of an RR in unknown rr format.
+ * There are more format and comment options available for printout
+ * with the function: TBD(TODO)
+ * @param rr: wireformat RR data
+ * @param rr_len: length of the rr wire data.
+ * @param str: the string buffer to write to.
+ * If you pass NULL as the str, the return value of the function is
+ * the str_len you need for the entire rr. It does not include
+ * the 0 byte at the end.
+ * @param str_len: the size of the string buffer. If more is needed, it'll
+ * silently truncate the output to fit in the buffer.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str,
+ size_t str_len);
+
+/**
+ * This creates the comment to print after the RR. ; keytag=... , and other
+ * basic comments for RRs.
+ * There are more format and comment options available for printout
+ * with the function: TBD(TODO)
+ * @param rr: wireformat RR data
+ * @param rr_len: length of the rr wire data.
+ * @param dname_len: length of the dname in front of the RR.
+ * @param str: the string buffer to write to.
+ * If you pass NULL as the str, the return value of the function is
+ * the str_len you need for the entire comment. It does not include
+ * the 0 byte at the end.
+ * @param str_len: the size of the string buffer. If more is needed, it'll
+ * silently truncate the output to fit in the buffer.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len,
+ char* str, size_t str_len);
+
+/**
+ * Convert RDATA to string presentation format, on one line. User buffer.
+ * @param rdata: wireformat rdata part of an RR.
+ * @param rdata_len: length of the rr wire data.
+ * @param str: the string buffer to write to.
+ * If you pass NULL as the str, the return value of the function is
+ * the str_len you need for the entire packet. It does not include
+ * the 0 byte at the end.
+ * @param str_len: the size of the string buffer. If more is needed, it'll
+ * silently truncate the output to fit in the buffer.
+ * @param rrtype: rr type of the data
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
+ size_t str_len, uint16_t rrtype);
+
+/**
+ * Convert wire RR type to a string, 'MX', 'TYPE12'. With user buffer.
+ * @param rrtype: the RR type in host order.
+ * @param str: the string to write to.
+ * @param len: length of str.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len);
+
+/**
+ * Convert wire RR class to a string, 'IN', 'CLASS12'. With user buffer.
+ * @param rrclass: the RR class in host order.
+ * @param str: the string to write to.
+ * @param len: length of str.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
+
+/**
+ * Convert wire RR rcode to a string, 'NOERROR', 'NXDOMAIN'. With user buffer.
+ * @param rcode: rcode as integer in host order
+ * @param str: the string to write to.
+ * @param len: length of str.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
+
+/**
+ * Convert wire dname to a string, "example.com.". With user buffer.
+ * @param dname: the dname in uncompressed wireformat.
+ * @param dname_len: length of the dname.
+ * @param str: the string to write to.
+ * @param len: length of string.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger than str_len if output was truncated.
+ */
+int sldns_wire2str_dname_buf(uint8_t* dname, size_t dname_len, char* str,
+ size_t len);
+
+/**
+ * Scan wireformat rdf field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param rdftype: the type of the rdata field, enum sldns_rdf_type.
+ * @param pkt: packet for decompression, if NULL no decompression.
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_rdf_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, int rdftype, uint8_t* pkt, size_t pktlen);
+
+/**
+ * Scan wireformat int8 field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_int8_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat int16 field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_int16_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat int32 field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_int32_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat period field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_period_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat tsigtime field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_tsigtime_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat ip4 A field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_a_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat ip6 AAAA field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_aaaa_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat str field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_str_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat apl field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_apl_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat b32_ext field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_b32_ext_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat b64 field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_b64_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat hex field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_hex_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat nsec bitmap field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_nsec_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat nsec3_salt field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_nsec3_salt_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat cert_alg field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_cert_alg_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat alg field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_alg_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat type unknown field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_unknown_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat time field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_time_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat LOC field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_loc_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat WKS field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_wks_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat NSAP field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_nsap_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat ATMA field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_atma_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat IPSECKEY field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param pkt: packet for decompression, if NULL no decompression.
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_ipseckey_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint8_t* pkt, size_t pktlen);
+
+/**
+ * Scan wireformat HIP (algo, HIT, pubkey) field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_hip_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat int16_data field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_int16_data_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat nsec3_next_owner field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_nsec3_next_owner_scan(uint8_t** data, size_t* data_len,
+ char** str, size_t* str_len);
+
+/**
+ * Scan wireformat ILNP64 field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_ilnp64_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat EUI48 field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_eui48_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat EUI64 field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_eui64_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat TAG field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_tag_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Scan wireformat long_str field to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @return number of characters (except null) needed to print.
+ * Can return -1 on failure.
+ */
+int sldns_wire2str_long_str_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len);
+
+/**
+ * Print EDNS LLQ option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_llq_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
+ * Print EDNS UL option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_ul_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
+ * Print EDNS NSID option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_nsid_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
+ * Print EDNS DAU option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_dau_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
+ * Print EDNS DHU option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_dhu_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
+ * Print EDNS N3U option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_n3u_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
+ * Print EDNS SUBNET option data to string. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_subnet_print(char** str, size_t* str_len,
+ uint8_t* option_data, size_t option_len);
+
+/**
+ * Print an EDNS option as OPT: VALUE. User buffers, moves string pointers.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param option_code: host format EDNS option code.
+ * @param option_data: buffer with EDNS option code data.
+ * @param option_len: length of the data for this option.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_option_print(char** str, size_t* str_len,
+ uint16_t option_code, uint8_t* option_data, size_t option_len);
+
+/**
+ * Scan wireformat EDNS OPT to string, with user buffers.
+ * It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
+ * @param data: wireformat data.
+ * @param data_len: length of data buffer.
+ * @param str: string buffer.
+ * @param str_len: length of string buffer.
+ * @param pkt: packet with header and other info (may be NULL)
+ * @param pktlen: length of packet buffer.
+ * @return number of characters (except null) needed to print.
+ */
+int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
+ size_t* str_len, uint8_t* pkt, size_t pktlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LDNS_WIRE2STR_H */
# settings:
# directory for files
-DESTDIR=/usr/local/etc/unbound
+DESTDIR=@ub_conf_dir@
# issuer and subject name for certificates
SERVERNAME=unbound
--- /dev/null
+#!/usr/local/bin/bash
+# run tpkg tests from within a VM. Looks for loopback addr.
+# if run not from within a VM, runs the tests as usual.
+# with one argument: run that tpkg, otherwise, run all tpkgs.
+
+get_lo0_ip4() {
+ if test -x /sbin/ifconfig
+ then
+ LO0_IP4=`/sbin/ifconfig lo0 | grep '[^0-9]127\.' | sed -e 's/^[^1]*\(127\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[^0-9]*.*$/\1/g'`
+ if ( echo $LO0_IP4 | grep '^127\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null )
+ then
+ return
+ fi
+ fi
+ LO0_IP4=127.0.0.1
+}
+get_lo0_ip4
+export LO0_IP4
+if test "x$LO0_IP4" = "x127.0.0.1"
+then
+ ALT_LOOPBACK=false
+else
+ ALT_LOOPBACK=true
+fi
+cd testdata
+TPKG=../testcode/mini_tpkg.sh
+#RUNLIST=`(ls -1 *.tpkg|grep -v '^0[016]')`
+RUNLIST=`(ls -1 *.tpkg)`
+if test "$#" = "1"; then RUNLIST="$1"; fi
+
+# fix up tpkg that was edited on keyboard interrupt.
+cleanup() {
+ echo cleanup
+ if test -f "$t.bak"; then mv "$t.bak" "$t"; fi
+ exit 0
+}
+trap cleanup SIGINT
+
+for t in $RUNLIST
+do
+ if ! $ALT_LOOPBACK
+ then
+ $TPKG exe $t
+ continue
+ fi
+ # We have alternative 127.0.0.1 number
+ if ( echo $t | grep '6\.tpkg$' ) # skip IPv6 tests
+ then
+ continue
+ elif test "$t" = "edns_cache.tpkg" # This one is IPv6 too!
+ then
+ continue
+ fi
+ cp -p "$t" "$t.bak"
+ tar xzf $t
+ find "${t%.tpkg}.dir" -type f \
+ -exec grep -q -e '127\.0\.0\.1' -e '@localhost' {} \; -print | {
+ while read f
+ do
+ sed "s/127\.0\.0\.1/${LO0_IP4}/g" "$f" > "$f._"
+ mv "$f._" "$f"
+ sed "s/@localhost/@${LO0_IP4}/g" "$f" > "$f._"
+ mv "$f._" "$f"
+ done
+ }
+ find "${t%.tpkg}.dir" -type d -name "127.0.0.1" -print | {
+ while read d
+ do
+ mv -v "$d" "${d%127.0.0.1}${LO0_IP4}"
+ done
+ }
+ tar czf $t "${t%.tpkg}.dir"
+ rm -fr "${t%.tpkg}.dir"
+ $TPKG exe $t
+ mv "$t.bak" "$t"
+done
+# get out of testdata/
+cd ..
--- /dev/null
+; config options
+; The island of trust is at example.com (the DLV repository)
+server:
+ dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with DLV anchor but DLV domain is down
+; so DLV has been decommissioned.
+
+; 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 subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+
+ENTRY_BEGIN
+MATCH opcode
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.com. IN NS
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+; DS RR is
+; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix
+; DNSKEY prime query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN DNSKEY
+SECTION ANSWER
+example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+; NS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+; www.example.net query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+www.example.net. 3600 IN A 10.20.30.40
+www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.net. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+; The island of trust is at example.com (the DLV repository)
+server:
+ dlv-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with DLV and DLV repository is empty.
+
+; 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 subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; DLV query, everything is NXDOMAIN
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+example.com. IN DLV
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN NSEC example.com. NS SOA RRSIG NSEC DNSKEY
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AH++lP1qhsBw6zO1g3JVPZeQIpDhL9xT8V9xdgjXvCjIGQ1BUUlfQkA=
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net.example.com. IN DLV
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854}
+example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+com.example.com. IN DLV
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854}
+example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854}
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+; DS RR is
+; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix
+; DNSKEY prime query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN DNSKEY
+SECTION ANSWER
+example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+; NS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+; www.example.net query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+www.example.net. 3600 IN A 10.20.30.40
+www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.net. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+www.example.net. 3600 IN A 10.20.30.40
+www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+; The island of trust is at example.com (the DLV repository)
+server:
+ dlv-anchor: "dlv.example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with DLV and DLV is removed and not delegated
+; so the response is that the dlv domain itself does not exist, but it's
+; parent domain does exist (securely).
+
+; 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 subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN A
+SECTION AUTHORITY
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN A
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; DLV query, everything is NXDOMAIN
+; thus, no delegation to the dlv repository in dlv.example.com
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR AA NXDOMAIN
+SECTION QUESTION
+example.com. IN DLV
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. 3600 IN NSEC example.com. NS SOA RRSIG NSEC DNSKEY
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926135752 20070829135752 2854 example.com. AH++lP1qhsBw6zO1g3JVPZeQIpDhL9xT8V9xdgjXvCjIGQ1BUUlfQkA=
+SECTION ADDITIONAL
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net.example.com. IN DLV
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854}
+example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+com.example.com. IN DLV
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN SOA open.nlnetlabs.nl. hostmaster.nlnetlabs.nl. 2008081300 28800 7200 604800 3600
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. AKPJnPBqfJKxE4P2iVYkSRJno9HmiXJZtjdqE8oBeq9Lk9FytcMdcig= ;{id = 2854}
+example.com IN NSEC example.net.example.com. SOA NS RRSIG NSEC
+example.com. 3600 IN RRSIG NSEC 3 2 3600 20070926134150 20070829134150 2854 example.com. AIoUkJ04/7/kJFDLocoqksqt9UL2RHHwlRfXAMxGdBHcNO+GSpG47Uk= ;{id = 2854}
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+; DS RR is
+; example.net. 3600 IN DS 30899 5 1 14188c885f20623ad1d3bec42798f3f951793e4c ; xehac-mofum-malyd-bomaf-pegit-fuzes-ganin-misiz-nigel-nozog-soxix
+; DNSKEY prime query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN DNSKEY
+SECTION ANSWER
+example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+; NS query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+; www.example.net query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+www.example.net. 3600 IN A 10.20.30.40
+www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.net. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.net. IN A
+SECTION ANSWER
+www.example.net. 3600 IN A 10.20.30.40
+www.example.net. 3600 IN RRSIG A 5 3 3600 20070926135752 20070829135752 30899 example.net. ACvv4RQVC7TbI57ewqFImRaVoymktJ5Cxn/FaCodIENt82LVM92nivbP2WtwWCsQHWp7FkrMxTlQTJwyAeXFyg== ;{id = 30899}
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.5
+ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+; The island of trust is at example.com
+server:
+ dlv-anchor: "dlv.example.net. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with DLV removed for positive anchored response
+; So the destination has a valid DNSSEC chain of trust to the root,
+; but the configured dlv anchor fails.
+
+; 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
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+; this covers dlv.example.net and thus makes it servfail (unusable).
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+net. IN NS
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+ module-config: "dns64 validator iterator"
+ dns64-prefix: 64:ff9b::0/96
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test dns64 lookup and synthesis.
+; normal A lookup should still succeed
+; AAAA is synthesized if not present.
+; AAAA if present, is passed through unchanged.
+
+; 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
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ip4.example.com. IN AAAA
+SECTION ANSWER
+; NO AAAA present
+SECTION AUTHORITY
+example.com. IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ip4.example.com. IN A
+SECTION ANSWER
+ip4.example.com. IN A 5.6.7.8
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ip6.example.com. IN AAAA
+SECTION ANSWER
+ip6.example.com. IN AAAA 1:2:3::4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; synthesize from A record 5.6.7.8
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ip4.example.com. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ip4.example.com. IN AAAA
+SECTION ANSWER
+ip4.example.com. IN AAAA 64:ff9b::506:708
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; this node has its own ipv6 address
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ip6.example.com. IN AAAA
+ENTRY_END
+
+; recursion happens here.
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ip6.example.com. IN AAAA
+SECTION ANSWER
+ip6.example.com. IN AAAA 1:2:3::4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with spurious unsigned NS in auth section
+
+; 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
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+SECTION AUTHORITY
+; removed by spurious NS record removal code
+;;example.com. IN NS ns.example.com.
+;;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}"
+ trust-anchor: "example.com. 3600 IN DS 30899 5 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+ harden-algo-downgrade: no
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with multiple algorithm trust anchor without harden
+
+; 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
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 512b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. AKIIYDOGHogglFqJK94ZtOnF7EfGikgAyloMNRSMCrQgFaFkmcOyjrc= ;{id = 2854}
+example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20070926134150 20070829134150 30899 example.com. J55fsz1GGMnngc4r50xvXDUdaVMlfcLKLVsfMhwNLF+ERac5XV/lLRAc/aSER+qQdsSo0CrjYjy1wat7YQpDAA== ;{id = 30899}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. JNWECShNE+nCLQwOXJJ3xpUkh2G+FCh5nk8uYAHIVQRse/BIvCMSlvRrtVyw9RnXvk5RR2bEgN0pRdLWW7ug5Q== ;{id = 30899}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. JNWECShNE+nCLQwOXJJ3xpUkh2G+FCh5nk8uYAHIVQRse/BIvCMSlvRrtVyw9RnXvk5RR2bEgN0pRdLWW7ug5Q== ;{id = 30899}
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}"
+ trust-anchor: "example.com. 3600 IN DS 30899 5 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512"
+ trust-anchor: "example.com. 3600 IN DS 30899 7 1 d4bf9d2e10f6d76840d42ef5913022abcd0bf512"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+ harden-algo-downgrade: no
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with multiple algorithm missing one
+
+; 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
+www.example.com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJIIs70j+sDS/UT2QRp61SE7S3EEXopNXoFE73JLRmvpi/UrOO/Vz4Se6wXv/CYCKjGw06U4WRgRYXcpEhJROyNapmdIKSxhOzfLVE1gqA0PweZR8dtY3aNQSRn3sPpwJr6Mi/PqQKAMMrZ9ckJpf1+bQMOOvxgzz2U1GS18b3yZKcgTMEaJzd/GZYzi/BN2DzQ0MsrSwYXfsNLFOBbs8PJMW4LYIxeeOe6rUgkWOF7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 512b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134150 20070829134150 2854 example.com. AKIIYDOGHogglFqJK94ZtOnF7EfGikgAyloMNRSMCrQgFaFkmcOyjrc= ;{id = 2854}
+example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20070926134150 20070829134150 30899 example.com. J55fsz1GGMnngc4r50xvXDUdaVMlfcLKLVsfMhwNLF+ERac5XV/lLRAc/aSER+qQdsSo0CrjYjy1wat7YQpDAA== ;{id = 30899}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. JNWECShNE+nCLQwOXJJ3xpUkh2G+FCh5nk8uYAHIVQRse/BIvCMSlvRrtVyw9RnXvk5RR2bEgN0pRdLWW7ug5Q== ;{id = 30899}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 3600 IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. JNWECShNE+nCLQwOXJJ3xpUkh2G+FCh5nk8uYAHIVQRse/BIvCMSlvRrtVyw9RnXvk5RR2bEgN0pRdLWW7ug5Q== ;{id = 30899}
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+
+SECTION AUTHORITY
+example.com. 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN RRSIG NS 5 2 3600 20070926134150 20070829134150 30899 example.com. YTqtYba73HIOQuPr5oDyIX9pfmz1ybEBjwlD/jUgcPmFINUOZ9FeqG6ywgRKwn4AizkKTK00p1sxZYMKxl91wg== ;{id = 30899}
+
+SECTION ADDITIONAL
+ns.example.com. 3600 IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ns.example.com. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.com. Dn1ziMKrc3NdJkSv8g61Y9WNk3+BAuwCwnYzAZiHmkejkSCPViLJN7+f4Conp9l8LkTl50ZnLgoYrrUYNhMj6w== ;{id = 30899}
+ENTRY_END
+
+SCENARIO_END