From: Yuri Schaeffer Date: Thu, 30 Apr 2015 07:48:03 +0000 (+0000) Subject: also include all these new files. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a7e6d42ed031d053a951020389a98f2d77af9087;p=thirdparty%2Funbound.git also include all these new files. git-svn-id: file:///svn/unbound/branches/edns-subnet@3416 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/Makefile.in b/Makefile.in index c7f493703..7fb53ba04 100644 --- a/Makefile.in +++ b/Makefile.in @@ -698,18 +698,6 @@ iter_utils.lo iter_utils.o: $(srcdir)/iterator/iter_utils.c config.h $(srcdir)/i $(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 \ @@ -736,7 +724,7 @@ modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/service $(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 \ @@ -745,9 +733,7 @@ outside_network.lo outside_network.o: $(srcdir)/services/outside_network.c confi $(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 \ @@ -795,14 +781,12 @@ netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/neteve $(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 \ @@ -837,8 +821,7 @@ autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/val $(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 \ @@ -863,22 +846,20 @@ val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/ 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 \ @@ -886,17 +867,14 @@ val_nsec.lo val_nsec.o: $(srcdir)/validator/val_nsec.c config.h $(srcdir)/valida $(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 \ @@ -905,6 +883,13 @@ val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/val $(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 \ @@ -914,11 +899,6 @@ dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(src $(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 @@ -927,8 +907,7 @@ unitdname.lo unitdname.o: $(srcdir)/testcode/unitdname.c config.h $(srcdir)/util $(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 \ @@ -939,9 +918,6 @@ unitmsgparse.lo unitmsgparse.o: $(srcdir)/testcode/unitmsgparse.c config.h $(src $(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 \ @@ -966,41 +942,39 @@ testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcod $(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 \ @@ -1024,35 +998,33 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s $(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 \ @@ -1068,12 +1040,12 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr $(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 \ @@ -1081,18 +1053,17 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr 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 \ @@ -1163,19 +1134,18 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou $(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 \ @@ -1186,21 +1156,18 @@ streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h $(srcdir)/util $(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 \ @@ -1213,8 +1180,7 @@ win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc $(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 @@ -1222,14 +1188,11 @@ unbound-service-remove.lo unbound-service-remove.o: $(srcdir)/winrc/unbound-serv $(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 @@ -1249,8 +1212,7 @@ snprintf.lo snprintf.o: $(srcdir)/compat/snprintf.c config.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 diff --git a/compat/arc4_lock.c b/compat/arc4_lock.c new file mode 100644 index 000000000..faa743d15 --- /dev/null +++ b/compat/arc4_lock.c @@ -0,0 +1,67 @@ +/* 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 */ diff --git a/compat/arc4random.c b/compat/arc4random.c new file mode 100644 index 000000000..27a626b7b --- /dev/null +++ b/compat/arc4random.c @@ -0,0 +1,231 @@ +/* $OpenBSD: arc4random.c,v 1.41 2014/07/12 13:24:54 deraadt Exp $ */ + +/* + * Copyright (c) 1996, David Mazieres + * Copyright (c) 2008, Damien Miller + * Copyright (c) 2013, Markus Friedl + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef UB_ON_WINDOWS +#include +#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(); +} diff --git a/compat/arc4random_uniform.c b/compat/arc4random_uniform.c new file mode 100644 index 000000000..154260ebd --- /dev/null +++ b/compat/arc4random_uniform.c @@ -0,0 +1,57 @@ +/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */ + +/* + * Copyright (c) 2008, Damien Miller + * + * 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 +#include + +/* + * 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; +} diff --git a/compat/chacha_private.h b/compat/chacha_private.h new file mode 100644 index 000000000..192258c7f --- /dev/null +++ b/compat/chacha_private.h @@ -0,0 +1,222 @@ +/* +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 + } +} diff --git a/compat/explicit_bzero.c b/compat/explicit_bzero.c new file mode 100644 index 000000000..a3ba2798a --- /dev/null +++ b/compat/explicit_bzero.c @@ -0,0 +1,22 @@ +/* $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 + +__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); +} diff --git a/compat/getentropy_linux.c b/compat/getentropy_linux.c new file mode 100644 index 000000000..76f0f9df5 --- /dev/null +++ b/compat/getentropy_linux.c @@ -0,0 +1,540 @@ +/* $OpenBSD: getentropy_linux.c,v 1.20 2014/07/12 15:43:49 beck Exp $ */ + +/* + * Copyright (c) 2014 Theo de Raadt + * Copyright (c) 2014 Bob Beck + * + * 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 +#include +#include +#include +#include +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef HAVE_GETAUXVAL +#include +#endif +#include + +#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; +} diff --git a/compat/getentropy_osx.c b/compat/getentropy_osx.c new file mode 100644 index 000000000..d5a64ab36 --- /dev/null +++ b/compat/getentropy_osx.c @@ -0,0 +1,432 @@ +/* $OpenBSD: getentropy_osx.c,v 1.3 2014/07/12 14:48:00 deraadt Exp $ */ + +/* + * Copyright (c) 2014 Theo de Raadt + * Copyright (c) 2014 Bob Beck + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/compat/getentropy_solaris.c b/compat/getentropy_solaris.c new file mode 100644 index 000000000..838957382 --- /dev/null +++ b/compat/getentropy_solaris.c @@ -0,0 +1,435 @@ +/* $OpenBSD: getentropy_solaris.c,v 1.3 2014/07/12 14:46:31 deraadt Exp $ */ + +/* + * Copyright (c) 2014 Theo de Raadt + * Copyright (c) 2014 Bob Beck + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SHA512_Init SHA512Init +#define SHA512_Update SHA512Update +#define SHA512_Final SHA512Final + +#include +#include +#include + +#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; +} diff --git a/compat/getentropy_win.c b/compat/getentropy_win.c new file mode 100644 index 000000000..71fb955e7 --- /dev/null +++ b/compat/getentropy_win.c @@ -0,0 +1,56 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2014, Theo de Raadt + * Copyright (c) 2014, Bob Beck + * + * 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 +#include +#include +#include +#include +#include + +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); +} diff --git a/compat/reallocarray.c b/compat/reallocarray.c new file mode 100644 index 000000000..04d5d71c8 --- /dev/null +++ b/compat/reallocarray.c @@ -0,0 +1,39 @@ +/* $OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $ */ +/* + * Copyright (c) 2008 Otto Moerbeek + * + * 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 +#include +#include +#include + +/* + * 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); +} diff --git a/compat/sha512.c b/compat/sha512.c new file mode 100644 index 000000000..ac046abb7 --- /dev/null +++ b/compat/sha512.c @@ -0,0 +1,477 @@ +/* + * 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 /* memcpy()/memset() or bcopy()/bzero() */ +#include /* 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 (which in turn includes + * 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; +} diff --git a/config.guess b/config.guess index 1f5c50c0d..b79252d6b 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /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 @@ -50,7 +50,7 @@ version="\ 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." @@ -149,7 +149,7 @@ Linux|GNU|GNU/*) 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 @@ -826,7 +826,7 @@ EOF *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - *:MSYS*:*) + i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) @@ -969,10 +969,10 @@ EOF 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:*:*) @@ -1260,26 +1260,16 @@ EOF 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 ;; @@ -1371,6 +1361,154 @@ EOF exit ;; esac +eval $set_cc_for_build +cat >$dummy.c < +# include +#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 + 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 +# 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 <." 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." @@ -265,7 +265,6 @@ case $basic_machine in | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ @@ -283,10 +282,8 @@ case $basic_machine in | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ @@ -298,11 +295,11 @@ case $basic_machine in | 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 \ @@ -327,7 +324,7 @@ case $basic_machine in 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 ;; @@ -384,7 +381,6 @@ case $basic_machine in | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ @@ -404,10 +400,8 @@ case $basic_machine in | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ @@ -419,7 +413,6 @@ case $basic_machine in | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ - | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ @@ -829,10 +822,6 @@ case $basic_machine in basic_machine=powerpc-unknown os=-morphos ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; msdos) basic_machine=i386-pc os=-msdos @@ -1017,7 +1006,7 @@ case $basic_machine in ;; 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 @@ -1378,14 +1367,14 @@ case $os in | -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*) @@ -1603,6 +1592,9 @@ case $basic_machine in mips*-*) os=-elf ;; + or1k-*) + os=-elf + ;; or32-*) os=-coff ;; diff --git a/contrib/aaaa-filter-iterator.patch b/contrib/aaaa-filter-iterator.patch new file mode 100644 index 000000000..8e03d7c99 --- /dev/null +++ b/contrib/aaaa-filter-iterator.patch @@ -0,0 +1,394 @@ +--- 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 ++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 + 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; diff --git a/contrib/unbound_smf22.tar.gz b/contrib/unbound_smf22.tar.gz new file mode 100644 index 000000000..e4c51c3dc Binary files /dev/null and b/contrib/unbound_smf22.tar.gz differ diff --git a/dns64/dns64.c b/dns64/dns64.c new file mode 100644 index 000000000..63cc8084e --- /dev/null +++ b/dns64/dns64.c @@ -0,0 +1,873 @@ +/* + * 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; irrset_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; irrset_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(ian_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; +} diff --git a/dns64/dns64.h b/dns64/dns64.h new file mode 100644 index 000000000..2f0c01a22 --- /dev/null +++ b/dns64/dns64.h @@ -0,0 +1,71 @@ +/* + * 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 */ diff --git a/dnstap/dnstap.c b/dnstap/dnstap.c new file mode 100644 index 000000000..b62dc5b8c --- /dev/null +++ b/dnstap/dnstap.c @@ -0,0 +1,510 @@ +/* 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 +#include +#include "sldns/sbuffer.h" +#include "util/config_file.h" +#include "util/net_help.h" +#include "util/netevent.h" +#include "util/log.h" + +#include +#include + +#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 */ diff --git a/dnstap/dnstap.h b/dnstap/dnstap.h new file mode 100644 index 000000000..0103c1c0e --- /dev/null +++ b/dnstap/dnstap.h @@ -0,0 +1,188 @@ +/* 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 */ diff --git a/dnstap/dnstap.m4 b/dnstap/dnstap.m4 new file mode 100644 index 000000000..5b78b3e26 --- /dev/null +++ b/dnstap/dnstap.m4 @@ -0,0 +1,56 @@ +# 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 +]) diff --git a/dnstap/dnstap.proto b/dnstap/dnstap.proto new file mode 100644 index 000000000..3504d99ed --- /dev/null +++ b/dnstap/dnstap.proto @@ -0,0 +1,262 @@ +// 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: +// +// . + +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 diff --git a/dnstap/dnstap_config.h.in b/dnstap/dnstap_config.h.in new file mode 100644 index 000000000..c9f74893a --- /dev/null +++ b/dnstap/dnstap_config.h.in @@ -0,0 +1,17 @@ +#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 */ diff --git a/doc/README.DNS64 b/doc/README.DNS64 new file mode 100644 index 000000000..49446ac57 --- /dev/null +++ b/doc/README.DNS64 @@ -0,0 +1,30 @@ +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 + diff --git a/libunbound/python/file_py3.i b/libunbound/python/file_py3.i new file mode 100644 index 000000000..5d8b5a271 --- /dev/null +++ b/libunbound/python/file_py3.i @@ -0,0 +1,155 @@ +/* + * 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 +#include +%} + +%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""'"); + } +}*/ diff --git a/libunbound/worker.h b/libunbound/worker.h new file mode 100644 index 000000000..a53150199 --- /dev/null +++ b/libunbound/worker.h @@ -0,0 +1,179 @@ +/* + * 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 */ diff --git a/ltmain.sh b/ltmain.sh index 63ae69dc6..bffda5418 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -70,7 +70,7 @@ # 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 # @@ -80,7 +80,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION=2.4.2 +VERSION="2.4.2 Debian-2.4.2-1.11" TIMESTAMP="" package_revision=1.3337 @@ -6124,7 +6124,10 @@ func_mode_link () 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 @@ -6444,19 +6447,19 @@ func_mode_link () # 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 @@ -7349,6 +7352,9 @@ func_mode_link () revision="$number_minor" lt_irix_increment=no ;; + *) + func_fatal_configuration "$modename: unknown library version type \`$version_type'" + ;; esac ;; no) diff --git a/sldns/keyraw.c b/sldns/keyraw.c new file mode 100644 index 000000000..59e8000f5 --- /dev/null +++ b/sldns/keyraw.c @@ -0,0 +1,370 @@ +/* + * 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 +#include +#include +#include +#include +#ifdef HAVE_OPENSSL_ENGINE_H +# include +#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 */ diff --git a/sldns/keyraw.h b/sldns/keyraw.h new file mode 100644 index 000000000..8abe23509 --- /dev/null +++ b/sldns/keyraw.h @@ -0,0 +1,112 @@ +/* + * 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 +# include +#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 */ diff --git a/sldns/parse.c b/sldns/parse.c new file mode 100644 index 000000000..35dee7196 --- /dev/null +++ b/sldns/parse.c @@ -0,0 +1,470 @@ +/* + * 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 +#include + +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; + } +} + diff --git a/sldns/parse.h b/sldns/parse.h new file mode 100644 index 000000000..7b7456dd2 --- /dev/null +++ b/sldns/parse.h @@ -0,0 +1,184 @@ +/* + * 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 */ diff --git a/sldns/parseutil.c b/sldns/parseutil.c new file mode 100644 index 000000000..2a2ebbb08 --- /dev/null +++ b/sldns/parseutil.c @@ -0,0 +1,726 @@ +/* + * 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 +#include +#include + +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; +} diff --git a/sldns/parseutil.h b/sldns/parseutil.h new file mode 100644 index 000000000..dfa1c2a2b --- /dev/null +++ b/sldns/parseutil.h @@ -0,0 +1,148 @@ +/* + * 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 */ diff --git a/sldns/pkthdr.h b/sldns/pkthdr.h new file mode 100644 index 000000000..de9952ea7 --- /dev/null +++ b/sldns/pkthdr.h @@ -0,0 +1,158 @@ +/* + * 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 */ diff --git a/sldns/rrdef.c b/sldns/rrdef.c new file mode 100644 index 000000000..72161d7b6 --- /dev/null +++ b/sldns/rrdef.c @@ -0,0 +1,734 @@ +/* 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; +} diff --git a/sldns/rrdef.h b/sldns/rrdef.h new file mode 100644 index 000000000..933bcdfbf --- /dev/null +++ b/sldns/rrdef.h @@ -0,0 +1,503 @@ +/* + * 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 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 */ diff --git a/sldns/sbuffer.c b/sldns/sbuffer.c new file mode 100644 index 000000000..a7fe53aa0 --- /dev/null +++ b/sldns/sbuffer.c @@ -0,0 +1,178 @@ +/* + * 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 + +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); +} diff --git a/sldns/sbuffer.h b/sldns/sbuffer.h new file mode 100644 index 000000000..3ce874fc7 --- /dev/null +++ b/sldns/sbuffer.h @@ -0,0 +1,706 @@ +/* + * 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 */ diff --git a/sldns/str2wire.c b/sldns/str2wire.c new file mode 100644 index 000000000..8cda8c750 --- /dev/null +++ b/sldns/str2wire.c @@ -0,0 +1,2023 @@ +/** + * 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 +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + +/** return an error */ +#define RET_ERR(e, off) ((int)((e)|((off)< 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] */ + 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 . */ +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; iid); + } 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 "[.][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; +} diff --git a/sldns/str2wire.h b/sldns/str2wire.h new file mode 100644 index 000000000..527074a15 --- /dev/null +++ b/sldns/str2wire.h @@ -0,0 +1,541 @@ +/** + * 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 + +#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 */ diff --git a/sldns/wire2str.c b/sldns/wire2str.c new file mode 100644 index 000000000..cec3bc7b0 --- /dev/null +++ b/sldns/wire2str.c @@ -0,0 +1,1967 @@ +/* + * 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 +#endif +#include +#include +#include +#ifdef HAVE_NETDB_H +#include +#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>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 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 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>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. ? */ + if(exponent < 2) { + if(exponent == 1) + mantissa *= 10; + return sldns_str_print(str, sl, "0.%02ld", (long)mantissa); + } + /* always */ + w += sldns_str_print(str, sl, "%d", (int)mantissa); + for(i=0; i 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; iname) + 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; iname) + 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 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; +} diff --git a/sldns/wire2str.h b/sldns/wire2str.h new file mode 100644 index 000000000..67f543566 --- /dev/null +++ b/sldns/wire2str.h @@ -0,0 +1,984 @@ +/** + * 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 */ diff --git a/smallapp/unbound-control-setup.sh b/smallapp/unbound-control-setup.sh.in old mode 100755 new mode 100644 similarity index 99% rename from smallapp/unbound-control-setup.sh rename to smallapp/unbound-control-setup.sh.in index 29e4c1cd0..682ab260a --- a/smallapp/unbound-control-setup.sh +++ b/smallapp/unbound-control-setup.sh.in @@ -36,7 +36,7 @@ # settings: # directory for files -DESTDIR=/usr/local/etc/unbound +DESTDIR=@ub_conf_dir@ # issuer and subject name for certificates SERVERNAME=unbound diff --git a/testcode/run_vm.sh b/testcode/run_vm.sh new file mode 100644 index 000000000..78649f07a --- /dev/null +++ b/testcode/run_vm.sh @@ -0,0 +1,78 @@ +#!/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 .. diff --git a/testdata/ctrl_pipe.tpkg b/testdata/ctrl_pipe.tpkg new file mode 100644 index 000000000..877fcf901 Binary files /dev/null and b/testdata/ctrl_pipe.tpkg differ diff --git a/testdata/dlv_remove.rpl b/testdata/dlv_remove.rpl new file mode 100644 index 000000000..1b8b642d8 --- /dev/null +++ b/testdata/dlv_remove.rpl @@ -0,0 +1,197 @@ +; 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 diff --git a/testdata/dlv_remove_empty.rpl b/testdata/dlv_remove_empty.rpl new file mode 100644 index 000000000..30afceda0 --- /dev/null +++ b/testdata/dlv_remove_empty.rpl @@ -0,0 +1,270 @@ +; 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 diff --git a/testdata/dlv_remove_nodel.rpl b/testdata/dlv_remove_nodel.rpl new file mode 100644 index 000000000..799e841e8 --- /dev/null +++ b/testdata/dlv_remove_nodel.rpl @@ -0,0 +1,274 @@ +; 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 diff --git a/testdata/dlv_remove_pos.rpl b/testdata/dlv_remove_pos.rpl new file mode 100644 index 000000000..de7da4473 --- /dev/null +++ b/testdata/dlv_remove_pos.rpl @@ -0,0 +1,163 @@ +; 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 diff --git a/testdata/dns64_lookup.rpl b/testdata/dns64_lookup.rpl new file mode 100644 index 000000000..5d4a63b3e --- /dev/null +++ b/testdata/dns64_lookup.rpl @@ -0,0 +1,211 @@ +; 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 diff --git a/testdata/fwd_capsid_strip.tpkg b/testdata/fwd_capsid_strip.tpkg new file mode 100644 index 000000000..c0be8a3c5 Binary files /dev/null and b/testdata/fwd_capsid_strip.tpkg differ diff --git a/testdata/val_spurious_ns.rpl b/testdata/val_spurious_ns.rpl new file mode 100644 index 000000000..741fd1aff --- /dev/null +++ b/testdata/val_spurious_ns.rpl @@ -0,0 +1,151 @@ +; 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 diff --git a/testdata/val_ta_algo_dnskey_dp.rpl b/testdata/val_ta_algo_dnskey_dp.rpl new file mode 100644 index 000000000..b23c0f1b0 --- /dev/null +++ b/testdata/val_ta_algo_dnskey_dp.rpl @@ -0,0 +1,182 @@ +; 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 diff --git a/testdata/val_ta_algo_missing_dp.rpl b/testdata/val_ta_algo_missing_dp.rpl new file mode 100644 index 000000000..2cf0556f5 --- /dev/null +++ b/testdata/val_ta_algo_missing_dp.rpl @@ -0,0 +1,185 @@ +; 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