Initial vendor import of ldns-1.6.4 into contrib.
authorJan Lentfer <lentferj@df64devel.lan.net>
Tue, 9 Mar 2010 20:42:10 +0000 (21:42 +0100)
committerJan Lentfer <lentferj@atom.lan.net>
Sun, 6 Jun 2010 07:39:51 +0000 (09:39 +0200)
96 files changed:
contrib/ldns/Changelog [new file with mode: 0644]
contrib/ldns/LICENSE [new file with mode: 0644]
contrib/ldns/README [new file with mode: 0644]
contrib/ldns/README.DELETED [new file with mode: 0644]
contrib/ldns/README.DRAGONFLY [new file with mode: 0644]
contrib/ldns/README.snapshots [new file with mode: 0644]
contrib/ldns/README.svn [new file with mode: 0644]
contrib/ldns/buffer.c [new file with mode: 0644]
contrib/ldns/compat/b32_ntop.c [new file with mode: 0644]
contrib/ldns/compat/b32_pton.c [new file with mode: 0644]
contrib/ldns/compat/b64_ntop.c [new file with mode: 0644]
contrib/ldns/compat/b64_pton.c [new file with mode: 0644]
contrib/ldns/compat/ctime_r.c [new file with mode: 0644]
contrib/ldns/compat/fake-rfc2553.c [new file with mode: 0644]
contrib/ldns/compat/fake-rfc2553.h [new file with mode: 0644]
contrib/ldns/compat/gmtime_r.c [new file with mode: 0644]
contrib/ldns/compat/inet_aton.c [new file with mode: 0644]
contrib/ldns/compat/inet_ntop.c [new file with mode: 0644]
contrib/ldns/compat/inet_pton.c [new file with mode: 0644]
contrib/ldns/compat/isblank.c [new file with mode: 0644]
contrib/ldns/compat/malloc.c [new file with mode: 0644]
contrib/ldns/compat/memmove.c [new file with mode: 0644]
contrib/ldns/compat/realloc.c [new file with mode: 0644]
contrib/ldns/compat/snprintf.c [new file with mode: 0644]
contrib/ldns/compat/strlcpy.c [new file with mode: 0644]
contrib/ldns/compat/timegm.c [new file with mode: 0644]
contrib/ldns/dname.c [new file with mode: 0644]
contrib/ldns/dnssec.c [new file with mode: 0644]
contrib/ldns/dnssec_sign.c [new file with mode: 0644]
contrib/ldns/dnssec_verify.c [new file with mode: 0644]
contrib/ldns/dnssec_zone.c [new file with mode: 0644]
contrib/ldns/drill/ChangeLog.22-nov-2005 [new file with mode: 0644]
contrib/ldns/drill/README [new file with mode: 0644]
contrib/ldns/drill/REGRESSIONS [new file with mode: 0644]
contrib/ldns/drill/chasetrace.c [new file with mode: 0644]
contrib/ldns/drill/dnssec.c [new file with mode: 0644]
contrib/ldns/drill/drill.1 [new file with mode: 0644]
contrib/ldns/drill/drill.c [new file with mode: 0644]
contrib/ldns/drill/drill_util.c [new file with mode: 0644]
contrib/ldns/drill/drill_util.h [new file with mode: 0644]
contrib/ldns/drill/error.c [new file with mode: 0644]
contrib/ldns/drill/root.c [new file with mode: 0644]
contrib/ldns/drill/securetrace.c [new file with mode: 0644]
contrib/ldns/drill/work.c [new file with mode: 0644]
contrib/ldns/error.c [new file with mode: 0644]
contrib/ldns/higher.c [new file with mode: 0644]
contrib/ldns/host2str.c [new file with mode: 0644]
contrib/ldns/host2wire.c [new file with mode: 0644]
contrib/ldns/keys.c [new file with mode: 0644]
contrib/ldns/ldns/buffer.h [new file with mode: 0644]
contrib/ldns/ldns/common.h [new file with mode: 0644]
contrib/ldns/ldns/config.h.in [new file with mode: 0644]
contrib/ldns/ldns/dname.h [new file with mode: 0644]
contrib/ldns/ldns/dnssec.h [new file with mode: 0644]
contrib/ldns/ldns/dnssec_sign.h [new file with mode: 0644]
contrib/ldns/ldns/dnssec_verify.h [new file with mode: 0644]
contrib/ldns/ldns/dnssec_zone.h [new file with mode: 0644]
contrib/ldns/ldns/error.h [new file with mode: 0644]
contrib/ldns/ldns/higher.h [new file with mode: 0644]
contrib/ldns/ldns/host2str.h [new file with mode: 0644]
contrib/ldns/ldns/host2wire.h [new file with mode: 0644]
contrib/ldns/ldns/keys.h [new file with mode: 0644]
contrib/ldns/ldns/ldns.h [new file with mode: 0644]
contrib/ldns/ldns/net.h.in [new file with mode: 0644]
contrib/ldns/ldns/packet.h [new file with mode: 0644]
contrib/ldns/ldns/parse.h [new file with mode: 0644]
contrib/ldns/ldns/rbtree.h [new file with mode: 0644]
contrib/ldns/ldns/rdata.h [new file with mode: 0644]
contrib/ldns/ldns/resolver.h [new file with mode: 0644]
contrib/ldns/ldns/rr.h [new file with mode: 0644]
contrib/ldns/ldns/rr_functions.h [new file with mode: 0644]
contrib/ldns/ldns/sha1.h [new file with mode: 0644]
contrib/ldns/ldns/sha2.h [new file with mode: 0644]
contrib/ldns/ldns/str2host.h [new file with mode: 0644]
contrib/ldns/ldns/tsig.h [new file with mode: 0644]
contrib/ldns/ldns/update.h [new file with mode: 0644]
contrib/ldns/ldns/util.h.in [new file with mode: 0644]
contrib/ldns/ldns/wire2host.h [new file with mode: 0644]
contrib/ldns/ldns/zone.h [new file with mode: 0644]
contrib/ldns/linktest.c [new file with mode: 0644]
contrib/ldns/net.c [new file with mode: 0644]
contrib/ldns/packet.c [new file with mode: 0644]
contrib/ldns/parse.c [new file with mode: 0644]
contrib/ldns/rbtree.c [new file with mode: 0644]
contrib/ldns/rdata.c [new file with mode: 0644]
contrib/ldns/resolver.c [new file with mode: 0644]
contrib/ldns/rr.c [new file with mode: 0644]
contrib/ldns/rr_functions.c [new file with mode: 0644]
contrib/ldns/sha1.c [new file with mode: 0644]
contrib/ldns/sha2.c [new file with mode: 0644]
contrib/ldns/str2host.c [new file with mode: 0644]
contrib/ldns/tsig.c [new file with mode: 0644]
contrib/ldns/update.c [new file with mode: 0644]
contrib/ldns/util.c [new file with mode: 0644]
contrib/ldns/wire2host.c [new file with mode: 0644]
contrib/ldns/zone.c [new file with mode: 0644]

diff --git a/contrib/ldns/Changelog b/contrib/ldns/Changelog
new file mode 100644 (file)
index 0000000..5ad466a
--- /dev/null
@@ -0,0 +1,467 @@
+1.6.4  2010-01-20
+       * Imported pyldns contribution by Zdenek Vasicek and Karel Slany.
+         Changed its configure and Makefile to fit into ldns.
+         Added its dname_* methods to the rdf_* class (as is the ldns API).
+         Changed swig destroy of ldns_buffer class to ldns_buffer_free.
+         Declared ldns_pkt_all and ldns_pkt_all_noquestion so swig sees them.
+       * Bugfix: parse PTR target of .tomhendrikx.nl with error not crash.
+       * Bugfix: handle escaped characters in TXT rdata.
+       * bug292: no longer crash on malformed domain names where a label is
+         on position 255, which was a buffer overflow by one.
+       * Fix ldns_get_rr_list_hosts_frm_fp_l (strncpy to strlcpy change),
+         which fixes resolv.conf reading badly terminated string buffers.
+       * Fix ldns_pkt_set_random_id to be more random, and a little faster,
+         it did not do value 0 statistically correctly.
+       * Fix ldns_rdf2native_sockaddr_storage to set sockaddr type to zeroes,
+         for portability.
+       * bug295: nsec3-hash routine no longer case sensitive.
+       * bug298: drill failed nsec3 denial of existence proof.
+
+1.6.3  2009-12-04
+       * Bugfix: allow for unknown resource records in zonefile with rdlen=0.
+       * Bugfix: also mark an RR as question if it comes from the wire
+       * Bugfix: NSEC3 bitmap contained NSEC
+       * Bugfix: Inherit class when creating signatures
+
+1.6.2  2009-11-12
+       * Fix Makefile patch from Havard Eidnes, better install.sh usage.
+       * Fix parse error on SOA serial of 2910532839.
+         Fix print of ';' and readback of '\;' in names, also for '\\'.
+         Fix parse of '\(' and '\)' in names.  Also for file read. Also '\.'
+       * Fix signature creation when TTLs are different for RRs in RRset.
+       * bug273: fix so EDNS rdata is included in pkt to wire conversion.
+       * bug274: fix use of c++ keyword 'class' for RR class in the code.
+       * bug275: fix memory leak of packet edns rdata.
+       * Fix timeout procedure for TCP and AXFR on Solaris.
+       * Fix occasional NSEC bitmap bogus
+       * Fix rr comparing (was in reversed order since 1.6.0)
+       * bug278: fix parsing HINFO rdata (and other cases).
+       * Fix previous owner name: also pick up if owner name is @.
+       * RFC5702: enabled sha2 functions by default. This requires OpenSSL 0.9.8 or higher.
+      Reason for this default is the root to be signed with RSASHA256.
+       * Fix various LDNS RR parsing issues: IPSECKEY, WKS, NSAP, very long lines
+       * Fix: Make ldns_dname_is_subdomain case insensitive.
+       * Fix ldns-verify-zone so that address records at zone NS set are not considered glue
+               (Or glue records fall below delegation)
+    * Fix LOC RR altitude printing.
+       * Feature: Added period (e.g. '3m6d') support at explicit TTLs.
+    * Feature: DNSKEY rrset by default signed with minimal signatures
+               but -A option for ldns-signzone to sign it with all keys.
+               This makes the DNSKEY responses smaller for signed domains.
+
+1.6.1   2009-09-14
+       * --enable-gost : use the GOST algorithm (experimental).
+       * Added some missing options to drill manpage
+       * Some fixes to --without-ssl option
+       * Fixed quote parsing withing strings
+       * Bitmask fix in EDNS handling
+       * Fixed non-fqdn domain name completion for rdata field domain
+         names of length 1
+       * Fixed chain validation with SHA256 DS records
+
+1.6.0
+       Additions:
+       * Addition of an ldns-config script which gives cflags and libs
+         values, for use in configure scripts for applications that use
+         use ldns. Can be disabled with ./configure --disable-ldns-config
+       * Added direct sha1, sha256, and sha512 support in ldns.
+         With these functions, all NSEC3 functionality can still be
+         used, even if ldns is built without OpenSSL. Thanks to OpenBSD,
+         Steve Reid, and Aaron D. Gifford for the code.
+       * Added reading/writing support for the SPF Resource Record
+       * Base32 functions are now exported
+       Bugfixes:
+       * ldns_is_rrset did not go through the complete rrset, but
+         only compared the first two records. Thanks to Olafur
+         Gudmundsson for report and patch
+       * Fixed a small memory bug in ldns_rr_list_subtype_by_rdf(),
+         thanks to Marius Rieder for finding an patching this.
+       * --without-ssl should now work. Make sure that examples/ and
+         drill also get the --without-ssl flag on their configure, if
+         this is used.
+       * Some malloc() return value checks have been added
+       * NSEC3 creation has been improved wrt to empty nonterminals,
+         and opt-out.
+       * Fixed a bug in the parser when reading large NSEC3 salt
+         values.
+       * Made the allowed length for domain names on wire
+         and presentation format the same.
+       Example tools:
+       * ldns-key2ds can now also generate DS records for keys without
+         the SEP flag
+       * ldns-signzone now equalizes the TTL of the DNSKEY RRset (to
+         the first non-default DNSKEY TTL value it sees)
+       
+1.5.1
+       Example tools:
+       * ldns-signzone was broken in 1.5.0 for multiple keys, this
+          has been repaired
+
+       Build system:
+        * Removed a small erroneous output warning in
+          examples/configure and drill/configure
+
+1.5.0
+       Bug fixes:
+       * fixed a possible memory overflow in the RR parser
+       * build flag fix for Sun Studio
+       * fixed a building race condition in the copying of header
+         files
+       * EDNS0 extended rcode; the correct assembled code number
+         is now printed (still in the EDNS0 field, though)
+       * ldns_pkt_rr no longer leaks memory (in fact, it no longer
+         copies anything all)
+
+       API addition:
+       * ldns_key now has support for 'external' data, in which
+         case the OpenSSL EVP structures are not used;
+         ldns_key_set_external_key() and ldns_key_external_key()
+       * added ldns_key_get_file_base_name() which creates a 
+         'default' filename base string for key storage, of the
+         form "K<zone>+<algorithm>+<keytag>"
+       * the ldns_dnssec_* family of structures now have deep_free()
+         functions, which also free the ldns_rr's contained in them
+       * there is now an ldns_match_wildcard() function, which checks
+         whether a domain name matches a wildcard name
+       * ldns_sign_public has been split up; this resulted in the
+         addition of ldns_create_empty_rrsig() and
+         ldns_sign_public_buffer()
+
+       Examples:
+       * ldns-signzone can now automatically add DNSKEY records when
+         using an OpenSSL engine, as it already did when using key
+         files
+       * added new example tool: ldns-nsec3-hash
+       * ldns-dpa can now filter on specific query name and types
+       * ldnsd has fixes for the zone name, a fix for the return
+          value of recvfrom(), and an memory initialization fix
+          (Thanks to Colm MacCárthaigh for the patch)
+        * Fixed memory leaks in ldnsd
+
+
+
+1.4.1
+       Bug fixes:
+       * fixed a build issue where ldns lib existence was done too early
+       * removed unnecessary check for pcap.h
+       * NSEC3 optout flag now correctly printed in string output
+       * inttypes.h moved to configured inclusion
+       * fixed NSEC3 type bitmaps for empty nonterminals and unsigned
+         delegations 
+
+       API addition:
+       * for that last fix, we added a new function
+         ldns_dname_add_from() that can clone parts of a dname
+       
+1.4.0
+       Bug fixes:
+       * sig chase return code fix (patch from Rafael Justo, bug id 189)
+       * rdata.c memory leaks on error and allocation checks fixed (patch
+         from Shane Kerr, bug id 188)
+       * zone.c memory leaks on error and allocation checks fixed (patch
+       from Shane Kerr, bug id 189)
+       * ldns-zplit output and error messages fixed (patch from Shane Kerr,
+         bug id 190)
+       * Fixed potential buffer overflow in ldns_str2rdf_dname
+       * Signing code no longer signs delegation NS rrsets
+       * Some minor configure/makefile updates
+       * Fixed a bug in the randomness initialization
+       * Fixed a bug in the reading of resolv.conf
+       * Fixed a bug concerning whitespace in zone data (with patch from Ondrej
+         Sury, bug 213)
+       * Fixed a small fallback problem in axfr client code
+       
+       API CHANGES:
+       * added 2str convenience functions:
+               - ldns_rr_type2str
+               - ldns_rr_class2str
+               - ldns_rr_type2buffer_str
+               - ldns_rr_class2buffer_str
+       * buffer2str() is now called ldns_buffer2str
+       * base32 and base64 function names are now also prepended with ldns_
+       * ldns_rr_new_frm_str() now returns an error on missing RDATA fields.
+         Since you cannot read QUESTION section RRs with this anymore,
+         there is now a function called ldns_rr_new_question_frm_str()
+
+       LIBRARY FEATURES:
+       * DS RRs string representation now add bubblebabble in a comment
+         (patch from Jakob Schlyter)
+       * DLV RR type added
+       * TCP fallback system has been improved
+       * HMAC-SHA256 TSIG support has been added.
+       * TTLS are now correcly set in NSEC(3) records when signing zones
+       
+       EXAMPLE TOOLS:
+       * New example: ldns-revoke to revoke DNSKEYs according to RFC5011
+       * ldns-testpkts has been fixed and updated
+       * ldns-signzone now has the option to not add the DNSKEY
+       * ldns-signzone now has an (full zone only) opt-out option for
+                       NSEC3
+       * ldns-keygen can create HMAC-SHA1 and HMAC-SHA256 symmetric keys
+       * ldns-walk output has been fixed
+       * ldns-compare-zones has been fixed, and now has an option
+         to show all differences (-a)
+       * ldns-read-zone now has an option to print DNSSEC records only
+
+1.3
+       Base library:
+
+       * Added a new family of functions based around ldns_dnssec_zone,
+       which is a new structure that keeps a zone sorted through an
+       rbtree and links signatures and NSEC(3) records directly to their
+       RRset. These functions all start with ldns_dnssec_
+
+       * ldns_zone_sign and ldns_zone_sign_nsec3 are now deprecated, but
+       have been changed to internally use the new
+       ldns_dnssec_zone_sign(_nsec3)
+
+       * Moved some ldns_buffer functions inline, so a clean rebuild of
+       applications relying on those is needed (otherwise you'll get
+       linker errors)
+       * ldns_dname_label now returns one extra (zero)
+       byte, so it can be seen as an fqdn.
+       * NSEC3 type code update for signing algorithms.
+       * DSA key generation of DNSKEY RRs fixed (one byte too small).
+
+       * Added support for RSA/SHA256 and RSA/SHA512, as specified in
+       draft-ietf-dnsext-dnssec-rsasha256-04. The typecodes are not
+       final, and this feature is not enabled by default. It can be
+       enabled at compilation time with the flag --with-sha2
+
+       * Added 2wire_canonical family of functions that lowercase dnames
+       in rdata fields in resource records of the types in the list in
+       rfc3597
+
+       * Added base32 conversion functions.
+
+       * Fixed DSA RRSIG conversion when calling OpenSSL
+
+       Drill:
+
+       * Chase output is completely different, it shows, in ascii, the
+       relations in the trust hierarchy.
+
+       Examples:
+       * Added ldns-verify-zone, that can verify the internal DNSSEC records
+       of a signed BIND-style zone file
+
+       * ldns-keygen now takes an -a argument specifying the algorithm,
+       instead of -R or -D. -a list show a list of supported algorithms
+
+       * ldns-keygen now defaults to the exponent RSA_F4 instead of RSA_3
+       for RSA key generation
+
+       * ldns-signzone now has support for HSMs
+       * ldns-signzone uses the new ldns_dnssec_ structures and functions
+       which improves its speed, and output; RRSIGS are now placed
+       directly after their RRset, NSEC(3) records directly after the
+       name they handle
+
+       Contrib:
+       * new contrib/ dir with user contributions
+       * added compilation script for solaris (thanks to Jakob Schlyter)
+       
+28 Nov 2007 1.2.2:
+       * Added support for HMAC-MD5 keys in generator
+       * Added a new example tool (written by Ondrej Sury): ldns-compare-zones
+       * ldns-keygen now checks key sizes for rfc conformancy
+       * ldns-signzone outputs SSL error if present
+       * Fixed manpages (thanks to Ondrej Sury)
+       * Fixed Makefile for -j <x>
+       * Fixed a $ORIGIN error when reading zones
+       * Fixed another off-by-one error
+
+03 Oct 2007 1.2.1:
+       * Fixed an offset error in rr comparison
+       * Fixed ldns-read-zone exit code
+       * Added check for availability of SHA256 hashing algorithm
+       * Fixed ldns-key2ds -2 argument
+       * Fixed $ORIGIN bug in .key files
+       * Output algorithms as an integer instead of their mnemonic
+       * Fixed a memory leak in dnssec code when SHA256 is not available
+       * Updated fedora .spec file
+
+11 Apr 2007 1.2.0:
+       * canonicalization of rdata in DNSSEC functions now adheres to the
+          rr type list in rfc3597, not rfc4035, which will be updated
+         (see http://www.ops.ietf.org/lists/namedroppers/namedroppers.2007/msg00183.html)
+       * ldns-walk now support dnames with maximum label length
+       * ldnsd now takes an extra argument containing the address to listen on
+       * signing no longer signs every rrset with KSK's, but only the DNSKEY rrset
+       * ported to Solaris 10
+       * added ldns_send_buffer() function
+       * added ldns-testpkts fake packet server
+       * added ldns-notify to send NOTIFY packets
+       * ldns-dpa can now accurately calculate the number of matches per
+         second
+       * libtool is now used for compilation too (still gcc, but not directly)
+       * Bugfixes:
+               - TSIG signing buffer size
+               - resolv.conf reading (comments)
+               - dname comparison off by one error
+               - typo in keyfetchers output file name fixed (a . too much)
+               - fixed zone file parser when comments contain ( or )
+               - fixed LOC RR type
+               - fixed CERT RR type
+
+       Drill:
+       * drill prints error on failed axfr.
+       * drill now accepts mangled packets with -f
+       * old -c option (use tcp) changed to -t
+       * -c option to specify alternative resolv.conf file added
+       * feedback of signature chase improved
+       * chaser now stops at root when no trusted keys are found
+         instead of looping forever trying to find the DS for .
+       * Fixed bugs:
+               - wildcard on multiple labels signature verification
+               - error in -f packet writing for malformed packets
+               - made KSK check more resilient
+
+7 Jul 2006: 1.1.0: ldns-team
+       * Added tutorials and an introduction to the documentation
+       * Added include/ and lib/ dirs so that you can compile against ldns
+         without installing ldns on your system
+       * Makefile updates
+       * Starting usage of assert throughout the library to catch illegal calls
+       * Solaris 9 testing was carried out. Ldns now compiles on that
+         platform; some gnuism were identified and fixed.
+       * The ldns_zone structure was stress tested. The current setup
+        (ie. just a list of rrs) can scale to zone file in order of
+         megabytes. Sorting such zone is still difficult.
+       * Reading multiline b64 encoded rdata works.
+       * OpenSSL was made optional, configure --without-ssl.
+         Ofcourse all dnssec/tsig related functions are disabled
+       * Building of examples and drill now happens with the same
+         defines as the building of ldns itself.
+       * Preliminary sha-256 support was added. Currently is your
+         OpenSSL supports it, it is supported in the DS creation.
+       * ldns_resolver_search was implemented
+       * Fixed a lot of bugs
+
+       Drill:
+       * -r was killed in favor of -o <header bit mnemonic> which 
+         allows for a header bits setting (and maybe more in the
+         future)
+       * DNSSEC is never automaticaly set, even when you query
+         for DNSKEY/RRSIG or DS.
+       * Implement a crude RTT check, it now distinguishes between
+         reachable and unreachable.
+        * A form of secure tracing was added
+        * Secure Chasing has been improved
+       * -x does a reverse lookup for the given IP address
+       
+       Examples:
+       * ldns-dpa was added to the examples - this is the Dns Packet
+         Analyzer tool.
+       * ldnsd - as very, very simple nameserver impl.
+       * ldns-zsplit - split zones for parrallel signing
+       * ldns-zcat - cat split zones back together
+        * ldns-keyfetcher - Fetches DNSKEY records with a few (non-strong, 
+         non-DNSSEC) anti-spoofing techniques.
+       * ldns-walk - 'Walks' a DNSSEC signed zone
+       * Added an all-static target to the makefile so you can use examples
+         without installing the library
+       * When building in the source tree or in a direct subdirectory of
+         the build dir, configure does not need --with-ldns=../ anymore
+
+       Code:
+       * All networking code was moved to net.c
+       * rdata.c: added asserts to the rdf set/get functions
+       * const keyword was added to pointer arguments that 
+         aren't changed
+
+       API:
+       Changed:
+       * renamed ldns/dns.h to ldns/ldns.h
+       * ldns_rr_new_frm_str() is extented with an extra variable which
+         in common use may be NULL. This trickles through to:
+          o ldns_rr_new_frm_fp
+         o ldns_rr_new_frm_fp_l
+         Which also get an extra variable
+         Also the function has been changed to return a status message.
+         The compiled RR is returned in the first argument.
+       * ldns_zone_new_frm_fp_l()  and ldns_zone_new_frm_fp() are
+          changed to return a status msg.
+       * ldns_key_new_frm_fp is changed to return ldns_status and
+         the actual key list in the first argument
+       * ldns_rdata_new_frm_fp[_l]() are changed to return a status.
+         the rdf is return in the first argument
+        * ldns_resolver_new_frm_fp: same treatment: return status and 
+         the new resolver in the first argument
+       * ldns_pkt_query_new_frm_str(): same: return status and the
+         packet in the first arg
+       * tsig.h: internal used functions are now static:
+         ldns_digest_name and ldns_tsig_mac_new
+       * ldns_key_rr2ds has an extra argument to specify the hash to
+         use.
+       * ldns_pkt_rcode() is renamed to ldns_pkt_get_rcode, ldns_pkt_rcode
+         is now the rcode type, like ldns_pkt_opcode
+       New:
+       * ldns_resolver_searchlist_count: return the searchlist counter
+       * ldns_zone_sort: Sort a zone
+       * ldns_bgsend(): background send, returns a socket.
+       * ldns_pkt_empty(): check is a packet is empty
+       * ldns_rr_list_pop_rr_list(): pop multiple rr's from another rr_list
+       * ldns_rr_list_push_rr_list(): push multiple rr's to an rr_list
+        * ldns_rr_list_compare(): compare 2 ldns_rr_lists
+       * ldns_pkt_push_rr_list: rr_list equiv for rr
+       * ldns_pkt_safe_push_rr_list: rr_list equiv for rr
+       Removed:
+       * ldns_resolver_bgsend(): was not used in 1.0.0 and is not used now
+       * ldns_udp_server_connect(): was faulty and isn't really part of
+         the core ldns idea any how.
+       * ldns_rr_list_insert_rr(): obsoleted, because not used.
+       * char *_when was removed from the ldns_pkt structure
+
+18 Oct 2005: 1.0.0: ldns-team
+       * Commited a patch from Håkan Olsson
+       * Added UPDATE support (Jakob Schlyter and Håkan Olsson)
+       * License change: ldns is now BSD licensed
+       * ldns now depends on SSL
+       * Networking code cleanup, added (some) server udp/tcp support
+       * A zone type is introduced. Currently this is a list
+         of RRs, so it will not scale well.
+       * [beta] Zonefile parsing was added
+       * [tools] Drill was added to ldns - see drill/
+       * [tools] experimental signer was added
+       * [building] better check for ssl
+       * [building] major revision of build system
+       * [building] added rpm .spec in packaging/ (thanks to Paul Wouters)
+       * [building] A lot of cleanup in the build scripts (thanks to Jakob Schlyter
+       and Paul Wouters)
+
+28 Jul 2005: 0.70: ldns-team
+       * [func] ldns_pkt_get_section now returns copies from the rrlists
+         in the packet. This can be freed by the user program
+       * [code] added ldns_ prefixes to function from util.h
+       * [inst] removed documentation from default make install
+       * Usual fixes in documentation and code
+
+20 Jun 2005: 0.66: ldns-team
+       Rel. Focus: drill-pre2 uses some functions which are
+       not in 0.65
+       * dnssec_cd bit function was added
+       * Zone infrastructure was added
+       * Usual fixes in documentation and code
+
+13 Jun 2005: 0.65: ldns-team
+       * Repository is online at: 
+         http://www.nlnetlabs.nl/ldns/svn/
+       * Apply reference copying throuhgout ldns, except in 2 
+         places in the ldns_resolver structure (._domain and
+        ._nameservers)
+       * Usual array of bugfixes
+       * Documentation added
+       * keygen.c added as an example for DNSSEC programming
+
+23 May 2005: 0.60: ldns-team
+       * Removed config.h from the header installed files
+         (you're not supposed to include that in a libary)
+       * Further tweaking
+         - DNSSEC signing/verification works
+         - Assorted bug fixes and tweaks (memory management) 
+
+May 2005: 0.50: ldns-team
+       * First usable release
+       * Basic DNS functionality works
+       * DNSSEC validation works
diff --git a/contrib/ldns/LICENSE b/contrib/ldns/LICENSE
new file mode 100644 (file)
index 0000000..6d4c6be
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2005,2006, NLnetLabs
+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 NLnetLabs 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.
diff --git a/contrib/ldns/README b/contrib/ldns/README
new file mode 100644 (file)
index 0000000..3a93c41
--- /dev/null
@@ -0,0 +1,103 @@
+
+Contents: 
+       REQUIREMENTS
+       INSTALLATION
+               libdns
+               examples
+               drill
+       INFORMATION FOR SPECIFIC OPERATING SYSTEMS
+               Mac OS X
+               Solaris
+
+Project page:
+http://www.nlnetlabs.nl/ldns/
+On that page you can also subscribe to the ldns mailing list.
+
+* Development 
+ldns is mainly developed on Linux and FreeBSD. It is regularly tested to
+compile on other systems like Solaris and Mac OS X.
+
+REQUIREMENTS
+- OpenSSL (Optional, but needed for features like DNSSEC)
+- libpcap (Optional, but needed for examples/ldns-dpa)
+- (GNU) libtool (in OSX, that's glibtool, not libtool)
+- GNU make
+
+INSTALLATION
+1. Unpack the tarball
+2. cd ldns-<VERSION>
+3. ./configure
+4. gmake (it needs gnu make to compile, on systems where GNU make is the
+   default you can just use 'make')
+5. sudo gmake install
+6. Optional. (cd examples; ./configure; gmake), make example programs included.
+7. Optional. (cd drill; ./configure; gmake; gmake install), to build drill.
+
+You can configure and compile it in a separate build directory.
+
+* Examples
+There are some examples and dns related tools in the examples/ directory.
+These can be built with:
+1. cd examples/
+2. ./configure [--with-ldns=<path to ldns installation or build>]
+3. gmake
+
+* Drill
+Drill can be built with:
+1. cd drill/
+2. ./configure [--with-ldns=<path to ldns installation or build>]
+3. gmake
+
+Note that you need to set LD_LIBRARY_PATH if you want to run the binaries
+and you have not installed the library to a system directory. You can use
+the make target all-static for the examples to run them if you don't want to
+install the library.
+
+
+* Building from subversion repository
+
+If you are building from the repository you will need to have (gnu)
+autotools like libtool and autoreconf installed. A list of all the commands
+needed to build everything can be found in README.svn. Note that the actual
+commands may be a little bit different on your machine. Most notable, you'll need to run libtoolize (or glibtoolize), if you skip this step, you'll get an error about missing config.sub.
+
+* Developers
+ldns is developed by the ldns team at NLnet Labs. This team currently
+consists of:
+  o Jelte Jansen
+  o Wouter Wijngaards
+
+Former main developers:
+  o Miek Gieben
+
+* Credits
+We have received patches from the following people, thanks!
+  o Erik Rozendaal
+  o Håkan Olsson
+  o Jakob Schlyter
+  o Paul Wouters
+  o Simon Vallet
+  o Ondřej Surý
+
+
+IFORMATION FOR SPECIFIC OPERATING SYSTEMS
+
+MAC OS X
+
+For MACOSX 10.4 and later, it seems that you have to set the
+MACOSX_DEPLOYMENT_TARGET environment variable to 10.4 before running
+make. Apparently it defaults to 10.1.
+
+This appears to be a known problem in 10.2 to 10.4, see:
+http://developer.apple.com/qa/qa2001/qa1233.html
+for more information.
+
+
+SOLARIS
+
+In Solaris multi-architecture systems (that have both 32-bit and
+64-bit support), it can be a bit taxing to convince the system to
+compile in 64-bit mode. Jakob Schlyter has kindly contributed a build
+script that sets the right build and link options. You can find it in
+contrib/build-solaris.sh
+
diff --git a/contrib/ldns/README.DELETED b/contrib/ldns/README.DELETED
new file mode 100644 (file)
index 0000000..142e158
--- /dev/null
@@ -0,0 +1,24 @@
+Makefile.in
+ac_pkg_swig.m4
+aclocal.m4
+acx_nlnetlabs.m4
+acx_python.m4
+config.guess
+config.sub
+configure
+configure.ac
+contrib/
+doc/
+drill/Makefile.in
+drill/config.h.in
+drill/configure
+drill/configure.ac
+drill/drill.h.in
+drill/install-sh
+examples/
+install-sh
+ldns_symbols.def
+libdns.doxygen
+libdns.vim
+ltmain.sh
+packaging/
diff --git a/contrib/ldns/README.DRAGONFLY b/contrib/ldns/README.DRAGONFLY
new file mode 100644 (file)
index 0000000..2d896ef
--- /dev/null
@@ -0,0 +1,9 @@
+Original source can be downloaded from:
+http://www.nlnetlabs.nl/projects/ldns/
+
+    MD5 (ldns-1.6.4.tar.gz) = 6747d7bd96552ee5d8943f3abb24815f
+    SHA1 (ldns-1.6.4.tar.gz) = 9015968ad3ddd015c750c15b60e60b9cccd393ec
+
+A list of deleted files is in README.DELETED.
+
+When Upgrading please stick to development(7).
diff --git a/contrib/ldns/README.snapshots b/contrib/ldns/README.snapshots
new file mode 100644 (file)
index 0000000..891fcca
--- /dev/null
@@ -0,0 +1,8 @@
+ldns - snapshot releases
+
+Snapshot releases are not official released. They can be released to
+interested parties for development.
+
+Snapshots can be recognized from the date in the the tar file name.
+
+They should not be used for packaging in distributions.
diff --git a/contrib/ldns/README.svn b/contrib/ldns/README.svn
new file mode 100644 (file)
index 0000000..10f7cb4
--- /dev/null
@@ -0,0 +1,26 @@
+
+# The ldns subversion repository can found at:
+# www.nlnetlabs.nl/ldns/svn/
+
+# small list of commands to build all on a linux system
+# libtoolize is needed for most other targets
+
+# on Solaris, and other systems that may not have
+# the default 'automake' and 'aclocal' script aliases,
+# the correct versions may need to be set. On those
+# systems, the 'autoreconf' line should be changed to:
+# AUTOMAKE=automake-1.10 ACLOCAL=aclocal-1.10 autoreconf
+# (and these systems probably need gmake instead of make)
+
+# older versions of libtoolize do not support --install
+# so you might need to remove that (with newer versions
+# it is needed)
+libtoolize -c --install
+autoreconf --install
+./configure
+make
+make doc  # needs doxygen for the html pages
+(cd examples && autoreconf && ./configure && make)
+(cd drill && autoreconf && ./configure && make)
+(cd pcat && autoreconf && ./configure && make)
+(cd examples/nsd-test && autoreconf && ./configure && make)
diff --git a/contrib/ldns/buffer.c b/contrib/ldns/buffer.c
new file mode 100644 (file)
index 0000000..c6259b4
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * buffer.c -- generic memory buffer .
+ *
+ * Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+#include <ldns/buffer.h>
+
+ldns_buffer *
+ldns_buffer_new(size_t capacity)
+{
+       ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);
+
+       if (!buffer) {
+               return NULL;
+       }
+       
+       buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
+       if (!buffer->_data) {
+               LDNS_FREE(buffer);
+               return NULL;
+       }
+       
+       buffer->_position = 0;
+       buffer->_limit = buffer->_capacity = capacity;
+       buffer->_fixed = 0;
+       buffer->_status = LDNS_STATUS_OK;
+       
+       ldns_buffer_invariant(buffer);
+       
+       return buffer;
+}
+
+void
+ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size)
+{
+       assert(data != NULL);
+
+       buffer->_position = 0; 
+       buffer->_limit = buffer->_capacity = size;
+       buffer->_data = LDNS_XMALLOC(uint8_t, size);
+       memcpy(buffer->_data, data, size);
+       buffer->_fixed = 0;
+       buffer->_status = LDNS_STATUS_OK;
+       
+       ldns_buffer_invariant(buffer);
+}
+
+bool
+ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
+{
+       void *data;
+       
+       ldns_buffer_invariant(buffer);
+       assert(buffer->_position <= capacity);
+
+       data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
+       if (!data) {
+               buffer->_status = LDNS_STATUS_MEM_ERR;
+               return false;
+       } else {
+               buffer->_data = data;
+               buffer->_limit = buffer->_capacity = capacity;
+               return true;
+       }
+}
+
+bool
+ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
+{
+       ldns_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 (!ldns_buffer_set_capacity(buffer, new_capacity)) {
+                       buffer->_status = LDNS_STATUS_MEM_ERR;
+                       return false;
+               }
+       }
+       buffer->_limit = buffer->_capacity;
+       return true;
+}
+
+int
+ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
+{
+       va_list args;
+       int written = 0;
+       size_t remaining;
+       
+       if (ldns_buffer_status_ok(buffer)) {
+               ldns_buffer_invariant(buffer);
+               assert(buffer->_limit == buffer->_capacity);
+
+               remaining = ldns_buffer_remaining(buffer);
+               va_start(args, format);
+               written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
+                                   format, args);
+               va_end(args);
+               if (written == -1) {
+                       buffer->_status = LDNS_STATUS_INTERNAL_ERR;
+                       return -1;
+               } else if ((size_t) written >= remaining) {
+                       if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
+                               buffer->_status = LDNS_STATUS_MEM_ERR;
+                               return -1;
+                       }
+                       va_start(args, format);
+                       written = vsnprintf((char *) ldns_buffer_current(buffer),
+                           ldns_buffer_remaining(buffer), format, args);
+                       va_end(args);
+                       if (written == -1) {
+                               buffer->_status = LDNS_STATUS_INTERNAL_ERR;
+                               return -1;
+                       }
+               }
+               buffer->_position += written;
+       }
+       return written;
+}
+
+void
+ldns_buffer_free(ldns_buffer *buffer)
+{
+       if (!buffer) {
+               return;
+       }
+
+       LDNS_FREE(buffer->_data);
+
+       LDNS_FREE(buffer);
+}
+
+void *
+ldns_buffer_export(ldns_buffer *buffer)
+{
+       buffer->_fixed = 1;
+       return buffer->_data;
+}
+
+int
+ldns_bgetc(ldns_buffer *buffer)
+{
+       if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
+               ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
+               /* ldns_buffer_rewind(buffer);*/
+               return EOF;
+       }
+       return (int)ldns_buffer_read_u8(buffer);
+}
+
+void 
+ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from)
+{
+       size_t tocopy = ldns_buffer_limit(from);
+
+       if(tocopy > ldns_buffer_capacity(result))
+               tocopy = ldns_buffer_capacity(result);
+       ldns_buffer_clear(result);
+       ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
+       ldns_buffer_flip(result);
+}
diff --git a/contrib/ldns/compat/b32_ntop.c b/contrib/ldns/compat/b32_ntop.c
new file mode 100644 (file)
index 0000000..ec4104f
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <assert.h>
+
+static const char Base32[] =
+       "abcdefghijklmnopqrstuvwxyz234567";
+/*     "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";*/
+/*       00000000001111111111222222222233
+         01234567890123456789012345678901*/
+static const char Base32_extended_hex[] =
+/*     "0123456789ABCDEFGHIJKLMNOPQRSTUV";*/
+       "0123456789abcdefghijklmnopqrstuv";
+static const char Pad32 = '=';
+
+/* (From RFC3548 and draft-josefsson-rfc3548bis-00.txt)
+5.  Base 32 Encoding
+
+   The Base 32 encoding is designed to represent arbitrary sequences of
+   octets in a form that needs to be case insensitive but need not be
+   humanly readable.
+
+   A 33-character subset of US-ASCII is used, enabling 5 bits to be
+   represented per printable character.  (The extra 33rd character, "=",
+   is used to signify a special processing function.)
+
+   The encoding process represents 40-bit groups of input bits as output
+   strings of 8 encoded characters.  Proceeding from left to right, a
+   40-bit input group is formed by concatenating 5 8bit input groups.
+   These 40 bits are then treated as 8 concatenated 5-bit groups, each
+   of which is translated into a single digit in the base 32 alphabet.
+   When encoding a bit stream via the base 32 encoding, the bit stream
+   must be presumed to be ordered with the most-significant-bit first.
+   That is, the first bit in the stream will be the high-order bit in
+   the first 8bit byte, and the eighth bit will be the low-order bit in
+   the first 8bit byte, and so on.
+
+   Each 5-bit group is used as an index into an array of 32 printable
+   characters.  The character referenced by the index is placed in the
+   output string.  These characters, identified in Table 3, below, are
+   selected from US-ASCII digits and uppercase letters.
+
+                      Table 3: The Base 32 Alphabet
+
+         Value Encoding  Value Encoding  Value Encoding  Value Encoding
+             0 A             9 J            18 S            27 3
+             1 B            10 K            19 T            28 4
+             2 C            11 L            20 U            29 5
+             3 D            12 M            21 V            30 6
+             4 E            13 N            22 W            31 7
+             5 F            14 O            23 X
+             6 G            15 P            24 Y         (pad) =
+             7 H            16 Q            25 Z
+             8 I            17 R            26 2
+
+
+   Special processing is performed if fewer than 40 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a body.  When fewer than 40 input bits
+   are available in an input group, zero bits are added (on the right)
+   to form an integral number of 5-bit groups.  Padding at the end of
+   the data is performed using the "=" character.  Since all base 32
+   input is an integral number of octets, only the following cases can
+   arise:
+
+   (1) the final quantum of encoding input is an integral multiple of 40
+   bits; here, the final unit of encoded output will be an integral
+   multiple of 8 characters with no "=" padding,
+
+   (2) the final quantum of encoding input is exactly 8 bits; here, the
+   final unit of encoded output will be two characters followed by six
+   "=" padding characters,
+
+   (3) the final quantum of encoding input is exactly 16 bits; here, the
+   final unit of encoded output will be four characters followed by four
+   "=" padding characters,
+
+   (4) the final quantum of encoding input is exactly 24 bits; here, the
+   final unit of encoded output will be five characters followed by
+   three "=" padding characters, or
+
+   (5) the final quantum of encoding input is exactly 32 bits; here, the
+   final unit of encoded output will be seven characters followed by one
+   "=" padding character.
+
+
+6.  Base 32 Encoding with Extended Hex Alphabet
+
+   The following description of base 32 is due to [7].  This encoding
+   should not be regarded as the same as the "base32" encoding, and
+   should not be referred to as only "base32".
+
+   One property with this alphabet, that the base64 and base32 alphabet
+   lack, is that encoded data maintain its sort order when the encoded
+   data is compared bit-wise.
+
+   This encoding is identical to the previous one, except for the
+   alphabet.  The new alphabet is found in table 4.
+
+                     Table 4: The "Extended Hex" Base 32 Alphabet
+
+         Value Encoding  Value Encoding  Value Encoding  Value Encoding
+             0 0             9 9            18 I            27 R
+             1 1            10 A            19 J            28 S
+             2 2            11 B            20 K            29 T
+             3 3            12 C            21 L            30 U
+             4 4            13 D            22 M            31 V
+             5 5            14 E            23 N
+             6 6            15 F            24 O         (pad) =
+             7 7            16 G            25 P
+             8 8            17 H            26 Q
+
+*/
+
+
+int
+ldns_b32_ntop_ar(uint8_t const *src, size_t srclength, char *target, size_t targsize, const char B32_ar[]) {
+       size_t datalength = 0;
+       uint8_t input[5];
+       uint8_t output[8];
+       size_t i;
+        memset(output, 0, 8);
+
+       while (4 < srclength) {
+               input[0] = *src++;
+               input[1] = *src++;
+               input[2] = *src++;
+               input[3] = *src++;
+               input[4] = *src++;
+               srclength -= 5;
+
+               output[0] = (input[0] & 0xf8) >> 3;
+               output[1] = ((input[0] & 0x07) << 2) + ((input[1] & 0xc0) >> 6);
+               output[2] = (input[1] & 0x3e) >> 1;
+               output[3] = ((input[1] & 0x01) << 4) + ((input[2] & 0xf0) >> 4);
+               output[4] = ((input[2] & 0x0f) << 1) + ((input[3] & 0x80) >> 7);
+               output[5] = (input[3] & 0x7c) >> 2;
+               output[6] = ((input[3] & 0x03) << 3) + ((input[4] & 0xe0) >> 5);
+               output[7] = (input[4] & 0x1f);
+
+               assert(output[0] < 32);
+               assert(output[1] < 32);
+               assert(output[2] < 32);
+               assert(output[3] < 32);
+               assert(output[4] < 32);
+               assert(output[5] < 32);
+               assert(output[6] < 32);
+               assert(output[7] < 32);
+
+               if (datalength + 8 > targsize) {
+                       return (-1);
+               }
+               target[datalength++] = B32_ar[output[0]];
+               target[datalength++] = B32_ar[output[1]];
+               target[datalength++] = B32_ar[output[2]];
+               target[datalength++] = B32_ar[output[3]];
+               target[datalength++] = B32_ar[output[4]];
+               target[datalength++] = B32_ar[output[5]];
+               target[datalength++] = B32_ar[output[6]];
+               target[datalength++] = B32_ar[output[7]];
+       }
+    
+       /* Now we worry about padding. */
+       if (0 != srclength) {
+               /* Get what's left. */
+               input[0] = input[1] = input[2] = input[3] = input[4] = (uint8_t) '\0';
+               for (i = 0; i < srclength; i++)
+                       input[i] = *src++;
+       
+               output[0] = (input[0] & 0xf8) >> 3;
+               assert(output[0] < 32);
+               if (srclength >= 1) {
+                       output[1] = ((input[0] & 0x07) << 2) + ((input[1] & 0xc0) >> 6);
+                       assert(output[1] < 32);
+                       output[2] = (input[1] & 0x3e) >> 1;
+                       assert(output[2] < 32);
+               }
+               if (srclength >= 2) {
+                       output[3] = ((input[1] & 0x01) << 4) + ((input[2] & 0xf0) >> 4);
+                       assert(output[3] < 32);
+               }
+               if (srclength >= 3) {
+                       output[4] = ((input[2] & 0x0f) << 1) + ((input[3] & 0x80) >> 7);
+                       assert(output[4] < 32);
+                       output[5] = (input[3] & 0x7c) >> 2;
+                       assert(output[5] < 32);
+               }
+               if (srclength >= 4) {
+                       output[6] = ((input[3] & 0x03) << 3) + ((input[4] & 0xe0) >> 5);
+                       assert(output[6] < 32);
+               }
+
+
+               if (datalength + 1 > targsize) {
+                       return (-2);
+               }
+               target[datalength++] = B32_ar[output[0]];
+               if (srclength >= 1) {
+                       target[datalength++] = B32_ar[output[1]];
+                       if (srclength == 1 && output[2] == 0) {
+                               target[datalength++] = Pad32;
+                       } else {
+                               target[datalength++] = B32_ar[output[2]];
+                       }
+               } else {
+                       target[datalength++] = Pad32;
+                       target[datalength++] = Pad32;
+               }
+               if (srclength >= 2) {
+                       target[datalength++] = B32_ar[output[3]];
+               } else {
+                       target[datalength++] = Pad32;
+               }
+               if (srclength >= 3) {
+                       target[datalength++] = B32_ar[output[4]];
+                       if (srclength == 3 && output[5] == 0) {
+                               target[datalength++] = Pad32;
+                       } else {
+                               target[datalength++] = B32_ar[output[5]];
+                       }
+               } else {
+                       target[datalength++] = Pad32;
+                       target[datalength++] = Pad32;
+               }
+               if (srclength >= 4) {
+                       target[datalength++] = B32_ar[output[6]];
+               } else {
+                       target[datalength++] = Pad32;
+               }
+               target[datalength++] = Pad32;
+       }
+       if (datalength > targsize) {
+               return (-3);
+       }
+       target[datalength] = '\0';      /* Returned value doesn't count \0. */
+       return (int) (datalength);
+}
+
+int
+ldns_b32_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
+       return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32);
+}
+
+/* deprecated, here for backwards compatibility */
+int
+b32_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
+       return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32);
+}
+
+int
+ldns_b32_ntop_extended_hex(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
+       return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32_extended_hex);
+}
+
+/* deprecated, here for backwards compatibility */
+int
+b32_ntop_extended_hex(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
+       return ldns_b32_ntop_ar(src, srclength, target, targsize, Base32_extended_hex);
+}
+
diff --git a/contrib/ldns/compat/b32_pton.c b/contrib/ldns/compat/b32_pton.c
new file mode 100644 (file)
index 0000000..5a3c2ea
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*     "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";*/
+static const char Base32[] =
+       "abcdefghijklmnopqrstuvwxyz234567";
+/*     "0123456789ABCDEFGHIJKLMNOPQRSTUV";*/
+static const char Base32_extended_hex[] =
+       "0123456789abcdefghijklmnopqrstuv";
+static const char Pad32 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+5.  Base 32 Encoding
+
+   The Base 32 encoding is designed to represent arbitrary sequences of
+   octets in a form that needs to be case insensitive but need not be
+   humanly readable.
+
+   A 33-character subset of US-ASCII is used, enabling 5 bits to be
+   represented per printable character.  (The extra 33rd character, "=",
+   is used to signify a special processing function.)
+
+   The encoding process represents 40-bit groups of input bits as output
+   strings of 8 encoded characters.  Proceeding from left to right, a
+   40-bit input group is formed by concatenating 5 8bit input groups.
+   These 40 bits are then treated as 8 concatenated 5-bit groups, each
+   of which is translated into a single digit in the base 32 alphabet.
+   When encoding a bit stream via the base 32 encoding, the bit stream
+   must be presumed to be ordered with the most-significant-bit first.
+   That is, the first bit in the stream will be the high-order bit in
+   the first 8bit byte, and the eighth bit will be the low-order bit in
+   the first 8bit byte, and so on.
+
+   Each 5-bit group is used as an index into an array of 32 printable
+   characters.  The character referenced by the index is placed in the
+   output string.  These characters, identified in Table 3, below, are
+   selected from US-ASCII digits and uppercase letters.
+
+                      Table 3: The Base 32 Alphabet
+
+         Value Encoding  Value Encoding  Value Encoding  Value Encoding
+             0 A             9 J            18 S            27 3
+             1 B            10 K            19 T            28 4
+             2 C            11 L            20 U            29 5
+             3 D            12 M            21 V            30 6
+             4 E            13 N            22 W            31 7
+             5 F            14 O            23 X
+             6 G            15 P            24 Y         (pad) =
+             7 H            16 Q            25 Z
+             8 I            17 R            26 2
+
+
+   Special processing is performed if fewer than 40 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a body.  When fewer than 40 input bits
+   are available in an input group, zero bits are added (on the right)
+   to form an integral number of 5-bit groups.  Padding at the end of
+   the data is performed using the "=" character.  Since all base 32
+   input is an integral number of octets, only the following cases can
+   arise:
+
+   (1) the final quantum of encoding input is an integral multiple of 40
+   bits; here, the final unit of encoded output will be an integral
+   multiple of 8 characters with no "=" padding,
+
+   (2) the final quantum of encoding input is exactly 8 bits; here, the
+   final unit of encoded output will be two characters followed by six
+   "=" padding characters,
+
+   (3) the final quantum of encoding input is exactly 16 bits; here, the
+   final unit of encoded output will be four characters followed by four
+   "=" padding characters,
+
+   (4) the final quantum of encoding input is exactly 24 bits; here, the
+   final unit of encoded output will be five characters followed by
+   three "=" padding characters, or
+
+   (5) the final quantum of encoding input is exactly 32 bits; here, the
+   final unit of encoded output will be seven characters followed by one
+   "=" padding character.
+
+
+6.  Base 32 Encoding with Extended Hex Alphabet
+
+   The following description of base 32 is due to [7].  This encoding
+   should not be regarded as the same as the "base32" encoding, and
+   should not be referred to as only "base32".
+
+   One property with this alphabet, that the base32 and base32 alphabet
+   lack, is that encoded data maintain its sort order when the encoded
+   data is compared bit-wise.
+
+   This encoding is identical to the previous one, except for the
+   alphabet.  The new alphabet is found in table 4.
+
+                     Table 4: The "Extended Hex" Base 32 Alphabet
+
+         Value Encoding  Value Encoding  Value Encoding  Value Encoding
+             0 0             9 9            18 I            27 R
+             1 1            10 A            19 J            28 S
+             2 2            11 B            20 K            29 T
+             3 3            12 C            21 L            30 U
+             4 4            13 D            22 M            31 V
+             5 5            14 E            23 N
+             6 6            15 F            24 O         (pad) =
+             7 7            16 G            25 P
+             8 8            17 H            26 Q
+
+
+
+
+*/
+/* skips all whitespace anywhere.
+   converts characters, four at a time, starting at (or after)
+   src from base - 32 numbers into three 8 bit bytes in the target area.
+   it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+ldns_b32_pton_ar(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize, const char B32_ar[])
+{
+       int tarindex, state, ch;
+       char *pos;
+       int i = 0;
+
+       state = 0;
+       tarindex = 0;
+       
+       while ((ch = *src++) != '\0' && (i == 0 || i < (int) hashed_owner_str_len)) {
+               i++;
+               ch = tolower(ch);
+               if (isspace((unsigned char)ch))        /* Skip whitespace anywhere. */
+                       continue;
+
+               if (ch == Pad32)
+                       break;
+
+               pos = strchr(B32_ar, ch);
+               if (pos == 0) {
+                       /* A non-base32 character. */
+                       return (-ch);
+               }
+
+               switch (state) {
+               case 0:
+                       if (target) {
+                               if ((size_t)tarindex >= targsize) {
+                                       return (-2);
+                               }
+                               target[tarindex] = (pos - B32_ar) << 3;
+                       }
+                       state = 1;
+                       break;
+               case 1:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize) {
+                                       return (-3);
+                               }
+                               target[tarindex]   |=  (pos - B32_ar) >> 2;
+                               target[tarindex+1]  = ((pos - B32_ar) & 0x03)
+                                                       << 6 ;
+                       }
+                       tarindex++;
+                       state = 2;
+                       break;
+               case 2:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize) {
+                                       return (-4);
+                               }
+                               target[tarindex]   |=  (pos - B32_ar) << 1;
+                       }
+                       /*tarindex++;*/
+                       state = 3;
+                       break;
+               case 3:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize) {
+                                       return (-5);
+                               }
+                               target[tarindex]   |=  (pos - B32_ar) >> 4;
+                               target[tarindex+1]  = ((pos - B32_ar) & 0x0f) << 4 ;
+                       }
+                       tarindex++;
+                       state = 4;
+                       break;
+               case 4:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize) {
+                                       return (-6);
+                               }
+                               target[tarindex]   |=  (pos - B32_ar) >> 1;
+                               target[tarindex+1]  = ((pos - B32_ar) & 0x01)
+                                                       << 7 ;
+                       }
+                       tarindex++;
+                       state = 5;
+                       break;
+               case 5:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize) {
+                                       return (-7);
+                               }
+                               target[tarindex]   |=  (pos - B32_ar) << 2;
+                       }
+                       state = 6;
+                       break;
+               case 6:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize) {
+                                       return (-8);
+                               }
+                               target[tarindex]   |=  (pos - B32_ar) >> 3;
+                               target[tarindex+1]  = ((pos - B32_ar) & 0x07)
+                                                       << 5 ;
+                       }
+                       tarindex++;
+                       state = 7;
+                       break;
+               case 7:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize) {
+                                       return (-9);
+                               }
+                               target[tarindex]   |=  (pos - B32_ar);
+                       }
+                       tarindex++;
+                       state = 0;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+       /*
+        * We are done decoding Base-32 chars.  Let's see if we ended
+        * on a byte boundary, and/or with erroneous trailing characters.
+        */
+
+       if (ch == Pad32) {              /* We got a pad char. */
+               ch = *src++;            /* Skip it, get next. */
+               switch (state) {
+               case 0:         /* Invalid = in first position */
+               case 1:         /* Invalid = in second position */
+                       return (-10);
+
+               case 2:         /* Valid, means one byte of info */
+               case 3:
+                       /* Skip any number of spaces. */
+                       for ((void)NULL; ch != '\0'; ch = *src++)
+                               if (!isspace((unsigned char)ch))
+                                       break;
+                       /* Make sure there is another trailing = sign. */
+                       if (ch != Pad32) {
+                               return (-11);
+                       }
+                       ch = *src++;            /* Skip the = */
+                       /* Fall through to "single trailing =" case. */
+                       /* FALLTHROUGH */
+
+               case 4:         /* Valid, means two bytes of info */
+               case 5:
+               case 6:
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for ((void)NULL; ch != '\0'; ch = *src++)
+                               if (!(isspace((unsigned char)ch) || ch == '=')) {
+                                       return (-12);
+                               }
+
+               case 7:         /* Valid, means three bytes of info */
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for ((void)NULL; ch != '\0'; ch = *src++)
+                               if (!isspace((unsigned char)ch)) {
+                                       return (-13);
+                               }
+
+                       /*
+                        * Now make sure for cases 2 and 3 that the "extra"
+                        * bits that slopped past the last full byte were
+                        * zeros.  If we don't check them, they become a
+                        * subliminal channel.
+                        */
+                       if (target && target[tarindex] != 0) {
+                               return (-14);
+                       }
+               }
+       } else {
+               /*
+                * We ended by seeing the end of the string.  Make sure we
+                * have no partial bytes lying around.
+                */
+               if (state != 0)
+                       return (-15);
+       }
+
+       return (tarindex);
+}
+
+int
+ldns_b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize)
+{
+       return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32);
+}
+
+/* deprecated, here for backwards compatibility */
+int
+b32_pton(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize)
+{
+       return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32);
+}
+
+int
+ldns_b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize)
+{
+       return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32_extended_hex);
+}
+
+/* deprecated, here for backwards compatibility */
+int
+b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len, uint8_t *target, size_t targsize)
+{
+       return ldns_b32_pton_ar(src, hashed_owner_str_len, target, targsize, Base32_extended_hex);
+}
diff --git a/contrib/ldns/compat/b64_ntop.c b/contrib/ldns/compat/b64_ntop.c
new file mode 100644 (file)
index 0000000..93c209a
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+   The following encoding technique is taken from RFC 1521 by Borenstein
+   and Freed.  It is reproduced here in a slightly edited form for
+   convenience.
+
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+   represented per printable character. (The extra 65th character, "=",
+   is used to signify a special processing function.)
+
+   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.
+
+   Each 6-bit group is used as an index into an array of 64 printable
+   characters. The character referenced by the index is placed in the
+   output string.
+
+                         Table 1: The Base64 Alphabet
+
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+          0 A            17 R            34 i            51 z
+          1 B            18 S            35 j            52 0
+          2 C            19 T            36 k            53 1
+          3 D            20 U            37 l            54 2
+          4 E            21 V            38 m            55 3
+          5 F            22 W            39 n            56 4
+          6 G            23 X            40 o            57 5
+          7 H            24 Y            41 p            58 6
+          8 I            25 Z            42 q            59 7
+          9 J            26 a            43 r            60 8
+         10 K            27 b            44 s            61 9
+         11 L            28 c            45 t            62 +
+         12 M            29 d            46 u            63 /
+         13 N            30 e            47 v
+         14 O            31 f            48 w         (pad) =
+         15 P            32 g            49 x
+         16 Q            33 h            50 y
+
+   Special processing is performed if fewer than 24 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a quantity.  When fewer than 24 input
+   bits are available in an input group, zero bits are added (on the
+   right) to form an integral number of 6-bit groups.  Padding at the
+   end of the data is performed using the '=' character.
+
+   Since all base64 input is an integral number of octets, only the
+         -------------------------------------------------                       
+   following cases can arise:
+   
+       (1) the final quantum of encoding input is an integral
+           multiple of 24 bits; here, the final unit of encoded
+          output will be an integral multiple of 4 characters
+          with no "=" padding,
+       (2) the final quantum of encoding input is exactly 8 bits;
+           here, the final unit of encoded output will be two
+          characters followed by two "=" padding characters, or
+       (3) the final quantum of encoding input is exactly 16 bits;
+           here, the final unit of encoded output will be three
+          characters followed by one "=" padding character.
+   */
+
+int
+ldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
+       size_t datalength = 0;
+       uint8_t input[3];
+       uint8_t output[4];
+       size_t i;
+       
+       if (srclength == 0) {
+               if (targsize > 0) {
+                       target[0] = '\0';
+                       return 0;
+               } else {
+                       return -1;
+               }
+       }
+
+       while (2 < srclength) {
+               input[0] = *src++;
+               input[1] = *src++;
+               input[2] = *src++;
+               srclength -= 3;
+
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               output[3] = input[2] & 0x3f;
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+               Assert(output[3] < 64);
+
+               if (datalength + 4 > targsize) {
+                       return (-1);
+               }
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               target[datalength++] = Base64[output[2]];
+               target[datalength++] = Base64[output[3]];
+       }
+    
+       /* Now we worry about padding. */
+       if (0 != srclength) {
+               /* Get what's left. */
+               input[0] = input[1] = input[2] = (uint8_t) '\0';
+               for (i = 0; i < srclength; i++)
+                       input[i] = *src++;
+       
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+
+               if (datalength + 4 > targsize) {
+                       return (-2);
+               }
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               if (srclength == 1) {
+                       target[datalength++] = Pad64;
+               } else {
+                       target[datalength++] = Base64[output[2]];
+               }
+               target[datalength++] = Pad64;
+       }
+       if (datalength >= targsize) {
+               return (-3);
+       }
+       target[datalength] = '\0';      /* Returned value doesn't count \0. */
+       return (int) (datalength);
+}
diff --git a/contrib/ldns/compat/b64_pton.c b/contrib/ldns/compat/b64_pton.c
new file mode 100644 (file)
index 0000000..a4babea
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+   The following encoding technique is taken from RFC 1521 by Borenstein
+   and Freed.  It is reproduced here in a slightly edited form for
+   convenience.
+
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+   represented per printable character. (The extra 65th character, "=",
+   is used to signify a special processing function.)
+
+   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.
+
+   Each 6-bit group is used as an index into an array of 64 printable
+   characters. The character referenced by the index is placed in the
+   output string.
+
+                         Table 1: The Base64 Alphabet
+
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+          0 A            17 R            34 i            51 z
+          1 B            18 S            35 j            52 0
+          2 C            19 T            36 k            53 1
+          3 D            20 U            37 l            54 2
+          4 E            21 V            38 m            55 3
+          5 F            22 W            39 n            56 4
+          6 G            23 X            40 o            57 5
+          7 H            24 Y            41 p            58 6
+          8 I            25 Z            42 q            59 7
+          9 J            26 a            43 r            60 8
+         10 K            27 b            44 s            61 9
+         11 L            28 c            45 t            62 +
+         12 M            29 d            46 u            63 /
+         13 N            30 e            47 v
+         14 O            31 f            48 w         (pad) =
+         15 P            32 g            49 x
+         16 Q            33 h            50 y
+
+   Special processing is performed if fewer than 24 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a quantity.  When fewer than 24 input
+   bits are available in an input group, zero bits are added (on the
+   right) to form an integral number of 6-bit groups.  Padding at the
+   end of the data is performed using the '=' character.
+
+   Since all base64 input is an integral number of octets, only the
+         -------------------------------------------------                       
+   following cases can arise:
+   
+       (1) the final quantum of encoding input is an integral
+           multiple of 24 bits; here, the final unit of encoded
+          output will be an integral multiple of 4 characters
+          with no "=" padding,
+       (2) the final quantum of encoding input is exactly 8 bits;
+           here, the final unit of encoded output will be two
+          characters followed by two "=" padding characters, or
+       (3) the final quantum of encoding input is exactly 16 bits;
+           here, the final unit of encoded output will be three
+          characters followed by one "=" padding character.
+   */
+
+/* skips all whitespace anywhere.
+   converts characters, four at a time, starting at (or after)
+   src from base - 64 numbers into three 8 bit bytes in the target area.
+   it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+ldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
+{
+       int tarindex, state, ch;
+       char *pos;
+
+       state = 0;
+       tarindex = 0;
+
+       if (strlen(src) == 0) {
+               return 0;
+       }
+
+       while ((ch = *src++) != '\0') {
+               if (isspace((unsigned char)ch))        /* Skip whitespace anywhere. */
+                       continue;
+
+               if (ch == Pad64)
+                       break;
+
+               pos = strchr(Base64, ch);
+               if (pos == 0) {
+                       /* A non-base64 character. */
+                       return (-1);
+               }
+
+               switch (state) {
+               case 0:
+                       if (target) {
+                               if ((size_t)tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] = (pos - Base64) << 2;
+                       }
+                       state = 1;
+                       break;
+               case 1:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 4;
+                               target[tarindex+1]  = ((pos - Base64) & 0x0f)
+                                                       << 4 ;
+                       }
+                       tarindex++;
+                       state = 2;
+                       break;
+               case 2:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 2;
+                               target[tarindex+1]  = ((pos - Base64) & 0x03)
+                                                       << 6;
+                       }
+                       tarindex++;
+                       state = 3;
+                       break;
+               case 3:
+                       if (target) {
+                               if ((size_t)tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] |= (pos - Base64);
+                       }
+                       tarindex++;
+                       state = 0;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+       /*
+        * We are done decoding Base-64 chars.  Let's see if we ended
+        * on a byte boundary, and/or with erroneous trailing characters.
+        */
+
+       if (ch == Pad64) {              /* We got a pad char. */
+               ch = *src++;            /* Skip it, get next. */
+               switch (state) {
+               case 0:         /* Invalid = in first position */
+               case 1:         /* Invalid = in second position */
+                       return (-1);
+
+               case 2:         /* Valid, means one byte of info */
+                       /* Skip any number of spaces. */
+                       for ((void)NULL; ch != '\0'; ch = *src++)
+                               if (!isspace((unsigned char)ch))
+                                       break;
+                       /* Make sure there is another trailing = sign. */
+                       if (ch != Pad64)
+                               return (-1);
+                       ch = *src++;            /* Skip the = */
+                       /* Fall through to "single trailing =" case. */
+                       /* FALLTHROUGH */
+
+               case 3:         /* Valid, means two bytes of info */
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for ((void)NULL; ch != '\0'; ch = *src++)
+                               if (!isspace((unsigned char)ch))
+                                       return (-1);
+
+                       /*
+                        * Now make sure for cases 2 and 3 that the "extra"
+                        * bits that slopped past the last full byte were
+                        * zeros.  If we don't check them, they become a
+                        * subliminal channel.
+                        */
+                       if (target && target[tarindex] != 0)
+                               return (-1);
+               }
+       } else {
+               /*
+                * We ended by seeing the end of the string.  Make sure we
+                * have no partial bytes lying around.
+                */
+               if (state != 0)
+                       return (-1);
+       }
+
+       return (tarindex);
+}
diff --git a/contrib/ldns/compat/ctime_r.c b/contrib/ldns/compat/ctime_r.c
new file mode 100644 (file)
index 0000000..4ffd8b7
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+char *ctime_r(const time_t *timep, char *buf)
+{
+       /* no thread safety. */
+       char* result = ctime(timep);
+       if(buf && result)
+               strcpy(buf, result);
+       return result;
+}
diff --git a/contrib/ldns/compat/fake-rfc2553.c b/contrib/ldns/compat/fake-rfc2553.c
new file mode 100644 (file)
index 0000000..431e04a
--- /dev/null
@@ -0,0 +1,229 @@
+/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */
+/*
+ * Copyright (C) 2000-2003 Damien Miller.  All rights reserved.
+ * Copyright (C) 1999 WIDE Project.  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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * Pseudo-implementation of RFC2553 name / address resolution functions
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For example, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#include <ldns/config.h>
+#include <ldns/common.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "compat/fake-rfc2553.h"
+
+#ifndef HAVE_GETNAMEINFO
+int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host, 
+                size_t hostlen, char *serv, size_t servlen, int flags)
+{
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+       struct hostent *hp;
+       char tmpserv[16];
+
+       if (serv != NULL) {
+               snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
+               if (strlcpy(serv, tmpserv, servlen) >= servlen)
+                       return (EAI_MEMORY);
+       }
+
+       if (host != NULL) {
+               if (flags & NI_NUMERICHOST) {
+                       if (strlcpy(host, inet_ntoa(sin->sin_addr),
+                           hostlen) >= hostlen)
+                               return (EAI_MEMORY);
+                       else
+                               return (0);
+               } else {
+                       hp = gethostbyaddr((char *)&sin->sin_addr, 
+                           sizeof(struct in_addr), AF_INET);
+                       if (hp == NULL)
+                               return (EAI_NODATA);
+                       
+                       if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
+                               return (EAI_MEMORY);
+                       else
+                               return (0);
+               }
+       }
+       return (0);
+}
+#endif /* !HAVE_GETNAMEINFO */
+
+#ifndef HAVE_GAI_STRERROR
+#ifdef HAVE_CONST_GAI_STRERROR_PROTO
+const char *
+#else
+char *
+#endif
+gai_strerror(int err)
+{
+       switch (err) {
+       case EAI_NODATA:
+               return ("no address associated with name");
+       case EAI_MEMORY:
+               return ("memory allocation failure.");
+       case EAI_NONAME:
+               return ("nodename nor servname provided, or not known");
+       default:
+               return ("unknown/invalid error.");
+       }
+}    
+#endif /* !HAVE_GAI_STRERROR */
+
+#ifndef HAVE_FREEADDRINFO
+void
+freeaddrinfo(struct addrinfo *ai)
+{
+       struct addrinfo *next;
+
+       for(; ai != NULL;) {
+               next = ai->ai_next;
+               free(ai);
+               ai = next;
+       }
+}
+#endif /* !HAVE_FREEADDRINFO */
+
+#ifndef HAVE_GETADDRINFO
+static struct
+addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
+{
+       struct addrinfo *ai;
+
+       ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
+       if (ai == NULL)
+               return (NULL);
+       
+       memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
+       
+       ai->ai_addr = (struct sockaddr *)(ai + 1);
+       /* XXX -- ssh doesn't use sa_len */
+       ai->ai_addrlen = sizeof(struct sockaddr_in);
+       ai->ai_addr->sa_family = ai->ai_family = AF_INET;
+
+       ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
+       ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
+       
+       /* XXX: the following is not generally correct, but does what we want */
+       if (hints->ai_socktype)
+               ai->ai_socktype = hints->ai_socktype;
+       else
+               ai->ai_socktype = SOCK_STREAM;
+
+       if (hints->ai_protocol)
+               ai->ai_protocol = hints->ai_protocol;
+
+       return (ai);
+}
+
+int
+getaddrinfo(const char *hostname, const char *servname, 
+    const struct addrinfo *hints, struct addrinfo **res)
+{
+       struct hostent *hp;
+       struct servent *sp;
+       struct in_addr in;
+       int i;
+       long int port;
+       u_long addr;
+
+       port = 0;
+       if (servname != NULL) {
+               char *cp;
+
+               port = strtol(servname, &cp, 10);
+               if (port > 0 && port <= 65535 && *cp == '\0')
+                       port = htons(port);
+               else if ((sp = getservbyname(servname, NULL)) != NULL)
+                       port = sp->s_port;
+               else
+                       port = 0;
+       }
+
+       if (hints && hints->ai_flags & AI_PASSIVE) {
+               addr = htonl(0x00000000);
+               if (hostname && inet_aton(hostname, &in) != 0)
+                       addr = in.s_addr;
+               *res = malloc_ai(port, addr, hints);
+               if (*res == NULL) 
+                       return (EAI_MEMORY);
+               return (0);
+       }
+               
+       if (!hostname) {
+               *res = malloc_ai(port, htonl(0x7f000001), hints);
+               if (*res == NULL) 
+                       return (EAI_MEMORY);
+               return (0);
+       }
+       
+       if (inet_aton(hostname, &in)) {
+               *res = malloc_ai(port, in.s_addr, hints);
+               if (*res == NULL) 
+                       return (EAI_MEMORY);
+               return (0);
+       }
+       
+       /* Don't try DNS if AI_NUMERICHOST is set */
+       if (hints && hints->ai_flags & AI_NUMERICHOST)
+               return (EAI_NONAME);
+       
+       hp = gethostbyname(hostname);
+       if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+               struct addrinfo *cur, *prev;
+
+               cur = prev = *res = NULL;
+               for (i = 0; hp->h_addr_list[i]; i++) {
+                       struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
+
+                       cur = malloc_ai(port, in->s_addr, hints);
+                       if (cur == NULL) {
+                               if (*res != NULL)
+                                       freeaddrinfo(*res);
+                               return (EAI_MEMORY);
+                       }
+                       if (prev)
+                               prev->ai_next = cur;
+                       else
+                               *res = cur;
+
+                       prev = cur;
+               }
+               return (0);
+       }
+       
+       return (EAI_NODATA);
+}
+#endif /* !HAVE_GETADDRINFO */
diff --git a/contrib/ldns/compat/fake-rfc2553.h b/contrib/ldns/compat/fake-rfc2553.h
new file mode 100644 (file)
index 0000000..1e9add1
--- /dev/null
@@ -0,0 +1,175 @@
+/* From openssh 4.3p2 filename openbsd-compat/fake-rfc2553.h */
+/*
+ * Copyright (C) 2000-2003 Damien Miller.  All rights reserved.
+ * Copyright (C) 1999 WIDE Project.  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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * Pseudo-implementation of RFC2553 name / address resolution functions
+ *
+ * But these functions are not implemented correctly. The minimum subset
+ * is implemented for ssh use only. For example, this routine assumes
+ * that ai_family is AF_INET. Don't use it for another purpose.
+ */
+
+#ifndef _FAKE_RFC2553_H
+#define _FAKE_RFC2553_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <limits.h>
+
+/*
+ * First, socket and INET6 related definitions 
+ */
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+#ifndef _SS_MAXSIZE
+# define       _SS_MAXSIZE     128     /* Implementation specific max size */
+# define       _SS_PADSIZE     (_SS_MAXSIZE - sizeof (struct sockaddr))
+struct sockaddr_storage {
+       struct sockaddr ss_sa;
+       char            __ss_pad2[_SS_PADSIZE];
+};
+# define ss_family ss_sa.sa_family
+#endif /* _SS_MAXSIZE */
+#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+# define IN6_IS_ADDR_LOOPBACK(a) \
+       (((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \
+        ((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == htonl(1))
+#endif /* !IN6_IS_ADDR_LOOPBACK */
+
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr {
+       uint8_t s6_addr[16];
+};
+#endif /* !HAVE_STRUCT_IN6_ADDR */
+
+#ifndef HAVE_STRUCT_SOCKADDR_IN6
+struct sockaddr_in6 {
+       unsigned short  sin6_family;
+       uint16_t        sin6_port;
+       uint32_t        sin6_flowinfo;
+       struct in6_addr sin6_addr;
+};
+#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
+
+#ifndef AF_INET6
+/* Define it to something that should never appear */
+#define AF_INET6 AF_MAX
+#endif
+
+/*
+ * Next, RFC2553 name / address resolution API
+ */
+
+#ifndef NI_NUMERICHOST
+# define NI_NUMERICHOST    (1)
+#endif
+#ifndef NI_NAMEREQD
+# define NI_NAMEREQD       (1<<1)
+#endif
+#ifndef NI_NUMERICSERV
+# define NI_NUMERICSERV    (1<<2)
+#endif
+
+#ifndef AI_PASSIVE
+# define AI_PASSIVE            (1)
+#endif
+#ifndef AI_CANONNAME
+# define AI_CANONNAME          (1<<1)
+#endif
+#ifndef AI_NUMERICHOST
+# define AI_NUMERICHOST                (1<<2)
+#endif
+
+#ifndef NI_MAXSERV
+# define NI_MAXSERV 32
+#endif /* !NI_MAXSERV */
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif /* !NI_MAXHOST */
+
+#ifndef INT_MAX
+#define INT_MAX                0xffffffff
+#endif
+
+#ifndef EAI_NODATA
+# define EAI_NODATA    (INT_MAX - 1)
+#endif
+#ifndef EAI_MEMORY
+# define EAI_MEMORY    (INT_MAX - 2)
+#endif
+#ifndef EAI_NONAME
+# define EAI_NONAME    (INT_MAX - 3)
+#endif
+#ifndef EAI_SYSTEM
+# define EAI_SYSTEM    (INT_MAX - 4)
+#endif
+
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
+       int     ai_family;      /* PF_xxx */
+       int     ai_socktype;    /* SOCK_xxx */
+       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+       size_t  ai_addrlen;     /* length of ai_addr */
+       char    *ai_canonname;  /* canonical name for hostname */
+       struct sockaddr *ai_addr;       /* binary address */
+       struct addrinfo *ai_next;       /* next structure in linked list */
+};
+#endif /* !HAVE_STRUCT_ADDRINFO */
+
+#ifndef HAVE_GETADDRINFO
+#ifdef getaddrinfo
+# undef getaddrinfo
+#endif
+#define getaddrinfo(a,b,c,d)   (ssh_getaddrinfo(a,b,c,d))
+int getaddrinfo(const char *, const char *, 
+    const struct addrinfo *, struct addrinfo **);
+#endif /* !HAVE_GETADDRINFO */
+
+#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO)
+#define gai_strerror(a)                (ssh_gai_strerror(a))
+char *gai_strerror(int);
+#endif /* !HAVE_GAI_STRERROR */
+
+#ifndef HAVE_FREEADDRINFO
+#define freeaddrinfo(a)                (ssh_freeaddrinfo(a))
+void freeaddrinfo(struct addrinfo *);
+#endif /* !HAVE_FREEADDRINFO */
+
+#ifndef HAVE_GETNAMEINFO
+#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g))
+int getnameinfo(const struct sockaddr *, size_t, char *, size_t, 
+    char *, size_t, int);
+#endif /* !HAVE_GETNAMEINFO */
+
+#endif /* !_FAKE_RFC2553_H */
+
diff --git a/contrib/ldns/compat/gmtime_r.c b/contrib/ldns/compat/gmtime_r.c
new file mode 100644 (file)
index 0000000..7062e7d
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+struct tm *gmtime_r(const time_t *timep, struct tm *result)
+{
+       /* no thread safety. */
+       *result = *gmtime(timep);
+       return result;
+}
diff --git a/contrib/ldns/compat/inet_aton.c b/contrib/ldns/compat/inet_aton.c
new file mode 100644 (file)
index 0000000..e8c3a57
--- /dev/null
@@ -0,0 +1,182 @@
+/* From openssh4.3p2 compat/inet_aton.c */
+/*
+ * Copyright (c) 1983, 1990, 1993
+ *    The Regents of the University of California.  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 University 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 REGENTS 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ * 
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/net/inet_addr.c */
+
+#include <ldns/config.h>
+
+#if !defined(HAVE_INET_ATON)
+
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#include <ctype.h>
+
+#if 0
+/*
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+in_addr_t
+inet_addr(const char *cp)
+{
+       struct in_addr val;
+
+       if (inet_aton(cp, &val))
+               return (val.s_addr);
+       return (INADDR_NONE);
+}
+#endif
+
+/* 
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+       uint32_t val;
+       int base, n;
+       char c;
+       unsigned int parts[4];
+       unsigned int *pp = parts;
+
+       c = *cp;
+       for (;;) {
+               /*
+                * Collect number up to ``.''.
+                * Values are specified as for C:
+                * 0x=hex, 0=octal, isdigit=decimal.
+                */
+               if (!isdigit((int) c))
+                       return (0);
+               val = 0; base = 10;
+               if (c == '0') {
+                       c = *++cp;
+                       if (c == 'x' || c == 'X')
+                               base = 16, c = *++cp;
+                       else
+                               base = 8;
+               }
+               for (;;) {
+                       if (isascii((int) c) && isdigit((int) c)) {
+                               val = (val * base) + (c - '0');
+                               c = *++cp;
+                       } else if (base == 16 && isascii((int) c) && isxdigit((int) c)) {
+                               val = (val << 4) |
+                                       (c + 10 - (islower((int) c) ? 'a' : 'A'));
+                               c = *++cp;
+                       } else
+                               break;
+               }
+               if (c == '.') {
+                       /*
+                        * Internet format:
+                        *      a.b.c.d
+                        *      a.b.c   (with c treated as 16 bits)
+                        *      a.b     (with b treated as 24 bits)
+                        */
+                       if (pp >= parts + 3)
+                               return (0);
+                       *pp++ = val;
+                       c = *++cp;
+               } else
+                       break;
+       }
+       /*
+        * Check for trailing characters.
+        */
+       if (c != '\0' && (!isascii((int) c) || !isspace((int) c)))
+               return (0);
+       /*
+        * Concoct the address according to
+        * the number of parts specified.
+        */
+       n = pp - parts + 1;
+       switch (n) {
+
+       case 0:
+               return (0);             /* initial nondigit */
+
+       case 1:                         /* a -- 32 bits */
+               break;
+
+       case 2:                         /* a.b -- 8.24 bits */
+               if ((val > 0xffffff) || (parts[0] > 0xff))
+                       return (0);
+               val |= parts[0] << 24;
+               break;
+
+       case 3:                         /* a.b.c -- 8.8.16 bits */
+               if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
+                       return (0);
+               val |= (parts[0] << 24) | (parts[1] << 16);
+               break;
+
+       case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
+               if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
+                       return (0);
+               val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+               break;
+       }
+       if (addr)
+               addr->s_addr = htonl(val);
+       return (1);
+}
+
+#endif /* !defined(HAVE_INET_ATON) */
diff --git a/contrib/ldns/compat/inet_ntop.c b/contrib/ldns/compat/inet_ntop.c
new file mode 100644 (file)
index 0000000..57509c7
--- /dev/null
@@ -0,0 +1,216 @@
+/* From openssh 4.3p2 compat/inet_ntop.c */
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */
+
+#include <ldns/config.h>
+
+#ifndef HAVE_INET_NTOP
+
+#include <sys/param.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#ifndef IN6ADDRSZ
+#define IN6ADDRSZ   16   /* IPv6 T_AAAA */                 
+#endif
+
+#ifndef INT16SZ
+#define INT16SZ     2    /* for systems without 16-bit ints */
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
+static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *     convert a network format address to presentation format.
+ * return:
+ *     pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *     Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(int af, const void *src, char *dst, size_t size)
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_ntop4(src, dst, size));
+       case AF_INET6:
+               return (inet_ntop6(src, dst, size));
+       default:
+#ifdef EAFNOSUPPORT
+               errno = EAFNOSUPPORT;
+#else
+               errno = ENOSYS;
+#endif
+               return (NULL);
+       }
+       /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *     format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ *     `dst' (as a const)
+ * notes:
+ *     (1) uses no statics
+ *     (2) takes a u_char* not an in_addr as input
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const u_char *src, char *dst, size_t size)
+{
+       static const char fmt[] = "%u.%u.%u.%u";
+       char tmp[sizeof "255.255.255.255"];
+       int l;
+
+       l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
+       if (l <= 0 || l >= (int)size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strlcpy(dst, tmp, size);
+       return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *     convert IPv6 binary address into presentation (printable) format
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(const u_char *src, char *dst, size_t size)
+{
+       /*
+        * Note that int32_t and int16_t need only be "at least" large enough
+        * to contain a value of the specified size.  On some systems, like
+        * Crays, there is no such thing as an integer variable with 16 bits.
+        * Keep this in mind if you think this function should have been coded
+        * to use pointer overlays.  All the world's not a VAX.
+        */
+       char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
+       char *tp, *ep;
+       struct { int base, len; } best, cur;
+       u_int words[IN6ADDRSZ / INT16SZ];
+       int i;
+       int advance;
+
+       /*
+        * Preprocess:
+        *      Copy the input (bytewise) array into a wordwise array.
+        *      Find the longest run of 0x00's in src[] for :: shorthanding.
+        */
+       memset(words, '\0', sizeof words);
+       for (i = 0; i < IN6ADDRSZ; i++)
+               words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+       best.base = -1;
+       cur.base = -1;
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+               if (words[i] == 0) {
+                       if (cur.base == -1)
+                               cur.base = i, cur.len = 1;
+                       else
+                               cur.len++;
+               } else {
+                       if (cur.base != -1) {
+                               if (best.base == -1 || cur.len > best.len)
+                                       best = cur;
+                               cur.base = -1;
+                       }
+               }
+       }
+       if (cur.base != -1) {
+               if (best.base == -1 || cur.len > best.len)
+                       best = cur;
+       }
+       if (best.base != -1 && best.len < 2)
+               best.base = -1;
+
+       /*
+        * Format the result.
+        */
+       tp = tmp;
+       ep = tmp + sizeof(tmp);
+       for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
+               /* Are we inside the best run of 0x00's? */
+               if (best.base != -1 && i >= best.base &&
+                   i < (best.base + best.len)) {
+                       if (i == best.base) {
+                               if (tp + 1 >= ep)
+                                       return (NULL);
+                               *tp++ = ':';
+                       }
+                       continue;
+               }
+               /* Are we following an initial run of 0x00s or any real hex? */
+               if (i != 0) {
+                       if (tp + 1 >= ep)
+                               return (NULL);
+                       *tp++ = ':';
+               }
+               /* Is this address an encapsulated IPv4? */
+               if (i == 6 && best.base == 0 &&
+                   (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+                       if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
+                               return (NULL);
+                       tp += strlen(tp);
+                       break;
+               }
+               advance = snprintf(tp, ep - tp, "%x", words[i]);
+               if (advance <= 0 || advance >= ep - tp)
+                       return (NULL);
+               tp += advance;
+       }
+       /* Was it a trailing run of 0x00's? */
+       if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
+               if (tp + 1 >= ep)
+                       return (NULL);
+               *tp++ = ':';
+       }
+       if (tp + 1 >= ep)
+               return (NULL);
+       *tp++ = '\0';
+
+       /*
+        * Check for overflow, copy, and we're done.
+        */
+       if ((size_t)(tp - tmp) > size) {
+               errno = ENOSPC;
+               return (NULL);
+       }
+       strlcpy(dst, tmp, size);
+       return (dst);
+}
+
+#endif /* !HAVE_INET_NTOP */
diff --git a/contrib/ldns/compat/inet_pton.c b/contrib/ldns/compat/inet_pton.c
new file mode 100644 (file)
index 0000000..7a4f576
--- /dev/null
@@ -0,0 +1,230 @@
+/*     $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $       */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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 <ldns/config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int     inet_pton4 (const char *src, uint8_t *dst);
+static int     inet_pton6 (const char *src, uint8_t *dst);
+
+/*
+ *
+ * The definitions we might miss.
+ *
+ */
+#ifndef NS_INT16SZ
+#define        NS_INT16SZ      2
+#endif
+
+#ifndef NS_IN6ADDRSZ
+#define NS_IN6ADDRSZ 16
+#endif
+
+#ifndef NS_INADDRSZ
+#define NS_INADDRSZ 4
+#endif
+
+/* int
+ * inet_pton(af, src, dst)
+ *     convert from presentation format (which usually means ASCII printable)
+ *     to network format (which is usually some kind of binary format).
+ * return:
+ *     1 if the address was valid for the specified address family
+ *     0 if the address wasn't valid (`dst' is untouched in this case)
+ *     -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *     Paul Vixie, 1996.
+ */
+int
+inet_pton(af, src, dst)
+       int af;
+       const char *src;
+       void *dst;
+{
+       switch (af) {
+       case AF_INET:
+               return (inet_pton4(src, dst));
+       case AF_INET6:
+               return (inet_pton6(src, dst));
+       default:
+#ifdef EAFNOSUPPORT
+               errno = EAFNOSUPPORT;
+#else
+               errno = ENOSYS;
+#endif
+               return (-1);
+       }
+       /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *     like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *     1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *     does not touch `dst' unless it's returning 1.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+       const char *src;
+       uint8_t *dst;
+{
+       static const char digits[] = "0123456789";
+       int saw_digit, octets, ch;
+       uint8_t tmp[NS_INADDRSZ], *tp;
+
+       saw_digit = 0;
+       octets = 0;
+       *(tp = tmp) = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr(digits, ch)) != NULL) {
+                       uint32_t new = *tp * 10 + (pch - digits);
+
+                       if (new > 255)
+                               return (0);
+                       *tp = new;
+                       if (! saw_digit) {
+                               if (++octets > 4)
+                                       return (0);
+                               saw_digit = 1;
+                       }
+               } else if (ch == '.' && saw_digit) {
+                       if (octets == 4)
+                               return (0);
+                       *++tp = 0;
+                       saw_digit = 0;
+               } else
+                       return (0);
+       }
+       if (octets < 4)
+               return (0);
+
+       memcpy(dst, tmp, NS_INADDRSZ);
+       return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ *     convert presentation level address to network order binary form.
+ * return:
+ *     1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *     (1) does not touch `dst' unless it's returning 1.
+ *     (2) :: in a full address is silently ignored.
+ * credit:
+ *     inspired by Mark Andrews.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton6(src, dst)
+       const char *src;
+       uint8_t *dst;
+{
+       static const char xdigits_l[] = "0123456789abcdef",
+                         xdigits_u[] = "0123456789ABCDEF";
+       uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+       const char *xdigits, *curtok;
+       int ch, saw_xdigit;
+       uint32_t val;
+
+       memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+       endp = tp + NS_IN6ADDRSZ;
+       colonp = NULL;
+       /* Leading :: requires some special handling. */
+       if (*src == ':')
+               if (*++src != ':')
+                       return (0);
+       curtok = src;
+       saw_xdigit = 0;
+       val = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+                       pch = strchr((xdigits = xdigits_u), ch);
+               if (pch != NULL) {
+                       val <<= 4;
+                       val |= (pch - xdigits);
+                       if (val > 0xffff)
+                               return (0);
+                       saw_xdigit = 1;
+                       continue;
+               }
+               if (ch == ':') {
+                       curtok = src;
+                       if (!saw_xdigit) {
+                               if (colonp)
+                                       return (0);
+                               colonp = tp;
+                               continue;
+                       }
+                       if (tp + NS_INT16SZ > endp)
+                               return (0);
+                       *tp++ = (uint8_t) (val >> 8) & 0xff;
+                       *tp++ = (uint8_t) val & 0xff;
+                       saw_xdigit = 0;
+                       val = 0;
+                       continue;
+               }
+               if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+                   inet_pton4(curtok, tp) > 0) {
+                       tp += NS_INADDRSZ;
+                       saw_xdigit = 0;
+                       break;  /* '\0' was seen by inet_pton4(). */
+               }
+               return (0);
+       }
+       if (saw_xdigit) {
+               if (tp + NS_INT16SZ > endp)
+                       return (0);
+               *tp++ = (uint8_t) (val >> 8) & 0xff;
+               *tp++ = (uint8_t) val & 0xff;
+       }
+       if (colonp != NULL) {
+               /*
+                * Since some memmove()'s erroneously fail to handle
+                * overlapping regions, we'll do the shift by hand.
+                */
+               const int n = tp - colonp;
+               int i;
+
+               for (i = 1; i <= n; i++) {
+                       endp[- i] = colonp[n - i];
+                       colonp[n - i] = 0;
+               }
+               tp = endp;
+       }
+       if (tp != endp)
+               return (0);
+       memcpy(dst, tmp, NS_IN6ADDRSZ);
+       return (1);
+}
diff --git a/contrib/ldns/compat/isblank.c b/contrib/ldns/compat/isblank.c
new file mode 100644 (file)
index 0000000..3b38154
--- /dev/null
@@ -0,0 +1,15 @@
+/* Just a replacement, if the original isblank is not
+   present */
+
+#if HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+
+int isblank(int c);
+
+/* true if character is a blank (space or tab). C99. */
+int
+isblank(int c)
+{
+       return (c == ' ') || (c == '\t');
+}
diff --git a/contrib/ldns/compat/malloc.c b/contrib/ldns/compat/malloc.c
new file mode 100644 (file)
index 0000000..bbc632e
--- /dev/null
@@ -0,0 +1,22 @@
+/* Just a replacement, if the original malloc is not
+   GNU-compliant. See autoconf documentation. */
+
+#if HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+#undef malloc
+
+#include <sys/types.h>
+
+void *malloc ();
+
+/* Allocate an N-byte block of memory from the heap.
+   If N is zero, allocate a 1-byte block.  */
+
+void *
+rpl_malloc (size_t n)
+{
+  if (n == 0)
+    n = 1;
+  return malloc (n);
+}
diff --git a/contrib/ldns/compat/memmove.c b/contrib/ldns/compat/memmove.c
new file mode 100644 (file)
index 0000000..e458092
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *     memmove.c: memmove compat implementation.
+ *
+ *     Copyright (c) 2001-2008, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+*/
+
+#include <ldns/config.h>
+#include <stdlib.h>
+
+void *memmove(void *dest, const void *src, size_t n);
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+       uint8_t* from = (uint8_t*) src;
+       uint8_t* to = (uint8_t*) dest;
+
+       if (from == to || n == 0)
+               return dest;
+       if (to > from && to-from < (int)n) {
+               /* to overlaps with from */
+               /*  <from......>         */
+               /*         <to........>  */
+               /* copy in reverse, to avoid overwriting from */
+               int i;
+               for(i=n-1; i>=0; i--)
+                       to[i] = from[i];
+               return dest;
+       }
+       if (from > to  && from-to < (int)n) {
+               /* to overlaps with from */
+               /*        <from......>   */
+               /*  <to........>         */
+               /* copy forwards, to avoid overwriting from */
+               size_t i;
+               for(i=0; i<n; i++)
+                       to[i] = from[i];
+               return dest;
+       }
+       memcpy(dest, src, n);
+       return dest;
+}
diff --git a/contrib/ldns/compat/realloc.c b/contrib/ldns/compat/realloc.c
new file mode 100644 (file)
index 0000000..bdaf76d
--- /dev/null
@@ -0,0 +1,30 @@
+/* Just a replacement, if the original malloc is not
+   GNU-compliant. Based on malloc.c */
+
+#if HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+#undef realloc
+
+#include <sys/types.h>
+
+void *realloc (void*, size_t);
+void *malloc (size_t);
+
+/* Changes allocation to new sizes, copies over old data.
+ * if oldptr is NULL, does a malloc.
+ * if size is zero, allocate 1-byte block....
+ *   (does not return NULL and free block)
+ */
+
+void *
+rpl_realloc (void* ptr, size_t n)
+{
+  if (n == 0)
+    n = 1;
+  if(ptr == 0) {
+    return malloc(n);
+  }
+  return realloc(ptr, n);
+}
+
diff --git a/contrib/ldns/compat/snprintf.c b/contrib/ldns/compat/snprintf.c
new file mode 100644 (file)
index 0000000..c668dae
--- /dev/null
@@ -0,0 +1,770 @@
+#include <ldns/config.h>
+
+#ifndef HAVE_SNPRINTF
+
+#include <ctype.h>
+#include <sys/types.h>
+
+/* Define this as a fall through, HAVE_STDARG_H is probably already set */
+
+#define HAVE_VARARGS_H
+
+/**************************************************************
+ * Original:
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
+ * A bombproof version of doprnt (dopr) included.
+ * Sigh.  This sort of thing is always nasty do deal with.  Note that
+ * the version here does not include floating point...
+ *
+ * snprintf() is used instead of sprintf() as it does limit checks
+ * for string length.  This covers a nasty loophole.
+ *
+ * The other functions are there to prevent NULL pointers from
+ * causing nast effects.
+ *
+ * More Recently:
+ *  Brandon Long (blong@fiction.net) 9/15/96 for mutt 0.43
+ *  This was ugly.  It is still ugly.  I opted out of floating point
+ *  numbers, but the formatter understands just about everything
+ *  from the normal C string format, at least as far as I can tell from
+ *  the Solaris 2.5 printf(3S) man page.
+ *
+ *  Brandon Long (blong@fiction.net) 10/22/97 for mutt 0.87.1
+ *    Ok, added some minimal floating point support, which means this
+ *    probably requires libm on most operating systems.  Don't yet
+ *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint()
+ *    was pretty badly broken, it just wasn't being exercised in ways
+ *    which showed it, so that's been fixed.  Also, formated the code
+ *    to mutt conventions, and removed dead code left over from the
+ *    original.  Also, there is now a builtin-test, just compile with:
+ *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
+ *    and run snprintf for results.
+ *
+ **************************************************************/
+
+
+/* varargs declarations: */
+
+#if defined(HAVE_STDARG_H)
+# include <stdarg.h>
+# define HAVE_STDARGS    /* let's hope that works everywhere (mj) */
+# define VA_LOCAL_DECL   va_list ap
+# define VA_START(f)     va_start(ap, f)
+# define VA_SHIFT(v,t)  ;   /* no-op for ANSI */
+# define VA_END          va_end(ap)
+#else
+# if defined(HAVE_VARARGS_H)
+#  include <varargs.h>
+#  undef HAVE_STDARGS
+#  define VA_LOCAL_DECL   va_list ap
+#  define VA_START(f)     va_start(ap)      /* f is ignored! */
+#  define VA_SHIFT(v,t) v = va_arg(ap,t)
+#  define VA_END        va_end(ap)
+# else
+/*XX ** NO VARARGS ** XX*/
+# endif
+#endif
+
+int snprintf (char *str, size_t count, const char *fmt, ...);
+int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
+
+static void dopr (char *buffer, size_t maxlen, const char *format, 
+                  va_list args);
+static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
+                   char *value, int flags, int min, int max);
+static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
+                   long value, int base, int min, int max, int flags);
+static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
+                  long double fvalue, int min, int max, int flags);
+static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
+
+int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
+{
+  str[0] = 0;
+  dopr(str, count, fmt, args);
+  return(strlen(str));
+}
+
+/* VARARGS3 */
+#ifdef HAVE_STDARGS
+int snprintf (char *str,size_t count,const char *fmt,...)
+#else
+int snprintf (va_alist) va_dcl
+#endif
+{
+#ifndef HAVE_STDARGS
+  char *str;
+  size_t count;
+  char *fmt;
+#endif
+  VA_LOCAL_DECL;
+    
+  VA_START (fmt);
+  VA_SHIFT (str, char *);
+  VA_SHIFT (count, size_t );
+  VA_SHIFT (fmt, char *);
+  (void) vsnprintf(str, count, fmt, ap);
+  VA_END;
+  return(strlen(str));
+}
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS   1
+#define DP_S_MIN     2
+#define DP_S_DOT     3
+#define DP_S_MAX     4
+#define DP_S_MOD     5
+#define DP_S_CONV    6
+#define DP_S_DONE    7
+
+/* format flags - Bits */
+#define DP_F_MINUS 1
+#define DP_F_PLUS  2
+#define DP_F_SPACE 4
+#define DP_F_NUM   8
+#define DP_F_ZERO  16
+#define DP_F_UP    32
+
+/* Conversion Flags */
+#define DP_C_SHORT   1
+#define DP_C_LONG    2
+#define DP_C_LDOUBLE 3
+
+#define char_to_int(p) (p - '0')
+#define MAX(p,q) ((p >= q) ? p : q)
+
+static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
+{
+  char ch;
+  long value;
+  long double fvalue;
+  char *strvalue;
+  int min;
+  int max;
+  int state;
+  int flags;
+  int cflags;
+  size_t currlen;
+  
+  state = DP_S_DEFAULT;
+  currlen = flags = cflags = min = 0;
+  max = -1;
+  ch = *format++;
+
+  while (state != DP_S_DONE)
+  {
+    if ((ch == '\0') || (currlen >= maxlen)) 
+      state = DP_S_DONE;
+
+    switch(state) 
+    {
+    case DP_S_DEFAULT:
+      if (ch == '%') 
+       state = DP_S_FLAGS;
+      else 
+       dopr_outch (buffer, &currlen, maxlen, ch);
+      ch = *format++;
+      break;
+    case DP_S_FLAGS:
+      switch (ch) 
+      {
+      case '-':
+       flags |= DP_F_MINUS;
+        ch = *format++;
+       break;
+      case '+':
+       flags |= DP_F_PLUS;
+        ch = *format++;
+       break;
+      case ' ':
+       flags |= DP_F_SPACE;
+        ch = *format++;
+       break;
+      case '#':
+       flags |= DP_F_NUM;
+        ch = *format++;
+       break;
+      case '0':
+       flags |= DP_F_ZERO;
+        ch = *format++;
+       break;
+      default:
+       state = DP_S_MIN;
+       break;
+      }
+      break;
+    case DP_S_MIN:
+      if (isdigit((int) ch)) 
+      {
+       min = 10*min + char_to_int (ch);
+       ch = *format++;
+      } 
+      else if (ch == '*') 
+      {
+       min = va_arg (args, int);
+       ch = *format++;
+       state = DP_S_DOT;
+      } 
+      else 
+       state = DP_S_DOT;
+      break;
+    case DP_S_DOT:
+      if (ch == '.') 
+      {
+       state = DP_S_MAX;
+       ch = *format++;
+      } 
+      else 
+       state = DP_S_MOD;
+      break;
+    case DP_S_MAX:
+      if (isdigit((int) ch)) 
+      {
+       if (max < 0)
+         max = 0;
+       max = 10*max + char_to_int (ch);
+       ch = *format++;
+      } 
+      else if (ch == '*') 
+      {
+       max = va_arg (args, int);
+       ch = *format++;
+       state = DP_S_MOD;
+      } 
+      else 
+       state = DP_S_MOD;
+      break;
+    case DP_S_MOD:
+      /* Currently, we don't support Long Long, bummer */
+      switch (ch) 
+      {
+      case 'h':
+       cflags = DP_C_SHORT;
+       ch = *format++;
+       break;
+      case 'l':
+       cflags = DP_C_LONG;
+       ch = *format++;
+       break;
+      case 'L':
+       cflags = DP_C_LDOUBLE;
+       ch = *format++;
+       break;
+      default:
+       break;
+      }
+      state = DP_S_CONV;
+      break;
+    case DP_S_CONV:
+      switch (ch) 
+      {
+      case 'd':
+      case 'i':
+       if (cflags == DP_C_SHORT) 
+         value = va_arg (args, int);
+       else if (cflags == DP_C_LONG)
+         value = va_arg (args, long int);
+       else
+         value = va_arg (args, int);
+       fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+       break;
+      case 'o':
+       flags &= ~DP_F_PLUS;
+       if (cflags == DP_C_SHORT)
+         value = va_arg (args, unsigned int);
+       else if (cflags == DP_C_LONG)
+         value = va_arg (args, unsigned long int);
+       else
+         value = va_arg (args, unsigned int);
+       fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
+       break;
+      case 'u':
+       flags &= ~DP_F_PLUS;
+       if (cflags == DP_C_SHORT)
+         value = va_arg (args, unsigned int);
+       else if (cflags == DP_C_LONG)
+         value = va_arg (args, unsigned long int);
+       else
+         value = va_arg (args, unsigned int);
+       fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+       break;
+      case 'X':
+       flags |= DP_F_UP;
+      case 'x':
+       flags &= ~DP_F_PLUS;
+       if (cflags == DP_C_SHORT)
+         value = va_arg (args, unsigned int);
+       else if (cflags == DP_C_LONG)
+         value = va_arg (args, unsigned long int);
+       else
+         value = va_arg (args, unsigned int);
+       fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
+       break;
+      case 'f':
+       if (cflags == DP_C_LDOUBLE)
+         fvalue = va_arg (args, long double);
+       else
+         fvalue = va_arg (args, double);
+       /* um, floating point? */
+       fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
+       break;
+      case 'E':
+       flags |= DP_F_UP;
+      case 'e':
+       if (cflags == DP_C_LDOUBLE)
+         fvalue = va_arg (args, long double);
+       else
+         fvalue = va_arg (args, double);
+       break;
+      case 'G':
+       flags |= DP_F_UP;
+      case 'g':
+       if (cflags == DP_C_LDOUBLE)
+         fvalue = va_arg (args, long double);
+       else
+         fvalue = va_arg (args, double);
+       break;
+      case 'c':
+       dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
+       break;
+      case 's':
+       strvalue = va_arg (args, char *);
+       if (max < 0) 
+         max = maxlen; /* ie, no max */
+       fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
+       break;
+      case 'p':
+       strvalue = va_arg (args, void *);
+       fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+       break;
+      case 'n':
+       if (cflags == DP_C_SHORT) 
+       {
+         short int *num;
+         num = va_arg (args, short int *);
+         *num = currlen;
+        } 
+       else if (cflags == DP_C_LONG) 
+       {
+         long int *num;
+         num = va_arg (args, long int *);
+         *num = currlen;
+        } 
+       else 
+       {
+         int *num;
+         num = va_arg (args, int *);
+         *num = currlen;
+        }
+       break;
+      case '%':
+       dopr_outch (buffer, &currlen, maxlen, ch);
+       break;
+      case 'w':
+       /* not supported yet, treat as next char */
+       ch = *format++;
+       break;
+      default:
+       /* Unknown, skip */
+       break;
+      }
+      ch = *format++;
+      state = DP_S_DEFAULT;
+      flags = cflags = min = 0;
+      max = -1;
+      break;
+    case DP_S_DONE:
+      break;
+    default:
+      /* hmm? */
+      break; /* some picky compilers need this */
+    }
+  }
+  if (currlen < maxlen - 1) 
+    buffer[currlen] = '\0';
+  else 
+    buffer[maxlen - 1] = '\0';
+}
+
+static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
+                   char *value, int flags, int min, int max)
+{
+  int padlen, strln;     /* amount to pad */
+  int cnt = 0;
+  
+  if (value == 0)
+  {
+    value = (char *) "<NULL>";
+  }
+
+  for (strln = 0; value[strln]; ++strln); /* strlen */
+  padlen = min - strln;
+  if (padlen < 0) 
+    padlen = 0;
+  if (flags & DP_F_MINUS) 
+    padlen = -padlen; /* Left Justify */
+
+  while ((padlen > 0) && (cnt < max)) 
+  {
+    dopr_outch (buffer, currlen, maxlen, ' ');
+    --padlen;
+    ++cnt;
+  }
+  while (*value && (cnt < max)) 
+  {
+    dopr_outch (buffer, currlen, maxlen, *value++);
+    ++cnt;
+  }
+  while ((padlen < 0) && (cnt < max)) 
+  {
+    dopr_outch (buffer, currlen, maxlen, ' ');
+    ++padlen;
+    ++cnt;
+  }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
+                   long value, int base, int min, int max, int flags)
+{
+  int signvalue = 0;
+  unsigned long uvalue;
+  char convert[20];
+  int place = 0;
+  int spadlen = 0; /* amount to space pad */
+  int zpadlen = 0; /* amount to zero pad */
+  int caps = 0;
+  
+  if (max < 0)
+    max = 0;
+
+  uvalue = value;
+  if( value < 0 ) {
+    signvalue = '-';
+    uvalue = -value;
+  }
+  else
+    if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
+      signvalue = '+';
+    else
+      if (flags & DP_F_SPACE)
+       signvalue = ' ';
+
+  if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
+
+  do {
+    convert[place++] =
+      (caps? "0123456789ABCDEF":"0123456789abcdef")
+      [uvalue % (unsigned)base  ];
+    uvalue = (uvalue / (unsigned)base );
+  } while(uvalue && (place < 20));
+  if (place == 20) place--;
+  convert[place] = 0;
+
+  zpadlen = max - place;
+  spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); 
+  if (zpadlen < 0) zpadlen = 0;
+  if (spadlen < 0) spadlen = 0;
+  if (flags & DP_F_ZERO)
+  {
+    zpadlen = MAX(zpadlen, spadlen);
+    spadlen = 0;
+  }
+  if (flags & DP_F_MINUS) 
+    spadlen = -spadlen; /* Left Justifty */
+
+#ifdef DEBUG_SNPRINTF
+  dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
+      zpadlen, spadlen, min, max, place));
+#endif
+
+  /* Spaces */
+  while (spadlen > 0) 
+  {
+    dopr_outch (buffer, currlen, maxlen, ' ');
+    --spadlen;
+  }
+
+  /* Sign */
+  if (signvalue) 
+    dopr_outch (buffer, currlen, maxlen, signvalue);
+
+  /* Zeros */
+  if (zpadlen > 0) 
+  {
+    while (zpadlen > 0)
+    {
+      dopr_outch (buffer, currlen, maxlen, '0');
+      --zpadlen;
+    }
+  }
+
+  /* Digits */
+  while (place > 0) 
+    dopr_outch (buffer, currlen, maxlen, convert[--place]);
+  
+  /* Left Justified spaces */
+  while (spadlen < 0) {
+    dopr_outch (buffer, currlen, maxlen, ' ');
+    ++spadlen;
+  }
+}
+
+static long double abs_val (long double value)
+{
+  long double result = value;
+
+  if (value < 0)
+    result = -value;
+
+  return result;
+}
+
+static double pow10 (double exp)
+{
+  long double result = 1;
+
+  while (exp)
+  {
+    result *= 10;
+    exp--;
+  }
+  
+  return result;
+}
+
+static double round (double value)
+{
+  long intpart;
+
+  intpart = value;
+  value = value - intpart;
+  if (value >= 0.5)
+    intpart++;
+
+  return intpart;
+}
+
+static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
+                  long double fvalue, int min, int max, int flags)
+{
+  int signvalue = 0;
+  long double ufvalue;
+  char iconvert[20];
+  char fconvert[20];
+  int iplace = 0;
+  int fplace = 0;
+  int padlen = 0; /* amount to pad */
+  int zpadlen = 0; 
+  int caps = 0;
+  long intpart;
+  long fracpart;
+  
+  /* 
+   * AIX manpage says the default is 0, but Solaris says the default
+   * is 6, and sprintf on AIX defaults to 6
+   */
+  if (max < 0)
+    max = 6;
+
+  ufvalue = abs_val (fvalue);
+
+  if (fvalue < 0)
+    signvalue = '-';
+  else
+    if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
+      signvalue = '+';
+    else
+      if (flags & DP_F_SPACE)
+       signvalue = ' ';
+
+#if 0
+  if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
+#endif
+
+  intpart = ufvalue;
+
+  /* 
+   * Sorry, we only support 9 digits past the decimal because of our 
+   * conversion method
+   */
+  if (max > 9)
+    max = 9;
+
+  /* We "cheat" by converting the fractional part to integer by
+   * multiplying by a factor of 10
+   */
+  fracpart = round ((pow10 (max)) * (ufvalue - intpart));
+
+  if (fracpart >= pow10 (max))
+  {
+    intpart++;
+    fracpart -= pow10 (max);
+  }
+
+#ifdef DEBUG_SNPRINTF
+  dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart));
+#endif
+
+  /* Convert integer part */
+  do {
+    iconvert[iplace++] =
+      (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
+    intpart = (intpart / 10);
+  } while(intpart && (iplace < 20));
+  if (iplace == 20) iplace--;
+  iconvert[iplace] = 0;
+
+  /* Convert fractional part */
+  do {
+    fconvert[fplace++] =
+      (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
+    fracpart = (fracpart / 10);
+  } while(fracpart && (fplace < 20));
+  if (fplace == 20) fplace--;
+  fconvert[fplace] = 0;
+
+  /* -1 for decimal point, another -1 if we are printing a sign */
+  padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 
+  zpadlen = max - fplace;
+  if (zpadlen < 0)
+    zpadlen = 0;
+  if (padlen < 0) 
+    padlen = 0;
+  if (flags & DP_F_MINUS) 
+    padlen = -padlen; /* Left Justifty */
+
+  if ((flags & DP_F_ZERO) && (padlen > 0)) 
+  {
+    if (signvalue) 
+    {
+      dopr_outch (buffer, currlen, maxlen, signvalue);
+      --padlen;
+      signvalue = 0;
+    }
+    while (padlen > 0)
+    {
+      dopr_outch (buffer, currlen, maxlen, '0');
+      --padlen;
+    }
+  }
+  while (padlen > 0)
+  {
+    dopr_outch (buffer, currlen, maxlen, ' ');
+    --padlen;
+  }
+  if (signvalue) 
+    dopr_outch (buffer, currlen, maxlen, signvalue);
+
+  while (iplace > 0) 
+    dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
+
+  /*
+   * Decimal point.  This should probably use locale to find the correct
+   * char to print out.
+   */
+  dopr_outch (buffer, currlen, maxlen, '.');
+
+  while (fplace > 0) 
+    dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
+
+  while (zpadlen > 0)
+  {
+    dopr_outch (buffer, currlen, maxlen, '0');
+    --zpadlen;
+  }
+
+  while (padlen < 0) 
+  {
+    dopr_outch (buffer, currlen, maxlen, ' ');
+    ++padlen;
+  }
+}
+
+static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
+{
+  if (*currlen < maxlen)
+    buffer[(*currlen)++] = c;
+}
+
+#ifdef TEST_SNPRINTF
+#ifndef LONG_STRING
+#define LONG_STRING 1024
+#endif
+int main (void)
+{
+  char buf1[LONG_STRING];
+  char buf2[LONG_STRING];
+  char *fp_fmt[] = {
+    "%-1.5f",
+    "%1.5f",
+    "%123.9f",
+    "%10.5f",
+    "% 10.5f",
+    "%+22.9f",
+    "%+4.9f",
+    "%01.3f",
+    "%4f",
+    "%3.1f",
+    "%3.2f",
+    NULL
+  };
+  double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 
+    0.9996, 1.996, 4.136, 0};
+  char *int_fmt[] = {
+    "%-1.5d",
+    "%1.5d",
+    "%123.9d",
+    "%5.5d",
+    "%10.5d",
+    "% 10.5d",
+    "%+22.33d",
+    "%01.3d",
+    "%4d",
+    NULL
+  };
+  long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
+  int x, y;
+  int fail = 0;
+  int num = 0;
+
+  printf ("Testing snprintf format codes against system sprintf...\n");
+
+  for (x = 0; fp_fmt[x] != NULL ; x++)
+    for (y = 0; fp_nums[y] != 0 ; y++)
+    {
+      snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
+      sprintf (buf2, fp_fmt[x], fp_nums[y]);
+      if (strcmp (buf1, buf2))
+      {
+       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n", 
+           fp_fmt[x], buf1, buf2);
+       fail++;
+      }
+      num++;
+    }
+
+  for (x = 0; int_fmt[x] != NULL ; x++)
+    for (y = 0; int_nums[y] != 0 ; y++)
+    {
+      snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
+      sprintf (buf2, int_fmt[x], int_nums[y]);
+      if (strcmp (buf1, buf2))
+      {
+       printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n", 
+           int_fmt[x], buf1, buf2);
+       fail++;
+      }
+      num++;
+    }
+  printf ("%d tests failed out of %d.\n", fail, num);
+}
+#endif /* SNPRINTF_TEST */
+
+#endif /* !HAVE_SNPRINTF */
diff --git a/contrib/ldns/compat/strlcpy.c b/contrib/ldns/compat/strlcpy.c
new file mode 100644 (file)
index 0000000..d6c34c1
--- /dev/null
@@ -0,0 +1,57 @@
+/* from openssh 4.3p2 compat/strlcpy.c */
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */
+
+#include <ldns/config.h>
+#ifndef HAVE_STRLCPY
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+       char *d = dst;
+       const char *s = src;
+       size_t n = siz;
+
+       /* Copy as many bytes as will fit */
+       if (n != 0 && --n != 0) {
+               do {
+                       if ((*d++ = *s++) == 0)
+                               break;
+               } while (--n != 0);
+       }
+
+       /* Not enough room in dst, add NUL and traverse rest of src */
+       if (n == 0) {
+               if (siz != 0)
+                       *d = '\0';              /* NUL-terminate dst */
+               while (*s++)
+                       ;
+       }
+
+       return(s - src - 1);    /* count does not include NUL */
+}
+
+#endif /* !HAVE_STRLCPY */
diff --git a/contrib/ldns/compat/timegm.c b/contrib/ldns/compat/timegm.c
new file mode 100644 (file)
index 0000000..97e1e54
--- /dev/null
@@ -0,0 +1,31 @@
+#ifdef HAVE_CONFIG_H
+#include <ldns/config.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <time.h>
+
+time_t
+timegm (struct tm *tm) {
+       time_t ret;
+       char *tz;
+       
+       tz = getenv("TZ");
+       putenv((char*)"TZ=");
+       tzset();
+       ret = mktime(tm);
+       if (tz) {
+               char buf[256];
+               snprintf(buf, sizeof(buf), "TZ=%s", tz);
+               putenv(tz);
+       }
+       else
+               putenv((char*)"TZ");
+       tzset();
+       return ret;
+}
diff --git a/contrib/ldns/dname.c b/contrib/ldns/dname.c
new file mode 100644 (file)
index 0000000..e5c8031
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * dname.c
+ *
+ * dname specific rdata implementations
+ * A dname is a rdf structure with type LDNS_RDF_TYPE_DNAME
+ * It is not a /real/ type! All function must therefor check
+ * for LDNS_RDF_TYPE_DNAME.
+ *
+ * a Net::DNS like library for C
+ *
+ * (c) NLnet Labs, 2004-2006
+ *
+ * See the file LICENSE for the license
+ */
+
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+ldns_rdf *
+ldns_dname_cat_clone(const ldns_rdf *rd1, const ldns_rdf *rd2)
+{
+       ldns_rdf *new;
+       uint16_t new_size;
+       uint8_t *buf;
+       uint16_t left_size;
+
+       if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME ||
+                       ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) {
+               return NULL;
+       }
+
+       /* remove root label if it is present at the end of the left
+        * rd, by reducing the size with 1
+        */
+       left_size = ldns_rdf_size(rd1);
+       if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) {
+               left_size--;
+       }
+
+       /* we overwrite the nullbyte of rd1 */
+       new_size = left_size + ldns_rdf_size(rd2);
+       buf = LDNS_XMALLOC(uint8_t, new_size);
+       if (!buf) {
+               return NULL;
+       }
+
+       /* put the two dname's after each other */
+       memcpy(buf, ldns_rdf_data(rd1), left_size);
+       memcpy(buf + left_size, ldns_rdf_data(rd2), ldns_rdf_size(rd2));
+
+       new = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, new_size, buf);
+
+       LDNS_FREE(buf);
+       return new;
+}
+
+ldns_status
+ldns_dname_cat(ldns_rdf *rd1, ldns_rdf *rd2)
+{
+       uint16_t left_size;
+       uint16_t size;
+
+       if (ldns_rdf_get_type(rd1) != LDNS_RDF_TYPE_DNAME ||
+                       ldns_rdf_get_type(rd2) != LDNS_RDF_TYPE_DNAME) {
+               return LDNS_STATUS_ERR;
+       }
+
+       /* remove root label if it is present at the end of the left
+        * rd, by reducing the size with 1
+        */
+       left_size = ldns_rdf_size(rd1);
+       if (left_size > 0 &&ldns_rdf_data(rd1)[left_size - 1] == 0) {
+               left_size--;
+       }
+
+       size = left_size + ldns_rdf_size(rd2);
+
+       ldns_rdf_set_data(rd1, LDNS_XREALLOC(ldns_rdf_data(rd1), uint8_t, size));
+       memcpy(ldns_rdf_data(rd1) + left_size, ldns_rdf_data(rd2),
+                       ldns_rdf_size(rd2));
+       ldns_rdf_set_size(rd1, size);
+
+       return LDNS_STATUS_OK;
+}
+
+ldns_rdf *
+ldns_dname_reverse(const ldns_rdf *d)
+{
+       ldns_rdf *new;
+       ldns_rdf *tmp;
+       ldns_rdf *d_tmp;
+       ldns_status status;
+
+       d_tmp = ldns_rdf_clone(d);
+
+       new = ldns_dname_new_frm_str(".");
+
+       while(ldns_dname_label_count(d_tmp) > 0) {
+               tmp = ldns_dname_label(d_tmp, 0);
+               status = ldns_dname_cat(tmp, new);
+               ldns_rdf_deep_free(new);
+               new = tmp;
+               tmp = ldns_dname_left_chop(d_tmp);
+               ldns_rdf_deep_free(d_tmp);
+               d_tmp = tmp;
+       }
+       ldns_rdf_deep_free(d_tmp);
+
+       return new;
+}
+
+ldns_rdf *
+ldns_dname_clone_from(const ldns_rdf *d, uint16_t n)
+{
+       uint8_t *data;
+       uint8_t label_size;
+       size_t data_size;
+
+       if (!d ||
+           ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME ||
+           ldns_dname_label_count(d) < n) {
+               return NULL;
+       }
+
+       data = ldns_rdf_data(d);
+       data_size = ldns_rdf_size(d);
+       while (n > 0) {
+               label_size = data[0] + 1;
+               data += label_size;
+               if (data_size < label_size) {
+                       /* this label is very broken */
+                       return NULL;
+               }
+               data_size -= label_size;
+               n--;
+       }
+
+       return ldns_dname_new_frm_data(data_size, data);
+}
+
+ldns_rdf *
+ldns_dname_left_chop(const ldns_rdf *d)
+{
+       uint8_t label_pos;
+       ldns_rdf *chop;
+
+       if (!d) {
+               return NULL;
+       }
+
+       if (ldns_rdf_get_type(d) != LDNS_RDF_TYPE_DNAME) {
+               return NULL;
+       }
+       if (ldns_dname_label_count(d) == 0) {
+               /* root label */
+               return NULL;
+       }
+       /* 05blaat02nl00 */
+       label_pos = ldns_rdf_data(d)[0];
+
+       chop = ldns_dname_new_frm_data(ldns_rdf_size(d) - label_pos - 1,
+                       ldns_rdf_data(d) + label_pos + 1);
+       return chop;
+}
+
+uint8_t
+ldns_dname_label_count(const ldns_rdf *r)
+{
+        uint16_t src_pos;
+        uint16_t len;
+        uint8_t i;
+        size_t r_size;
+
+       if (!r) {
+               return 0;
+       }
+
+       i = 0;
+       src_pos = 0;
+       r_size = ldns_rdf_size(r);
+
+       if (ldns_rdf_get_type(r) != LDNS_RDF_TYPE_DNAME) {
+               return 0;
+       } else {
+               len = ldns_rdf_data(r)[src_pos]; /* start of the label */
+
+               /* single root label */
+               if (1 == r_size) {
+                       return 0;
+               } else {
+                       while ((len > 0) && src_pos < r_size) {
+                               src_pos++;
+                               src_pos += len;
+                               len = ldns_rdf_data(r)[src_pos];
+                               i++;
+                       }
+               }
+       }
+       return i;
+}
+
+ldns_rdf *
+ldns_dname_new(uint16_t s, void *d)
+{
+        ldns_rdf *rd;
+
+        rd = LDNS_MALLOC(ldns_rdf);
+        if (!rd) {
+                return NULL;
+        }
+        ldns_rdf_set_size(rd, s);
+        ldns_rdf_set_type(rd, LDNS_RDF_TYPE_DNAME);
+        ldns_rdf_set_data(rd, d);
+        return rd;
+}
+
+ldns_rdf *
+ldns_dname_new_frm_str(const char *str)
+{
+       return ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, str);
+}
+
+ldns_rdf *
+ldns_dname_new_frm_data(uint16_t size, const void *data)
+{
+       return ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, size, data);
+}
+
+void
+ldns_dname2canonical(const ldns_rdf *rd)
+{
+       uint8_t *rdd;
+       uint16_t i;
+
+       if (ldns_rdf_get_type(rd) != LDNS_RDF_TYPE_DNAME) {
+               return;
+       }
+
+       rdd = (uint8_t*)ldns_rdf_data(rd);
+       for (i = 0; i < ldns_rdf_size(rd); i++, rdd++) {
+               *rdd = (uint8_t)LDNS_DNAME_NORMALIZE((int)*rdd);
+       }
+}
+
+bool
+ldns_dname_is_subdomain(const ldns_rdf *sub, const ldns_rdf *parent)
+{
+       uint8_t sub_lab;
+       uint8_t par_lab;
+       int8_t i, j;
+       ldns_rdf *tmp_sub = NULL;
+       ldns_rdf *tmp_par = NULL;
+    ldns_rdf *sub_clone;
+    ldns_rdf *parent_clone;
+    bool result = true;
+
+       if (ldns_rdf_get_type(sub) != LDNS_RDF_TYPE_DNAME ||
+                       ldns_rdf_get_type(parent) != LDNS_RDF_TYPE_DNAME ||
+                       ldns_rdf_compare(sub, parent) == 0) {
+               return false;
+       }
+
+    /* would be nicer if we do not have to clone... */
+    sub_clone = ldns_dname_clone_from(sub, 0);
+    parent_clone = ldns_dname_clone_from(parent, 0);
+    ldns_dname2canonical(sub_clone);
+    ldns_dname2canonical(parent_clone);
+
+       sub_lab = ldns_dname_label_count(sub_clone);
+       par_lab = ldns_dname_label_count(parent_clone);
+
+       /* if sub sits above parent, it cannot be a child/sub domain */
+       if (sub_lab < par_lab) {
+               result = false;
+       } else {
+               /* check all labels the from the parent labels, from right to left.
+                * When they /all/ match we have found a subdomain
+                */
+               j = sub_lab - 1; /* we count from zero, thank you */
+               for (i = par_lab -1; i >= 0; i--) {
+                       tmp_sub = ldns_dname_label(sub_clone, j);
+                       tmp_par = ldns_dname_label(parent_clone, i);
+                       if (!tmp_sub || !tmp_par) {
+                               /* deep free does null check */
+                               ldns_rdf_deep_free(tmp_sub);
+                               ldns_rdf_deep_free(tmp_par);
+                               result = false;
+                               break;
+                       }
+
+                       if (ldns_rdf_compare(tmp_sub, tmp_par) != 0) {
+                               /* they are not equal */
+                               ldns_rdf_deep_free(tmp_sub);
+                               ldns_rdf_deep_free(tmp_par);
+                               result = false;
+                               break;
+                       }
+                       ldns_rdf_deep_free(tmp_sub);
+                       ldns_rdf_deep_free(tmp_par);
+                       j--;
+               }
+       }
+       ldns_rdf_deep_free(sub_clone);
+       ldns_rdf_deep_free(parent_clone);
+       return result;
+}
+
+int
+ldns_dname_compare(const ldns_rdf *dname1, const ldns_rdf *dname2)
+{
+       size_t lc1, lc2, lc1f, lc2f;
+       size_t i;
+       int result = 0;
+       uint8_t *lp1, *lp2;
+
+       /* see RFC4034 for this algorithm */
+       /* this algorithm assumes the names are normalized to case */
+
+        /* only when both are not NULL we can say anything about them */
+        if (!dname1 && !dname2) {
+                return 0;
+        }
+        if (!dname1 || !dname2) {
+                return -1;
+        }
+       /* asserts must happen later as we are looking in the
+        * dname, which could be NULL. But this case is handled
+        * above
+        */
+       assert(ldns_rdf_get_type(dname1) == LDNS_RDF_TYPE_DNAME);
+       assert(ldns_rdf_get_type(dname2) == LDNS_RDF_TYPE_DNAME);
+
+       lc1 = ldns_dname_label_count(dname1);
+       lc2 = ldns_dname_label_count(dname2);
+
+       if (lc1 == 0 && lc2 == 0) {
+               return 0;
+       }
+       if (lc1 == 0) {
+               return -1;
+       }
+       if (lc2 == 0) {
+               return 1;
+       }
+       lc1--;
+       lc2--;
+       /* we start at the last label */
+       while (true) {
+               /* find the label first */
+               lc1f = lc1;
+               lp1 = ldns_rdf_data(dname1);
+               while (lc1f > 0) {
+                       lp1 += *lp1 + 1;
+                       lc1f--;
+               }
+
+               /* and find the other one */
+               lc2f = lc2;
+               lp2 = ldns_rdf_data(dname2);
+               while (lc2f > 0) {
+                       lp2 += *lp2 + 1;
+                       lc2f--;
+               }
+
+               /* now check the label character for character. */
+               for (i = 1; i < (size_t)(*lp1 + 1); i++) {
+                       if (i > *lp2) {
+                               /* apparently label 1 is larger */
+                               result = 1;
+                               goto done;
+                       }
+                       if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) <
+                           LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) {
+                           result = -1;
+                           goto done;
+                       } else if (LDNS_DNAME_NORMALIZE((int) *(lp1 + i)) >
+                           LDNS_DNAME_NORMALIZE((int) *(lp2 + i))) {
+                           result = 1;
+                           goto done;
+                       }
+               }
+               if (*lp1 < *lp2) {
+                       /* apparently label 2 is larger */
+                       result = -1;
+                       goto done;
+               }
+               if (lc1 == 0 && lc2 > 0) {
+                       result = -1;
+                       goto done;
+               } else if (lc1 > 0 && lc2 == 0) {
+                       result = 1;
+                       goto done;
+               } else if (lc1 == 0 && lc2 == 0) {
+                       result = 0;
+                       goto done;
+               }
+               lc1--;
+               lc2--;
+       }
+
+       done:
+       return result;
+}
+
+int
+ldns_dname_match_wildcard(const ldns_rdf *dname, const ldns_rdf *wildcard)
+{
+       ldns_rdf *wc_chopped;
+       int result;
+       /* check whether it really is a wildcard */
+       if (ldns_dname_label_count(wildcard) > 0 &&
+           ldns_rdf_data(wildcard)[0] == 1 &&
+           ldns_rdf_data(wildcard)[1] == '*') {
+               /* ok, so the dname needs to be a subdomain of the wildcard
+                * without the *
+                */
+               wc_chopped = ldns_dname_left_chop(wildcard);
+               result = (int) ldns_dname_is_subdomain(dname, wc_chopped);
+               ldns_rdf_deep_free(wc_chopped);
+       } else {
+               result = (ldns_dname_compare(dname, wildcard) == 0);
+       }
+       return result;
+}
+
+/* nsec test: does prev <= middle < next
+ * -1 = yes
+ * 0 = error/can't tell
+ * 1 = no
+ */
+int
+ldns_dname_interval(const ldns_rdf *prev, const ldns_rdf *middle,
+               const ldns_rdf *next)
+{
+       int prev_check, next_check;
+
+       assert(ldns_rdf_get_type(prev) == LDNS_RDF_TYPE_DNAME);
+       assert(ldns_rdf_get_type(middle) == LDNS_RDF_TYPE_DNAME);
+       assert(ldns_rdf_get_type(next) == LDNS_RDF_TYPE_DNAME);
+
+       prev_check = ldns_dname_compare(prev, middle);
+       next_check = ldns_dname_compare(middle, next);
+       /* <= next. This cannot be the case for nsec, because then we would
+        * have gotten the nsec of next...
+        */
+       if (next_check == 0) {
+               return 0;
+       }
+
+                       /* <= */
+       if ((prev_check == -1 || prev_check == 0) &&
+                       /* < */
+                       next_check == -1) {
+               return -1;
+       } else {
+               return 1;
+       }
+}
+
+
+bool
+ldns_dname_str_absolute(const char *dname_str)
+{
+       if(dname_str && strcmp(dname_str, ".") == 0)
+               return 1;
+       return (dname_str &&
+               strlen(dname_str) > 1 &&
+               dname_str[strlen(dname_str) - 1] == '.' &&
+               dname_str[strlen(dname_str) - 2] != '\\');
+}
+
+ldns_rdf *
+ldns_dname_label(const ldns_rdf *rdf, uint8_t labelpos)
+{
+       uint8_t labelcnt;
+       uint16_t src_pos;
+       uint16_t len;
+       ldns_rdf *tmpnew;
+       size_t s;
+
+       if (ldns_rdf_get_type(rdf) != LDNS_RDF_TYPE_DNAME) {
+               return NULL;
+       }
+
+       labelcnt = 0;
+       src_pos = 0;
+       s = ldns_rdf_size(rdf);
+
+       len = ldns_rdf_data(rdf)[src_pos]; /* label start */
+       while ((len > 0) && src_pos < s) {
+               if (labelcnt == labelpos) {
+                       /* found our label */
+                       tmpnew = LDNS_MALLOC(ldns_rdf);
+                       if (!tmpnew) {
+                               return NULL;
+                       }
+                       tmpnew->_type = LDNS_RDF_TYPE_DNAME;
+                       tmpnew->_data = LDNS_XMALLOC(uint8_t, len + 2);
+                       if (!tmpnew->_data) {
+                               LDNS_FREE(tmpnew);
+                               return NULL;
+                       }
+                       memset(tmpnew->_data, 0, len + 2);
+                       memcpy(tmpnew->_data, ldns_rdf_data(rdf) + src_pos, len + 1);
+                       tmpnew->_size = len + 2;
+                       return tmpnew;
+               }
+               src_pos++;
+               src_pos += len;
+               len = ldns_rdf_data(rdf)[src_pos];
+               labelcnt++;
+       }
+       return NULL;
+}
diff --git a/contrib/ldns/dnssec.c b/contrib/ldns/dnssec.c
new file mode 100644 (file)
index 0000000..c39985f
--- /dev/null
@@ -0,0 +1,1578 @@
+/*
+ * dnssec.c
+ *
+ * contains the cryptographic function needed for DNSSEC in ldns
+ * The crypto library used is openssl
+ *
+ * (c) NLnet Labs, 2004-2008
+ *
+ * See the file LICENSE for the license
+ */
+
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+#include <ldns/dnssec.h>
+
+#include <strings.h>
+#include <time.h>
+
+#ifdef HAVE_SSL
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#endif
+
+ldns_rr *
+ldns_dnssec_get_rrsig_for_name_and_type(const ldns_rdf *name,
+                                        const ldns_rr_type type,
+                                        const ldns_rr_list *rrs)
+{
+       size_t i;
+       ldns_rr *candidate;
+
+       if (!name || !rrs) {
+               return NULL;
+       }
+
+       for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+               candidate = ldns_rr_list_rr(rrs, i);
+               if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_RRSIG) {
+                       if (ldns_dname_compare(ldns_rr_owner(candidate),
+                                              name) == 0 &&
+                           ldns_rdf2native_int8(ldns_rr_rrsig_typecovered(candidate))
+                           == type
+                           ) {
+                               return candidate;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+ldns_rr *
+ldns_dnssec_get_dnskey_for_rrsig(const ldns_rr *rrsig,
+                                                  const ldns_rr_list *rrs)
+{
+       size_t i;
+       ldns_rr *candidate;
+
+       if (!rrsig || !rrs) {
+               return NULL;
+       }
+
+       for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+               candidate = ldns_rr_list_rr(rrs, i);
+               if (ldns_rr_get_type(candidate) == LDNS_RR_TYPE_DNSKEY) {
+                       if (ldns_dname_compare(ldns_rr_owner(candidate),
+                                              ldns_rr_rrsig_signame(rrsig)) == 0 &&
+                           ldns_rdf2native_int16(ldns_rr_rrsig_keytag(rrsig)) ==
+                           ldns_calc_keytag(candidate)
+                           ) {
+                               return candidate;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+ldns_rdf *
+ldns_nsec_get_bitmap(ldns_rr *nsec) {
+       if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) {
+               return ldns_rr_rdf(nsec, 1);
+       } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) {
+               return ldns_rr_rdf(nsec, 5);
+       } else {
+               return NULL;
+       }
+}
+
+/*return the owner name of the closest encloser for name from the list of rrs */
+/* this is NOT the hash, but the original name! */
+ldns_rdf *
+ldns_dnssec_nsec3_closest_encloser(ldns_rdf *qname,
+                                   ATTR_UNUSED(ldns_rr_type qtype),
+                                   ldns_rr_list *nsec3s)
+{
+       /* remember parameters, they must match */
+       uint8_t algorithm;
+       uint32_t iterations;
+       uint8_t salt_length;
+       uint8_t *salt;
+
+       ldns_rdf *sname, *hashed_sname, *tmp;
+       ldns_rr *ce;
+       bool flag;
+
+       bool exact_match_found;
+       bool in_range_found;
+
+       ldns_status status;
+       ldns_rdf *zone_name;
+
+       size_t nsec_i;
+       ldns_rr *nsec;
+       ldns_rdf *result = NULL;
+       qtype = qtype;
+
+       if (!qname || !nsec3s || ldns_rr_list_rr_count(nsec3s) < 1) {
+               return NULL;
+       }
+
+       nsec = ldns_rr_list_rr(nsec3s, 0);
+       algorithm = ldns_nsec3_algorithm(nsec);
+       salt_length = ldns_nsec3_salt_length(nsec);
+       salt = ldns_nsec3_salt_data(nsec);
+       iterations = ldns_nsec3_iterations(nsec);
+
+       sname = ldns_rdf_clone(qname);
+
+       ce = NULL;
+       flag = false;
+
+       zone_name = ldns_dname_left_chop(ldns_rr_owner(nsec));
+
+       /* algorithm from nsec3-07 8.3 */
+       while (ldns_dname_label_count(sname) > 0) {
+               exact_match_found = false;
+               in_range_found = false;
+
+               hashed_sname = ldns_nsec3_hash_name(sname,
+                                                                        algorithm,
+                                                                        iterations,
+                                                                        salt_length,
+                                                                        salt);
+
+               status = ldns_dname_cat(hashed_sname, zone_name);
+
+               for (nsec_i = 0; nsec_i < ldns_rr_list_rr_count(nsec3s); nsec_i++) {
+                       nsec = ldns_rr_list_rr(nsec3s, nsec_i);
+
+                       /* check values of iterations etc! */
+
+                       /* exact match? */
+                       if (ldns_dname_compare(ldns_rr_owner(nsec), hashed_sname) == 0) {
+                               exact_match_found = true;
+                       } else if (ldns_nsec_covers_name(nsec, hashed_sname)) {
+                               in_range_found = true;
+                       }
+
+               }
+               if (!exact_match_found && in_range_found) {
+                       flag = true;
+               } else if (exact_match_found && flag) {
+                       result = ldns_rdf_clone(sname);
+                       /* RFC 5155: 8.3. 2.** "The proof is complete" */
+                       ldns_rdf_deep_free(hashed_sname);
+                       goto done;
+               } else if (exact_match_found && !flag) {
+                       /* error! */
+                       ldns_rdf_deep_free(hashed_sname);
+                       goto done;
+               } else {
+                       flag = false;
+               }
+
+               ldns_rdf_deep_free(hashed_sname);
+               tmp = sname;
+               sname = ldns_dname_left_chop(sname);
+               ldns_rdf_deep_free(tmp);
+       }
+
+       done:
+       LDNS_FREE(salt);
+       ldns_rdf_deep_free(zone_name);
+       ldns_rdf_deep_free(sname);
+
+       return result;
+}
+
+bool
+ldns_dnssec_pkt_has_rrsigs(const ldns_pkt *pkt)
+{
+       size_t i;
+       for (i = 0; i < ldns_pkt_ancount(pkt); i++) {
+               if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_answer(pkt), i)) ==
+                   LDNS_RR_TYPE_RRSIG) {
+                       return true;
+               }
+       }
+       for (i = 0; i < ldns_pkt_nscount(pkt); i++) {
+               if (ldns_rr_get_type(ldns_rr_list_rr(ldns_pkt_authority(pkt), i)) ==
+                   LDNS_RR_TYPE_RRSIG) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+ldns_rr_list *
+ldns_dnssec_pkt_get_rrsigs_for_name_and_type(const ldns_pkt *pkt,
+                                                                       ldns_rdf *name,
+                                                                       ldns_rr_type type)
+{
+       uint16_t t_netorder;
+       ldns_rr_list *sigs;
+       ldns_rr_list *sigs_covered;
+       ldns_rdf *rdf_t;
+       
+       sigs = ldns_pkt_rr_list_by_name_and_type(pkt,
+                                                                        name,
+                                                                        LDNS_RR_TYPE_RRSIG,
+                                                                        LDNS_SECTION_ANY_NOQUESTION
+                                                                        );
+
+       t_netorder = htons(type); /* rdf are in network order! */
+       rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE, LDNS_RDF_SIZE_WORD, &t_netorder);
+       sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+       
+       ldns_rdf_free(rdf_t);
+       ldns_rr_list_deep_free(sigs);
+
+       return sigs_covered;
+
+}
+
+ldns_rr_list *
+ldns_dnssec_pkt_get_rrsigs_for_type(const ldns_pkt *pkt, ldns_rr_type type)
+{
+       uint16_t t_netorder;
+       ldns_rr_list *sigs;
+       ldns_rr_list *sigs_covered;
+       ldns_rdf *rdf_t;
+
+       sigs = ldns_pkt_rr_list_by_type(pkt,
+                                       LDNS_RR_TYPE_RRSIG,
+                                       LDNS_SECTION_ANY_NOQUESTION
+                                                         );
+
+       t_netorder = htons(type); /* rdf are in network order! */
+       rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE,
+                                        2,
+                                        &t_netorder);
+       sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+
+       ldns_rdf_free(rdf_t);
+       ldns_rr_list_deep_free(sigs);
+
+       return sigs_covered;
+
+}
+
+/* used only on the public key RR */
+uint16_t
+ldns_calc_keytag(const ldns_rr *key)
+{
+       uint16_t ac16;
+       ldns_buffer *keybuf;
+       size_t keysize;
+
+       if (!key) {
+               return 0;
+       }
+
+       if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY &&
+           ldns_rr_get_type(key) != LDNS_RR_TYPE_KEY
+           ) {
+               return 0;
+       }
+
+       /* rdata to buf - only put the rdata in a buffer */
+       keybuf = ldns_buffer_new(LDNS_MIN_BUFLEN); /* grows */
+       if (!keybuf) {
+               return 0;
+       }
+       (void)ldns_rr_rdata2buffer_wire(keybuf, key);
+       /* the current pos in the buffer is the keysize */
+       keysize= ldns_buffer_position(keybuf);
+
+       ac16 = ldns_calc_keytag_raw(ldns_buffer_begin(keybuf), keysize);
+       ldns_buffer_free(keybuf);
+       return ac16;
+}
+
+uint16_t ldns_calc_keytag_raw(uint8_t* key, size_t keysize)
+{
+       unsigned int i;
+       uint32_t ac32;
+       uint16_t ac16;
+
+       if(keysize < 4) {
+               return 0;
+       }
+       /* look at the algorithm field, copied from 2535bis */
+       if (key[3] == LDNS_RSAMD5) {
+               ac16 = 0;
+               if (keysize > 4) {
+                       memmove(&ac16, key + keysize - 3, 2);
+               }
+               ac16 = ntohs(ac16);
+               return (uint16_t) ac16;
+       } else {
+               ac32 = 0;
+               for (i = 0; (size_t)i < keysize; ++i) {
+                       ac32 += (i & 1) ? key[i] : key[i] << 8;
+               }
+               ac32 += (ac32 >> 16) & 0xFFFF;
+               return (uint16_t) (ac32 & 0xFFFF);
+       }
+}
+
+#ifdef HAVE_SSL
+DSA *
+ldns_key_buf2dsa(ldns_buffer *key)
+{
+       return ldns_key_buf2dsa_raw((unsigned char*)ldns_buffer_begin(key),
+                                                  ldns_buffer_position(key));
+}
+
+DSA *
+ldns_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;
+       }
+       dsa->p = P;
+       dsa->q = Q;
+       dsa->g = G;
+       dsa->pub_key = Y;
+
+       return dsa;
+}
+
+RSA *
+ldns_key_buf2rsa(ldns_buffer *key)
+{
+       return ldns_key_buf2rsa_raw((unsigned char*)ldns_buffer_begin(key),
+                                                  ldns_buffer_position(key));
+}
+
+RSA *
+ldns_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;
+               /* need some smart comment here XXX*/
+               /* the exponent is too large so it's places
+                * futher...???? */
+               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;
+       }
+       rsa->n = modulus;
+       rsa->e = exponent;
+
+       return rsa;
+}
+
+int
+ldns_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 false;
+       if(!EVP_DigestInit_ex(ctx, md, NULL) ||
+               !EVP_DigestUpdate(ctx, data, len) ||
+               !EVP_DigestFinal_ex(ctx, dest, NULL)) {
+               EVP_MD_CTX_destroy(ctx);
+               return false;
+       }
+       EVP_MD_CTX_destroy(ctx);
+       return true;
+}
+#endif /* HAVE_SSL */
+
+ldns_rr *
+ldns_key_rr2ds(const ldns_rr *key, ldns_hash h)
+{
+       ldns_rdf *tmp;
+       ldns_rr *ds;
+       uint16_t keytag;
+       uint8_t  sha1hash;
+       uint8_t *digest;
+       ldns_buffer *data_buf;
+#ifdef USE_GOST
+       const EVP_MD* md = NULL;
+#endif
+
+       if (ldns_rr_get_type(key) != LDNS_RR_TYPE_DNSKEY) {
+               return NULL;
+       }
+
+       ds = ldns_rr_new();
+       if (!ds) {
+               return NULL;
+       }
+       ldns_rr_set_type(ds, LDNS_RR_TYPE_DS);
+       ldns_rr_set_owner(ds, ldns_rdf_clone(
+                                                                 ldns_rr_owner(key)));
+       ldns_rr_set_ttl(ds, ldns_rr_ttl(key));
+       ldns_rr_set_class(ds, ldns_rr_get_class(key));
+
+       switch(h) {
+       default:
+       case LDNS_SHA1:
+               digest = LDNS_XMALLOC(uint8_t, LDNS_SHA1_DIGEST_LENGTH);
+               if (!digest) {
+                       ldns_rr_free(ds);
+                       return NULL;
+               }
+               break;
+       case LDNS_SHA256:
+               digest = LDNS_XMALLOC(uint8_t, LDNS_SHA256_DIGEST_LENGTH);
+               if (!digest) {
+                       ldns_rr_free(ds);
+                       return NULL;
+               }
+               break;
+       case LDNS_HASH_GOST94:
+#ifdef USE_GOST
+               (void)ldns_key_EVP_load_gost_id();
+               md = EVP_get_digestbyname("md_gost94");
+               if(!md) {
+                       ldns_rr_free(ds);
+                       return NULL;
+               }
+               digest = LDNS_XMALLOC(uint8_t, EVP_MD_size(md));
+               if (!digest) {
+                       ldns_rr_free(ds);
+                       return NULL;
+               }
+#else
+               /* not implemented */
+               ldns_rr_free(ds);
+               return NULL;
+#endif
+               break;
+       }
+
+       data_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+       if (!data_buf) {
+               LDNS_FREE(digest);
+               ldns_rr_free(ds);
+               return NULL;
+       }
+
+       /* keytag */
+       keytag = htons(ldns_calc_keytag((ldns_rr*)key));
+       tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16,
+                                                  sizeof(uint16_t),
+                                                  &keytag);
+       ldns_rr_push_rdf(ds, tmp);
+
+       /* copy the algorithm field */
+       ldns_rr_push_rdf(ds, ldns_rdf_clone( ldns_rr_rdf(key, 2))); 
+
+       /* digest hash type */
+       sha1hash = (uint8_t)h;
+       tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+                                                  sizeof(uint8_t),
+                                                  &sha1hash);
+       ldns_rr_push_rdf(ds, tmp);
+
+       /* digest */
+       /* owner name */
+       tmp = ldns_rdf_clone(ldns_rr_owner(key));
+       ldns_dname2canonical(tmp);
+       if (ldns_rdf2buffer_wire(data_buf, tmp) != LDNS_STATUS_OK) {
+               LDNS_FREE(digest);
+               ldns_buffer_free(data_buf);
+               ldns_rr_free(ds);
+               ldns_rdf_deep_free(tmp);
+               return NULL;
+       }
+       ldns_rdf_deep_free(tmp);
+
+       /* all the rdata's */
+       if (ldns_rr_rdata2buffer_wire(data_buf,
+                                                       (ldns_rr*)key) != LDNS_STATUS_OK) {
+               LDNS_FREE(digest);
+               ldns_buffer_free(data_buf);
+               ldns_rr_free(ds);
+               return NULL;
+       }
+       switch(h) {
+       case LDNS_SHA1:
+               (void) ldns_sha1((unsigned char *) ldns_buffer_begin(data_buf),
+                                (unsigned int) ldns_buffer_position(data_buf),
+                                (unsigned char *) digest);
+
+               tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+                                           LDNS_SHA1_DIGEST_LENGTH,
+                                           digest);
+               ldns_rr_push_rdf(ds, tmp);
+
+               break;
+       case LDNS_SHA256:
+               (void) ldns_sha256((unsigned char *) ldns_buffer_begin(data_buf),
+                                  (unsigned int) ldns_buffer_position(data_buf),
+                                  (unsigned char *) digest);
+               tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+                                           LDNS_SHA256_DIGEST_LENGTH,
+                                           digest);
+               ldns_rr_push_rdf(ds, tmp);
+               break;
+       case LDNS_HASH_GOST94:
+#ifdef USE_GOST
+               if(!ldns_digest_evp((unsigned char *) ldns_buffer_begin(data_buf),
+                               (unsigned int) ldns_buffer_position(data_buf),
+                               (unsigned char *) digest, md)) {
+                       LDNS_FREE(digest);
+                       ldns_buffer_free(data_buf);
+                       ldns_rr_free(ds);
+                       return NULL;
+               }
+               tmp = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+                                           EVP_MD_size(md),
+                                           digest);
+               ldns_rr_push_rdf(ds, tmp);
+#endif
+               break;
+       }
+
+       LDNS_FREE(digest);
+       ldns_buffer_free(data_buf);
+       return ds;
+}
+
+ldns_rdf *
+ldns_dnssec_create_nsec_bitmap(ldns_rr_type rr_type_list[],
+                               size_t size,
+                               ldns_rr_type nsec_type)
+{
+       size_t i;
+       uint8_t *bitmap;
+       uint16_t bm_len = 0;
+       uint16_t i_type;
+       ldns_rdf *bitmap_rdf;
+
+       uint8_t *data = NULL;
+       uint8_t cur_data[32];
+       uint8_t cur_window = 0;
+       uint8_t cur_window_max = 0;
+       uint16_t cur_data_size = 0;
+
+       if (nsec_type != LDNS_RR_TYPE_NSEC &&
+           nsec_type != LDNS_RR_TYPE_NSEC3) {
+               return NULL;
+       }
+
+       i_type = 0;
+       for (i = 0; i < size; i++) {
+               if (i_type < rr_type_list[i])
+                       i_type = rr_type_list[i];
+       }
+       if (i_type < nsec_type) {
+               i_type = nsec_type;
+       }
+
+       bm_len = i_type / 8 + 2;
+       bitmap = LDNS_XMALLOC(uint8_t, bm_len);
+       for (i = 0; i < bm_len; i++) {
+               bitmap[i] = 0;
+       }
+
+       for (i = 0; i < size; i++) {
+               i_type = rr_type_list[i];
+               ldns_set_bit(bitmap + (int) i_type / 8,
+                                  (int) (7 - (i_type % 8)),
+                                  true);
+       }
+
+       /* fold it into windows TODO: can this be done directly? */
+       memset(cur_data, 0, 32);
+       for (i = 0; i < bm_len; i++) {
+               if (i / 32 > cur_window) {
+                       /* check, copy, new */
+                       if (cur_window_max > 0) {
+                               /* this window has stuff, add it */
+                               data = LDNS_XREALLOC(data,
+                                                                uint8_t,
+                                                                cur_data_size + cur_window_max + 3);
+                               data[cur_data_size] = cur_window;
+                               data[cur_data_size + 1] = cur_window_max + 1;
+                               memcpy(data + cur_data_size + 2,
+                                         cur_data,
+                                         cur_window_max+1);
+                               cur_data_size += cur_window_max + 3;
+                       }
+                       cur_window++;
+                       cur_window_max = 0;
+                       memset(cur_data, 0, 32);
+               }
+               cur_data[i%32] = bitmap[i];
+               if (bitmap[i] > 0) {
+                       cur_window_max = i%32;
+               }
+       }
+       if (cur_window_max > 0 || cur_data[0] != 0) {
+               /* this window has stuff, add it */
+               data = LDNS_XREALLOC(data,
+                                                uint8_t,
+                                                cur_data_size + cur_window_max + 3);
+               data[cur_data_size] = cur_window;
+               data[cur_data_size + 1] = cur_window_max + 1;
+               memcpy(data + cur_data_size + 2, cur_data, cur_window_max+1);
+               cur_data_size += cur_window_max + 3;
+       }
+
+       bitmap_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC,
+                                                               cur_data_size,
+                                                               data);
+
+       LDNS_FREE(bitmap);
+       LDNS_FREE(data);
+
+       return bitmap_rdf;
+}
+
+int
+ldns_dnssec_rrsets_contains_type(ldns_dnssec_rrsets *rrsets,
+                                 ldns_rr_type type)
+{
+       ldns_dnssec_rrsets *cur_rrset = rrsets;
+       while (cur_rrset) {
+               if (cur_rrset->type == type) {
+                       return 1;
+               }
+               cur_rrset = cur_rrset->next;
+       }
+       return 0;
+}
+
+/* returns true if the current dnssec_rrset from the given list of rrsets
+ * is glue */
+static int
+is_glue(ldns_dnssec_rrsets *cur_rrsets, ldns_dnssec_rrsets *orig_rrsets)
+{
+       /* only glue if a or aaaa if there are no ns, unless there is soa */
+       return (cur_rrsets->type == LDNS_RR_TYPE_A ||
+               cur_rrsets->type ==  LDNS_RR_TYPE_AAAA) &&
+               (ldns_dnssec_rrsets_contains_type(orig_rrsets,
+                     LDNS_RR_TYPE_NS) &&
+               !ldns_dnssec_rrsets_contains_type(orig_rrsets,
+                     LDNS_RR_TYPE_SOA));
+}
+
+ldns_rr *
+ldns_dnssec_create_nsec(ldns_dnssec_name *from,
+                        ldns_dnssec_name *to,
+                        ldns_rr_type nsec_type)
+{
+       ldns_rr *nsec_rr;
+       ldns_rr_type types[65535];
+       size_t type_count = 0;
+       ldns_dnssec_rrsets *cur_rrsets;
+
+       if (!from || !to || (nsec_type != LDNS_RR_TYPE_NSEC &&
+                                        nsec_type != LDNS_RR_TYPE_NSEC3)) {
+               return NULL;
+       }
+
+       nsec_rr = ldns_rr_new();
+       ldns_rr_set_type(nsec_rr, nsec_type);
+       ldns_rr_set_owner(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(from)));
+       ldns_rr_push_rdf(nsec_rr, ldns_rdf_clone(ldns_dnssec_name_name(to)));
+
+       cur_rrsets = from->rrsets;
+       while (cur_rrsets) {
+               if (is_glue(cur_rrsets, from->rrsets)) {
+                       cur_rrsets = cur_rrsets->next;
+                       continue;
+               }
+               types[type_count] = cur_rrsets->type;
+               type_count++;
+               cur_rrsets = cur_rrsets->next;
+       }
+       types[type_count] = LDNS_RR_TYPE_RRSIG;
+       type_count++;
+       types[type_count] = LDNS_RR_TYPE_NSEC;
+       type_count++;
+
+       ldns_rr_push_rdf(nsec_rr, ldns_dnssec_create_nsec_bitmap(types,
+                                      type_count,
+                                      nsec_type));
+
+       return nsec_rr;
+}
+
+ldns_rr *
+ldns_dnssec_create_nsec3(ldns_dnssec_name *from,
+                                       ldns_dnssec_name *to,
+                                       ldns_rdf *zone_name,
+                                       uint8_t algorithm,
+                                       uint8_t flags,
+                                       uint16_t iterations,
+                                       uint8_t salt_length,
+                                       uint8_t *salt)
+{
+       ldns_rr *nsec_rr;
+       ldns_rr_type types[65535];
+       size_t type_count = 0;
+       ldns_dnssec_rrsets *cur_rrsets;
+       ldns_status status;
+
+       flags = flags;
+
+       if (!from) {
+               return NULL;
+       }
+
+       nsec_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
+       ldns_rr_set_owner(nsec_rr,
+                         ldns_nsec3_hash_name(ldns_dnssec_name_name(from),
+                         algorithm,
+                         iterations,
+                         salt_length,
+                         salt));
+       status = ldns_dname_cat(ldns_rr_owner(nsec_rr), zone_name);
+       ldns_nsec3_add_param_rdfs(nsec_rr,
+                                 algorithm,
+                                 flags,
+                                 iterations,
+                                 salt_length,
+                                 salt);
+
+       cur_rrsets = from->rrsets;
+       while (cur_rrsets) {
+               if (is_glue(cur_rrsets, from->rrsets)) {
+                       cur_rrsets = cur_rrsets->next;
+                       continue;
+               }
+               types[type_count] = cur_rrsets->type;
+               type_count++;
+               cur_rrsets = cur_rrsets->next;
+       }
+       /* always add rrsig type if this is not an unsigned
+        * delegation
+        */
+       if (type_count > 0 &&
+           !(type_count == 1 && types[0] == LDNS_RR_TYPE_NS)) {
+               types[type_count] = LDNS_RR_TYPE_RRSIG;
+               type_count++;
+       }
+
+       /* leave next rdata empty if they weren't precomputed yet */
+       if (to && to->hashed_name) {
+               (void) ldns_rr_set_rdf(nsec_rr,
+                                      ldns_rdf_clone(to->hashed_name),
+                                      4);
+       } else {
+               (void) ldns_rr_set_rdf(nsec_rr, NULL, 4);
+       }
+
+       ldns_rr_push_rdf(nsec_rr,
+                        ldns_dnssec_create_nsec_bitmap(types,
+                        type_count,
+                        LDNS_RR_TYPE_NSEC3));
+
+       return nsec_rr;
+}
+
+ldns_rr *
+ldns_create_nsec(ldns_rdf *cur_owner, ldns_rdf *next_owner, ldns_rr_list *rrs)
+{
+       /* we do not do any check here - garbage in, garbage out */
+
+       /* the the start and end names - get the type from the
+        * before rrlist */
+
+       /* inefficient, just give it a name, a next name, and a list of rrs */
+       /* we make 1 big uberbitmap first, then windows */
+       /* todo: make something more efficient :) */
+       uint16_t i;
+       ldns_rr *i_rr;
+       uint16_t i_type;
+
+       ldns_rr *nsec = NULL;
+    ldns_rr_type i_type_list[65535];
+       int type_count = 0;
+
+       nsec = ldns_rr_new();
+       ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC);
+       ldns_rr_set_owner(nsec, ldns_rdf_clone(cur_owner));
+       ldns_rr_push_rdf(nsec, ldns_rdf_clone(next_owner));
+
+       for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+               i_rr = ldns_rr_list_rr(rrs, i);
+               if (ldns_rdf_compare(cur_owner,
+                                                ldns_rr_owner(i_rr)) == 0) {
+                       i_type = ldns_rr_get_type(i_rr);
+                       if (type_count == 0 || i_type_list[type_count-1] != i_type) {
+                               i_type_list[type_count] = i_type;
+                               type_count++;
+                       }
+               }
+       }
+
+       i_type_list[type_count] = LDNS_RR_TYPE_RRSIG;
+       type_count++;
+       i_type_list[type_count] = LDNS_RR_TYPE_NSEC;
+       type_count++;
+
+       ldns_rr_push_rdf(nsec,
+                                 ldns_dnssec_create_nsec_bitmap(i_type_list,
+                                               type_count, LDNS_RR_TYPE_NSEC));
+
+       return nsec;
+}
+
+ldns_rdf *
+ldns_nsec3_hash_name(ldns_rdf *name,
+                                uint8_t algorithm,
+                                uint16_t iterations,
+                                uint8_t salt_length,
+                                uint8_t *salt)
+{
+       size_t hashed_owner_str_len;
+       ldns_rdf *cann;
+       ldns_rdf *hashed_owner;
+       unsigned char *hashed_owner_str;
+       char *hashed_owner_b32;
+       size_t hashed_owner_b32_len;
+       uint32_t cur_it;
+       /* define to contain the largest possible hash, which is
+        * sha1 at the moment */
+       unsigned char hash[LDNS_SHA1_DIGEST_LENGTH];
+       ldns_status status;
+
+       /* prepare the owner name according to the draft section bla */
+       cann = ldns_rdf_clone(name);
+       if(!cann) {
+               fprintf(stderr, "Memory error\n");
+               return NULL;
+       }
+       ldns_dname2canonical(cann);
+
+       /* TODO: mnemonic list for hash algs SHA-1, default to 1 now (sha1) */
+       algorithm = algorithm;
+
+       hashed_owner_str_len = salt_length + ldns_rdf_size(cann);
+       hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len);
+       memcpy(hashed_owner_str, ldns_rdf_data(cann), ldns_rdf_size(cann));
+       memcpy(hashed_owner_str + ldns_rdf_size(cann), salt, salt_length);
+       ldns_rdf_deep_free(cann);
+
+       for (cur_it = iterations + 1; cur_it > 0; cur_it--) {
+               (void) ldns_sha1((unsigned char *) hashed_owner_str,
+                                (unsigned int) hashed_owner_str_len, hash);
+
+               LDNS_FREE(hashed_owner_str);
+               hashed_owner_str_len = salt_length + LDNS_SHA1_DIGEST_LENGTH;
+               hashed_owner_str = LDNS_XMALLOC(unsigned char, hashed_owner_str_len);
+               if (!hashed_owner_str) {
+                       fprintf(stderr, "Memory error\n");
+                       return NULL;
+               }
+               memcpy(hashed_owner_str, hash, LDNS_SHA1_DIGEST_LENGTH);
+               memcpy(hashed_owner_str + LDNS_SHA1_DIGEST_LENGTH, salt, salt_length);
+               hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH + salt_length;
+       }
+
+       LDNS_FREE(hashed_owner_str);
+       hashed_owner_str = hash;
+       hashed_owner_str_len = LDNS_SHA1_DIGEST_LENGTH;
+
+       hashed_owner_b32 = LDNS_XMALLOC(char,
+                  ldns_b32_ntop_calculate_size(hashed_owner_str_len) + 1);
+        hashed_owner_b32_len = (size_t) ldns_b32_ntop_extended_hex(
+                (uint8_t *) hashed_owner_str,
+                hashed_owner_str_len,
+                hashed_owner_b32,
+                ldns_b32_ntop_calculate_size(hashed_owner_str_len));
+       if (hashed_owner_b32_len < 1) {
+               fprintf(stderr, "Error in base32 extended hex encoding ");
+               fprintf(stderr, "of hashed owner name (name: ");
+               ldns_rdf_print(stderr, name);
+               fprintf(stderr, ", return code: %u)\n",
+                       (unsigned int) hashed_owner_b32_len);
+               LDNS_FREE(hashed_owner_b32);
+               return NULL;
+       }
+       hashed_owner_str_len = hashed_owner_b32_len;
+       hashed_owner_b32[hashed_owner_b32_len] = '\0';
+
+       status = ldns_str2rdf_dname(&hashed_owner, hashed_owner_b32);
+       if (status != LDNS_STATUS_OK) {
+               fprintf(stderr, "Error creating rdf from %s\n", hashed_owner_b32);
+               LDNS_FREE(hashed_owner_b32);
+               return NULL;
+       }
+
+       LDNS_FREE(hashed_owner_b32);
+       return hashed_owner;
+}
+
+void
+ldns_nsec3_add_param_rdfs(ldns_rr *rr,
+                                        uint8_t algorithm,
+                                        uint8_t flags,
+                                        uint16_t iterations,
+                                        uint8_t salt_length,
+                                        uint8_t *salt)
+{
+       ldns_rdf *salt_rdf = NULL;
+       uint8_t *salt_data = NULL;
+       ldns_rdf *old;
+
+       old = ldns_rr_set_rdf(rr,
+                             ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+                                                   1, (void*)&algorithm),
+                             0);
+       if (old) ldns_rdf_deep_free(old);
+
+       old = ldns_rr_set_rdf(rr,
+                             ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+                                                   1, (void*)&flags),
+                             1);
+       if (old) ldns_rdf_deep_free(old);
+
+       old = ldns_rr_set_rdf(rr,
+                          ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
+                                                iterations),
+                             2);
+       if (old) ldns_rdf_deep_free(old);
+
+       salt_data = LDNS_XMALLOC(uint8_t, salt_length + 1);
+       salt_data[0] = salt_length;
+       memcpy(salt_data + 1, salt, salt_length);
+       salt_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT,
+                                                          salt_length + 1,
+                                                          salt_data);
+
+       old = ldns_rr_set_rdf(rr, salt_rdf, 3);
+       if (old) ldns_rdf_deep_free(old);
+       LDNS_FREE(salt_data);
+}
+
+static int
+rr_list_delegation_only(ldns_rdf *origin, ldns_rr_list *rr_list)
+{
+       size_t i;
+       ldns_rr *cur_rr;
+       if (!origin || !rr_list) return 0;
+       for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
+               cur_rr = ldns_rr_list_rr(rr_list, i);
+               if (ldns_dname_compare(ldns_rr_owner(cur_rr), origin) == 0) {
+                       return 0;
+               }
+               if (ldns_rr_get_type(cur_rr) != LDNS_RR_TYPE_NS) {
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+/* this will NOT return the NSEC3  completed, you will have to run the
+   finalize function on the rrlist later! */
+ldns_rr *
+ldns_create_nsec3(ldns_rdf *cur_owner,
+                  ldns_rdf *cur_zone,
+                  ldns_rr_list *rrs,
+                  uint8_t algorithm,
+                  uint8_t flags,
+                  uint16_t iterations,
+                  uint8_t salt_length,
+                  uint8_t *salt,
+                  bool emptynonterminal)
+{
+       size_t i;
+       ldns_rr *i_rr;
+       uint16_t i_type;
+
+       ldns_rr *nsec = NULL;
+       ldns_rdf *hashed_owner = NULL;
+
+       ldns_status status;
+
+    ldns_rr_type i_type_list[1024];
+       int type_count = 0;
+
+       hashed_owner = ldns_nsec3_hash_name(cur_owner,
+                                                                algorithm,
+                                                                iterations,
+                                                                salt_length,
+                                                                salt);
+       status = ldns_dname_cat(hashed_owner, cur_zone);
+
+       nsec = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3);
+       ldns_rr_set_type(nsec, LDNS_RR_TYPE_NSEC3);
+       ldns_rr_set_owner(nsec, hashed_owner);
+
+       ldns_nsec3_add_param_rdfs(nsec,
+                                                algorithm,
+                                                flags,
+                                                iterations,
+                                                salt_length,
+                                                salt);
+       (void) ldns_rr_set_rdf(nsec, NULL, 4);
+
+
+       for (i = 0; i < ldns_rr_list_rr_count(rrs); i++) {
+               i_rr = ldns_rr_list_rr(rrs, i);
+               if (ldns_rdf_compare(cur_owner,
+                                                ldns_rr_owner(i_rr)) == 0) {
+                       i_type = ldns_rr_get_type(i_rr);
+                       if (type_count == 0 || i_type_list[type_count-1] != i_type) {
+                               i_type_list[type_count] = i_type;
+                               type_count++;
+                       }
+               }
+       }
+
+       /* add RRSIG anyway, but only if this is not an ENT or
+        * an unsigned delegation */
+       if (!emptynonterminal && !rr_list_delegation_only(cur_zone, rrs)) {
+               i_type_list[type_count] = LDNS_RR_TYPE_RRSIG;
+               type_count++;
+       }
+
+       /* and SOA if owner == zone */
+       if (ldns_dname_compare(cur_zone, cur_owner) == 0) {
+               i_type_list[type_count] = LDNS_RR_TYPE_SOA;
+               type_count++;
+       }
+
+       ldns_rr_push_rdf(nsec,
+                                 ldns_dnssec_create_nsec_bitmap(i_type_list,
+                                               type_count, LDNS_RR_TYPE_NSEC3));
+
+       return nsec;
+}
+
+uint8_t
+ldns_nsec3_algorithm(const ldns_rr *nsec3_rr)
+{
+       if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 &&
+           ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 0)) > 0
+           ) {
+               return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 0));
+       }
+       return 0;
+}
+
+uint8_t
+ldns_nsec3_flags(const ldns_rr *nsec3_rr)
+{
+       if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 &&
+           ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 1)) > 0
+           ) {
+               return ldns_rdf2native_int8(ldns_rr_rdf(nsec3_rr, 1));
+       }
+       return 0;
+}
+
+bool
+ldns_nsec3_optout(const ldns_rr *nsec3_rr)
+{
+       return (ldns_nsec3_flags(nsec3_rr) & LDNS_NSEC3_VARS_OPTOUT_MASK);
+}
+
+uint16_t
+ldns_nsec3_iterations(const ldns_rr *nsec3_rr)
+{
+       if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3 &&
+           ldns_rdf_size(ldns_rr_rdf(nsec3_rr, 2)) > 0
+           ) {
+               return ldns_rdf2native_int16(ldns_rr_rdf(nsec3_rr, 2));
+       }
+       return 0;
+       
+}
+
+ldns_rdf *
+ldns_nsec3_salt(const ldns_rr *nsec3_rr)
+{
+       if (nsec3_rr && ldns_rr_get_type(nsec3_rr) == LDNS_RR_TYPE_NSEC3) {
+               return ldns_rr_rdf(nsec3_rr, 3);
+       }
+       return NULL;
+}
+
+uint8_t
+ldns_nsec3_salt_length(const ldns_rr *nsec3_rr)
+{
+       ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr);
+       if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) {
+               return (uint8_t) ldns_rdf_data(salt_rdf)[0];
+       }
+       return 0;
+}
+
+/* allocs data, free with LDNS_FREE() */
+uint8_t *
+ldns_nsec3_salt_data(const ldns_rr *nsec3_rr)
+{
+       uint8_t salt_length;
+       uint8_t *salt;
+
+       ldns_rdf *salt_rdf = ldns_nsec3_salt(nsec3_rr);
+       if (salt_rdf && ldns_rdf_size(salt_rdf) > 0) {
+               salt_length = ldns_rdf_data(salt_rdf)[0];
+               salt = LDNS_XMALLOC(uint8_t, salt_length);
+               memcpy(salt, &ldns_rdf_data(salt_rdf)[1], salt_length);
+               return salt;
+       }
+       return NULL;
+}
+
+ldns_rdf *
+ldns_nsec3_next_owner(const ldns_rr *nsec3_rr)
+{
+       if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) {
+               return NULL;
+       } else {
+               return ldns_rr_rdf(nsec3_rr, 4);
+       }
+}
+
+ldns_rdf *
+ldns_nsec3_bitmap(const ldns_rr *nsec3_rr)
+{
+       if (!nsec3_rr || ldns_rr_get_type(nsec3_rr) != LDNS_RR_TYPE_NSEC3) {
+               return NULL;
+       } else {
+               return ldns_rr_rdf(nsec3_rr, 5);
+       }
+}
+
+ldns_rdf *
+ldns_nsec3_hash_name_frm_nsec3(const ldns_rr *nsec, ldns_rdf *name)
+{
+       uint8_t algorithm;
+       uint16_t iterations;
+       uint8_t salt_length;
+       uint8_t *salt = 0;
+
+       ldns_rdf *hashed_owner;
+
+       algorithm = ldns_nsec3_algorithm(nsec);
+       salt_length = ldns_nsec3_salt_length(nsec);
+       salt = ldns_nsec3_salt_data(nsec);
+       iterations = ldns_nsec3_iterations(nsec);
+
+       hashed_owner = ldns_nsec3_hash_name(name,
+                                                                algorithm,
+                                                                iterations,
+                                                                salt_length,
+                                                                salt);
+
+       LDNS_FREE(salt);
+       return hashed_owner;
+}
+
+bool
+ldns_nsec_bitmap_covers_type(const ldns_rdf *nsec_bitmap, ldns_rr_type type)
+{
+       uint8_t window_block_nr;
+       uint8_t bitmap_length;
+       uint16_t cur_type;
+       uint16_t pos = 0;
+       uint16_t bit_pos;
+       uint8_t *data = ldns_rdf_data(nsec_bitmap);
+
+       while(pos < ldns_rdf_size(nsec_bitmap)) {
+               window_block_nr = data[pos];
+               bitmap_length = data[pos + 1];
+               pos += 2;
+
+               for (bit_pos = 0; bit_pos < (bitmap_length) * 8; bit_pos++) {
+                       if (ldns_get_bit(&data[pos], bit_pos)) {
+                               cur_type = 256 * (uint16_t) window_block_nr + bit_pos;
+                               if (cur_type == type) {
+                                       return true;
+                               }
+                       }
+               }
+
+               pos += (uint16_t) bitmap_length;
+       }
+       return false;
+}
+
+bool
+ldns_nsec_covers_name(const ldns_rr *nsec, const ldns_rdf *name)
+{
+       ldns_rdf *nsec_owner = ldns_rr_owner(nsec);
+       ldns_rdf *hash_next;
+       char *next_hash_str;
+       ldns_rdf *nsec_next = NULL;
+       ldns_status status;
+       ldns_rdf *chopped_dname;
+       bool result;
+
+       if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC) {
+               nsec_next = ldns_rdf_clone(ldns_rr_rdf(nsec, 0));
+       } else if (ldns_rr_get_type(nsec) == LDNS_RR_TYPE_NSEC3) {
+               hash_next = ldns_nsec3_next_owner(nsec);
+               next_hash_str = ldns_rdf2str(hash_next);
+               nsec_next = ldns_dname_new_frm_str(next_hash_str);
+               LDNS_FREE(next_hash_str);
+               chopped_dname = ldns_dname_left_chop(nsec_owner);
+               status = ldns_dname_cat(nsec_next, chopped_dname);
+               ldns_rdf_deep_free(chopped_dname);
+               if (status != LDNS_STATUS_OK) {
+                       printf("error catting: %s\n", ldns_get_errorstr_by_id(status));
+               }
+       } else {
+               ldns_rdf_deep_free(nsec_next);
+               return false;
+       }
+
+       /* in the case of the last nsec */
+       if(ldns_dname_compare(nsec_owner, nsec_next) > 0) {
+               result = (ldns_dname_compare(nsec_owner, name) <= 0 ||
+                               ldns_dname_compare(name, nsec_next) < 0);
+       } else {
+               result = (ldns_dname_compare(nsec_owner, name) <= 0 &&
+                         ldns_dname_compare(name, nsec_next) < 0);
+       }
+
+       ldns_rdf_deep_free(nsec_next);
+       return result;
+}
+
+#ifdef HAVE_SSL
+/* sig may be null - if so look in the packet */
+ldns_status
+ldns_pkt_verify(ldns_pkt *p, ldns_rr_type t, ldns_rdf *o,
+                        ldns_rr_list *k, ldns_rr_list *s, ldns_rr_list *good_keys)
+{
+       ldns_rr_list *rrset;
+       ldns_rr_list *sigs;
+       ldns_rr_list *sigs_covered;
+       ldns_rdf *rdf_t;
+       ldns_rr_type t_netorder;
+
+       if (!k) {
+               return LDNS_STATUS_ERR;
+               /* return LDNS_STATUS_CRYPTO_NO_DNSKEY; */
+       }
+
+       if (t == LDNS_RR_TYPE_RRSIG) {
+               /* we don't have RRSIG(RRSIG) (yet? ;-) ) */
+               return LDNS_STATUS_ERR;
+       }
+
+       if (s) {
+               /* if s is not NULL, the sigs are given to use */
+               sigs = s;
+       } else {
+               /* otherwise get them from the packet */
+               sigs = ldns_pkt_rr_list_by_name_and_type(p, o, LDNS_RR_TYPE_RRSIG,
+                                                                         LDNS_SECTION_ANY_NOQUESTION);
+               if (!sigs) {
+                       /* no sigs */
+                       return LDNS_STATUS_ERR;
+                       /* return LDNS_STATUS_CRYPTO_NO_RRSIG; */
+               }
+       }
+
+       /* rrsig are subtyped, so now we need to find the correct
+        * sigs for the type t
+        */
+       t_netorder = htons(t); /* rdf are in network order! */
+       /* a type identifier is a 16-bit number, so the size is 2 bytes */
+       rdf_t = ldns_rdf_new(LDNS_RDF_TYPE_TYPE,
+                                        2,
+                                        &t_netorder);
+       sigs_covered = ldns_rr_list_subtype_by_rdf(sigs, rdf_t, 0);
+
+       rrset = ldns_pkt_rr_list_by_name_and_type(p,
+                                                                         o,
+                                                                         t,
+                                                                         LDNS_SECTION_ANY_NOQUESTION);
+
+       if (!rrset) {
+               return LDNS_STATUS_ERR;
+       }
+
+       if (!sigs_covered) {
+               return LDNS_STATUS_ERR;
+       }
+
+       return ldns_verify(rrset, sigs, k, good_keys);
+}
+#endif /* HAVE_SSL */
+
+ldns_status
+ldns_dnssec_chain_nsec3_list(ldns_rr_list *nsec3_rrs)
+{
+       size_t i;
+       char *next_nsec_owner_str;
+       ldns_rdf *next_nsec_owner_label;
+       ldns_rdf *next_nsec_rdf;
+       ldns_status status = LDNS_STATUS_OK;
+
+       for (i = 0; i < ldns_rr_list_rr_count(nsec3_rrs); i++) {
+               if (i == ldns_rr_list_rr_count(nsec3_rrs) - 1) {
+                       next_nsec_owner_label =
+                               ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs,
+                                                                                                         0)), 0);
+                       next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
+                       if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+                           == '.') {
+                               next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+                                       = '\0';
+                       }
+                       status = ldns_str2rdf_b32_ext(&next_nsec_rdf,
+                                                                       next_nsec_owner_str);
+                       if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i),
+                                                        next_nsec_rdf, 4)) {
+                               /* todo: error */
+                       }
+
+                       ldns_rdf_deep_free(next_nsec_owner_label);
+                       LDNS_FREE(next_nsec_owner_str);
+               } else {
+                       next_nsec_owner_label =
+                               ldns_dname_label(ldns_rr_owner(ldns_rr_list_rr(nsec3_rrs,
+                                                                                                         i + 1)),
+                                                         0);
+                       next_nsec_owner_str = ldns_rdf2str(next_nsec_owner_label);
+                       if (next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+                           == '.') {
+                               next_nsec_owner_str[strlen(next_nsec_owner_str) - 1]
+                                       = '\0';
+                       }
+                       status = ldns_str2rdf_b32_ext(&next_nsec_rdf,
+                                                                       next_nsec_owner_str);
+                       ldns_rdf_deep_free(next_nsec_owner_label);
+                       LDNS_FREE(next_nsec_owner_str);
+                       if (!ldns_rr_set_rdf(ldns_rr_list_rr(nsec3_rrs, i),
+                                                        next_nsec_rdf, 4)) {
+                               /* todo: error */
+                       }
+               }
+       }
+       return status;
+}
+
+int
+qsort_rr_compare_nsec3(const void *a, const void *b)
+{
+       const ldns_rr *rr1 = * (const ldns_rr **) a;
+       const ldns_rr *rr2 = * (const ldns_rr **) b;
+       if (rr1 == NULL && rr2 == NULL) {
+               return 0;
+       }
+       if (rr1 == NULL) {
+               return -1;
+       }
+       if (rr2 == NULL) {
+               return 1;
+       }
+       return ldns_rdf_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2));
+}
+
+void
+ldns_rr_list_sort_nsec3(ldns_rr_list *unsorted)
+{
+       qsort(unsorted->_rrs,
+             ldns_rr_list_rr_count(unsorted),
+             sizeof(ldns_rr *),
+             qsort_rr_compare_nsec3);
+}
+
+int
+ldns_dnssec_default_add_to_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_LEAVE_ADD_NEW;
+}
+
+int
+ldns_dnssec_default_leave_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_LEAVE_NO_ADD;
+}
+
+int
+ldns_dnssec_default_delete_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_REMOVE_NO_ADD;
+}
+
+int
+ldns_dnssec_default_replace_signatures(ldns_rr *sig, void *n)
+{
+       sig = sig;
+       n = n;
+       return LDNS_SIGNATURE_REMOVE_ADD_NEW;
+}
+
+#ifdef HAVE_SSL
+ldns_rdf *
+ldns_convert_dsa_rrsig_asn12rdf(const ldns_buffer *sig,
+                                                 const long sig_len)
+{
+       ldns_rdf *sigdata_rdf;
+       DSA_SIG *dsasig;
+       unsigned char *dsasig_data = (unsigned char*)ldns_buffer_begin(sig);
+       size_t byte_offset;
+
+       dsasig = d2i_DSA_SIG(NULL,
+                                        (const unsigned char **)&dsasig_data,
+                                        sig_len);
+       if (!dsasig) {
+               return NULL;
+       }
+
+       dsasig_data = LDNS_XMALLOC(unsigned char, 41);
+       dsasig_data[0] = 0;
+       byte_offset = (size_t) (20 - BN_num_bytes(dsasig->r));
+       if (byte_offset > 20) {
+               return NULL;
+       }
+       memset(&dsasig_data[1], 0, byte_offset);
+       BN_bn2bin(dsasig->r, &dsasig_data[1 + byte_offset]);
+       byte_offset = (size_t) (20 - BN_num_bytes(dsasig->s));
+       if (byte_offset > 20) {
+               return NULL;
+       }
+       memset(&dsasig_data[21], 0, byte_offset);
+       BN_bn2bin(dsasig->s, &dsasig_data[21 + byte_offset]);
+
+       sigdata_rdf = ldns_rdf_new(LDNS_RDF_TYPE_B64, 41, dsasig_data);
+       DSA_SIG_free(dsasig);
+
+       return sigdata_rdf;
+}
+
+ldns_status
+ldns_convert_dsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+                                                 const ldns_rdf *sig_rdf)
+{
+       /* the EVP api wants the DER encoding of the signature... */
+       uint8_t t;
+       BIGNUM *R, *S;
+       DSA_SIG *dsasig;
+       unsigned char *raw_sig = NULL;
+       int raw_sig_len;
+
+       /* extract the R and S field from the sig buffer */
+       t = ldns_rdf_data(sig_rdf)[0];
+       R = BN_new();
+       if(!R) return LDNS_STATUS_MEM_ERR;
+       (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 1,
+                        SHA_DIGEST_LENGTH, R);
+       S = BN_new();
+       if(!S) {
+               BN_free(R);
+               return LDNS_STATUS_MEM_ERR;
+       }
+       (void) BN_bin2bn((unsigned char *) ldns_rdf_data(sig_rdf) + 21,
+                        SHA_DIGEST_LENGTH, S);
+
+       dsasig = DSA_SIG_new();
+       if (!dsasig) {
+               BN_free(R);
+               BN_free(S);
+               return LDNS_STATUS_MEM_ERR;
+       }
+
+       dsasig->r = R;
+       dsasig->s = S;
+
+       raw_sig_len = i2d_DSA_SIG(dsasig, &raw_sig);
+       if (raw_sig_len < 0) {
+               DSA_SIG_free(dsasig);
+               free(raw_sig);
+               return LDNS_STATUS_SSL_ERR;
+       }
+       if (ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
+               ldns_buffer_write(target_buffer, raw_sig, (size_t)raw_sig_len);
+       }
+
+       DSA_SIG_free(dsasig);
+       free(raw_sig);
+
+       return ldns_buffer_status(target_buffer);
+}
+#endif /* HAVE_SSL */
diff --git a/contrib/ldns/dnssec_sign.c b/contrib/ldns/dnssec_sign.c
new file mode 100644 (file)
index 0000000..2b5cad9
--- /dev/null
@@ -0,0 +1,1170 @@
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+#include <ldns/dnssec.h>
+#include <ldns/dnssec_sign.h>
+
+#include <strings.h>
+#include <time.h>
+
+#ifdef HAVE_SSL
+/* this entire file is rather useless when you don't have
+ * crypto...
+ */
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#endif /* HAVE_SSL */
+
+ldns_rr *
+ldns_create_empty_rrsig(ldns_rr_list *rrset,
+                        ldns_key *current_key)
+{
+       uint32_t orig_ttl;
+       ldns_rr_class orig_class;
+       time_t now;
+       ldns_rr *current_sig;
+       uint8_t label_count;
+
+       label_count = ldns_dname_label_count(ldns_rr_owner(ldns_rr_list_rr(rrset,
+                                                          0)));
+       
+       current_sig = ldns_rr_new_frm_type(LDNS_RR_TYPE_RRSIG);
+       
+       /* set the type on the new signature */
+       orig_ttl = ldns_rr_ttl(ldns_rr_list_rr(rrset, 0));
+       orig_class = ldns_rr_get_class(ldns_rr_list_rr(rrset, 0));
+
+       ldns_rr_set_ttl(current_sig, orig_ttl);
+       ldns_rr_set_class(current_sig, orig_class);
+       ldns_rr_set_owner(current_sig, 
+                         ldns_rdf_clone(
+                              ldns_rr_owner(
+                                   ldns_rr_list_rr(rrset,
+                                                   0))));
+
+       /* fill in what we know of the signature */
+       
+       /* set the orig_ttl */
+       (void)ldns_rr_rrsig_set_origttl(
+                  current_sig, 
+                  ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
+                                        orig_ttl));
+       /* the signers name */
+       (void)ldns_rr_rrsig_set_signame(
+                       current_sig, 
+                       ldns_rdf_clone(ldns_key_pubkey_owner(current_key)));
+       /* label count - get it from the first rr in the rr_list */
+       (void)ldns_rr_rrsig_set_labels(
+                       current_sig, 
+                       ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8,
+                                            label_count));
+       /* inception, expiration */
+       now = time(NULL);
+       if (ldns_key_inception(current_key) != 0) {
+               (void)ldns_rr_rrsig_set_inception(
+                               current_sig,
+                               ldns_native2rdf_int32(
+                                   LDNS_RDF_TYPE_TIME, 
+                                   ldns_key_inception(current_key)));
+       } else {
+               (void)ldns_rr_rrsig_set_inception(
+                               current_sig,
+                               ldns_native2rdf_int32(LDNS_RDF_TYPE_TIME, now));
+       }
+       if (ldns_key_expiration(current_key) != 0) {
+               (void)ldns_rr_rrsig_set_expiration(
+                               current_sig,
+                               ldns_native2rdf_int32(
+                                   LDNS_RDF_TYPE_TIME, 
+                                   ldns_key_expiration(current_key)));
+       } else {
+               (void)ldns_rr_rrsig_set_expiration(
+                            current_sig,
+                               ldns_native2rdf_int32(
+                                   LDNS_RDF_TYPE_TIME, 
+                                   now + LDNS_DEFAULT_EXP_TIME));
+       }
+
+       (void)ldns_rr_rrsig_set_keytag(
+                  current_sig,
+                  ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 
+                                        ldns_key_keytag(current_key)));
+
+       (void)ldns_rr_rrsig_set_algorithm(
+                       current_sig,
+                       ldns_native2rdf_int8(
+                           LDNS_RDF_TYPE_ALG, 
+                           ldns_key_algorithm(current_key)));
+
+       (void)ldns_rr_rrsig_set_typecovered(
+                       current_sig,
+                       ldns_native2rdf_int16(
+                           LDNS_RDF_TYPE_TYPE,
+                           ldns_rr_get_type(ldns_rr_list_rr(rrset,
+                                                            0))));
+       return current_sig;
+}
+
+#ifdef HAVE_SSL
+ldns_rdf *
+ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
+{
+       ldns_rdf *b64rdf = NULL;
+
+       switch(ldns_key_algorithm(current_key)) {
+       case LDNS_SIGN_DSA:
+       case LDNS_DSA_NSEC3:
+               b64rdf = ldns_sign_public_evp(
+                                  sign_buf,
+                                  ldns_key_evp_key(current_key),
+                                  EVP_dss1());
+               break;
+       case LDNS_SIGN_RSASHA1:
+       case LDNS_SIGN_RSASHA1_NSEC3:
+               b64rdf = ldns_sign_public_evp(
+                                  sign_buf,
+                                  ldns_key_evp_key(current_key),
+                                  EVP_sha1());
+               break;
+#ifdef USE_SHA2
+       case LDNS_SIGN_RSASHA256:
+               b64rdf = ldns_sign_public_evp(
+                                  sign_buf,
+                                  ldns_key_evp_key(current_key),
+                                  EVP_sha256());
+               break;
+       case LDNS_SIGN_RSASHA512:
+               b64rdf = ldns_sign_public_evp(
+                                  sign_buf,
+                                  ldns_key_evp_key(current_key),
+                                  EVP_sha512());
+               break;
+#endif /* USE_SHA2 */
+#ifdef USE_GOST
+       case LDNS_SIGN_GOST:
+               b64rdf = ldns_sign_public_evp(
+                                  sign_buf,
+                                  ldns_key_evp_key(current_key),
+                                  EVP_get_digestbyname("md_gost94"));
+               break;
+#endif /* USE_GOST */
+       case LDNS_SIGN_RSAMD5:
+               b64rdf = ldns_sign_public_evp(
+                                  sign_buf,
+                                  ldns_key_evp_key(current_key),
+                                  EVP_md5());
+               break;
+       default:
+               /* do _you_ know this alg? */
+               printf("unknown algorithm, ");
+               printf("is the one used available on this system?\n");
+               break;
+       }
+       
+       return b64rdf;
+}
+
+/**
+ * use this function to sign with a public/private key alg
+ * return the created signatures
+ */
+ldns_rr_list *
+ldns_sign_public(ldns_rr_list *rrset, ldns_key_list *keys)
+{
+       ldns_rr_list *signatures;
+       ldns_rr_list *rrset_clone;
+       ldns_rr *current_sig;
+       ldns_rdf *b64rdf;
+       ldns_key *current_key;
+       size_t key_count;
+       uint16_t i;
+       ldns_buffer *sign_buf;
+       ldns_rdf *new_owner;
+
+       if (!rrset || ldns_rr_list_rr_count(rrset) < 1 || !keys) {
+               return NULL;
+       }
+       
+       new_owner = NULL;
+
+       key_count = 0;
+       signatures = ldns_rr_list_new();
+
+       /* prepare a signature and add all the know data
+        * prepare the rrset. Sign this together.  */
+       rrset_clone = ldns_rr_list_clone(rrset);
+       if (!rrset_clone) {
+               return NULL;
+       }
+
+       /* make it canonical */
+       for(i = 0; i < ldns_rr_list_rr_count(rrset_clone); i++) {
+               ldns_rr_set_ttl(ldns_rr_list_rr(rrset_clone, i), 
+                       ldns_rr_ttl(ldns_rr_list_rr(rrset, 0)));
+               ldns_rr2canonical(ldns_rr_list_rr(rrset_clone, i));
+       }
+       /* sort */
+       ldns_rr_list_sort(rrset_clone);
+       
+       for (key_count = 0;
+               key_count < ldns_key_list_key_count(keys);
+               key_count++) {
+               if (!ldns_key_use(ldns_key_list_key(keys, key_count))) {
+                       continue;
+               }
+               sign_buf = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+               if (!sign_buf) {
+                       ldns_rr_list_free(rrset_clone);
+                       ldns_rr_list_free(signatures);
+                       ldns_rdf_free(new_owner);
+                       return NULL;
+               }
+               b64rdf = NULL;
+
+               current_key = ldns_key_list_key(keys, key_count);
+               /* sign all RRs with keys that have ZSKbit, !SEPbit.
+                  sign DNSKEY RRs with keys that have ZSKbit&SEPbit */
+               if (
+                   ldns_key_flags(current_key) & LDNS_KEY_ZONE_KEY &&
+                   (!(ldns_key_flags(current_key) & LDNS_KEY_SEP_KEY)
+                       || ldns_rr_get_type(ldns_rr_list_rr(rrset, 0))
+                       == LDNS_RR_TYPE_DNSKEY)
+                   ) {
+                       current_sig = ldns_create_empty_rrsig(rrset_clone,
+                                                             current_key);
+
+                       /* right now, we have: a key, a semi-sig and an rrset. For
+                        * which we can create the sig and base64 encode that and
+                        * add that to the signature */
+
+                       if (ldns_rrsig2buffer_wire(sign_buf, current_sig)
+                           != LDNS_STATUS_OK) {
+                               ldns_buffer_free(sign_buf);
+                               /* ERROR */
+                               ldns_rr_list_deep_free(rrset_clone);
+                               return NULL;
+                       }
+
+                       /* add the rrset in sign_buf */
+                       if (ldns_rr_list2buffer_wire(sign_buf, rrset_clone)
+                           != LDNS_STATUS_OK) {
+                               ldns_buffer_free(sign_buf);
+                               ldns_rr_list_deep_free(rrset_clone);
+                               return NULL;
+                       }
+
+                       b64rdf = ldns_sign_public_buffer(sign_buf, current_key);
+
+                       if (!b64rdf) {
+                               /* signing went wrong */
+                               ldns_rr_list_deep_free(rrset_clone);
+                               return NULL;
+                       }
+
+                       ldns_rr_rrsig_set_sig(current_sig, b64rdf);
+
+                       /* push the signature to the signatures list */
+                       ldns_rr_list_push_rr(signatures, current_sig);
+               }
+               ldns_buffer_free(sign_buf); /* restart for the next key */
+       }
+       ldns_rr_list_deep_free(rrset_clone);
+
+       return signatures;
+}
+
+/**
+ * Sign data with DSA
+ *
+ * \param[in] to_sign The ldns_buffer containing raw data that is
+ *                    to be signed
+ * \param[in] key The DSA key structure to sign with
+ * \return ldns_rdf for the RRSIG ldns_rr
+ */
+ldns_rdf *
+ldns_sign_public_dsa(ldns_buffer *to_sign, DSA *key)
+{
+       unsigned char *sha1_hash;
+       ldns_rdf *sigdata_rdf;
+       ldns_buffer *b64sig;
+
+       DSA_SIG *sig;
+       uint8_t *data;
+       size_t pad;
+
+       b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+       if (!b64sig) {
+               return NULL;
+       }
+       
+       sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
+                                 ldns_buffer_position(to_sign), NULL);
+       if (!sha1_hash) {
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+
+
+       sig = DSA_do_sign(sha1_hash, SHA_DIGEST_LENGTH, key);
+
+       data = LDNS_XMALLOC(uint8_t, 1 + 2 * SHA_DIGEST_LENGTH);
+
+       data[0] = 1;
+       pad = 20 - (size_t) BN_num_bytes(sig->r);
+       if (pad > 0) {
+               memset(data + 1, 0, pad);
+       }
+       BN_bn2bin(sig->r, (unsigned char *) (data + 1) + pad);
+
+       pad = 20 - (size_t) BN_num_bytes(sig->s);
+       if (pad > 0) {
+               memset(data + 1 + SHA_DIGEST_LENGTH, 0, pad);
+       }
+       BN_bn2bin(sig->s, (unsigned char *) (data + 1 + SHA_DIGEST_LENGTH + pad));
+
+       sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
+                                                                1 + 2 * SHA_DIGEST_LENGTH,
+                                                                data);
+
+       ldns_buffer_free(b64sig);
+       LDNS_FREE(data);
+
+       return sigdata_rdf;
+}
+
+ldns_rdf *
+ldns_sign_public_evp(ldns_buffer *to_sign,
+                                EVP_PKEY *key,
+                                const EVP_MD *digest_type)
+{
+       unsigned int siglen;
+       ldns_rdf *sigdata_rdf;
+       ldns_buffer *b64sig;
+       EVP_MD_CTX ctx;
+       const EVP_MD *md_type;
+       int r;
+
+       siglen = 0;
+       b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+       if (!b64sig) {
+               return NULL;
+       }
+
+       /* initializes a signing context */
+       md_type = digest_type;
+       if(!md_type) {
+               /* unknown message difest */
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+
+       EVP_MD_CTX_init(&ctx);
+       r = EVP_SignInit(&ctx, md_type);
+       if(r == 1) {
+               r = EVP_SignUpdate(&ctx, (unsigned char*)
+                                           ldns_buffer_begin(to_sign), 
+                                           ldns_buffer_position(to_sign));
+       } else {
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+       if(r == 1) {
+               r = EVP_SignFinal(&ctx, (unsigned char*)
+                                          ldns_buffer_begin(b64sig), &siglen, key);
+       } else {
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+       if(r != 1) {
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+
+       /* unfortunately, OpenSSL output is differenct from DNS DSA format */
+       if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
+               sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
+       } else {
+               /* ok output for other types is the same */
+               sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
+                                                                        ldns_buffer_begin(b64sig));
+       }
+       ldns_buffer_free(b64sig);
+       EVP_MD_CTX_cleanup(&ctx);
+       return sigdata_rdf;
+}
+
+ldns_rdf *
+ldns_sign_public_rsasha1(ldns_buffer *to_sign, RSA *key)
+{
+       unsigned char *sha1_hash;
+       unsigned int siglen;
+       ldns_rdf *sigdata_rdf;
+       ldns_buffer *b64sig;
+       int result;
+
+       siglen = 0;
+       b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+       if (!b64sig) {
+               return NULL;
+       }
+
+       sha1_hash = SHA1((unsigned char*)ldns_buffer_begin(to_sign),
+                                 ldns_buffer_position(to_sign), NULL);
+       if (!sha1_hash) {
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+
+       result = RSA_sign(NID_sha1, sha1_hash, SHA_DIGEST_LENGTH,
+                                  (unsigned char*)ldns_buffer_begin(b64sig),
+                                  &siglen, key);
+       if (result != 1) {
+               return NULL;
+       }
+
+       if (result != 1) {
+               return NULL;
+       }
+
+       sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
+                                                                ldns_buffer_begin(b64sig));
+       ldns_buffer_free(b64sig); /* can't free this buffer ?? */
+       return sigdata_rdf;
+}
+
+ldns_rdf *
+ldns_sign_public_rsamd5(ldns_buffer *to_sign, RSA *key)
+{
+       unsigned char *md5_hash;
+       unsigned int siglen;
+       ldns_rdf *sigdata_rdf;
+       ldns_buffer *b64sig;
+
+       b64sig = ldns_buffer_new(LDNS_MAX_PACKETLEN);
+       if (!b64sig) {
+               return NULL;
+       }
+       
+       md5_hash = MD5((unsigned char*)ldns_buffer_begin(to_sign),
+                               ldns_buffer_position(to_sign), NULL);
+       if (!md5_hash) {
+               ldns_buffer_free(b64sig);
+               return NULL;
+       }
+
+       RSA_sign(NID_md5, md5_hash, MD5_DIGEST_LENGTH,
+                   (unsigned char*)ldns_buffer_begin(b64sig),
+                   &siglen, key);
+
+       sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen, 
+                                                                ldns_buffer_begin(b64sig));
+       ldns_buffer_free(b64sig);
+       return sigdata_rdf;
+}
+#endif /* HAVE_SSL */
+
+static int
+ldns_dnssec_name_has_only_a(ldns_dnssec_name *cur_name)
+{
+       ldns_dnssec_rrsets *cur_rrset;
+       cur_rrset = cur_name->rrsets;
+       while (cur_rrset) {
+               if (cur_rrset->type != LDNS_RR_TYPE_A &&
+                       cur_rrset->type != LDNS_RR_TYPE_AAAA) {
+                       return 0;
+               } else {
+                       cur_rrset = cur_rrset->next;
+               }
+       }
+       return 1;
+}
+
+ldns_status
+ldns_dnssec_zone_mark_glue(ldns_dnssec_zone *zone)
+{
+       ldns_rbnode_t *cur_node;
+       ldns_dnssec_name *cur_name;
+       ldns_rdf *cur_owner, *cur_parent;
+
+       cur_node = ldns_rbtree_first(zone->names);
+       while (cur_node != LDNS_RBTREE_NULL) {
+               cur_name = (ldns_dnssec_name *) cur_node->data;
+               cur_node = ldns_rbtree_next(cur_node);
+               if (ldns_dnssec_name_has_only_a(cur_name)) {
+                       /* assume glue XXX check for zone cur */
+                       cur_owner = ldns_rdf_clone(ldns_rr_owner(
+                                             cur_name->rrsets->rrs->rr));
+                       while (ldns_dname_label_count(cur_owner) >
+                                 ldns_dname_label_count(zone->soa->name)) {
+                               if (ldns_dnssec_zone_find_rrset(zone,
+                                                                                 cur_owner,
+                                                                                 LDNS_RR_TYPE_NS)) {
+                                       /*
+                                       fprintf(stderr, "[XX] Marking as glue: ");
+                                       ldns_rdf_print(stderr, cur_name->name);
+                                       fprintf(stderr, "\n");
+                                       */
+                                       cur_name->is_glue = true;
+                               }
+                               cur_parent = ldns_dname_left_chop(cur_owner);
+                               ldns_rdf_deep_free(cur_owner);
+                               cur_owner = cur_parent;
+                       }
+                       ldns_rdf_deep_free(cur_owner);
+               }
+       }
+       return LDNS_STATUS_OK;
+}
+
+ldns_rbnode_t *
+ldns_dnssec_name_node_next_nonglue(ldns_rbnode_t *node)
+{
+       ldns_rbnode_t *next_node = NULL;
+       ldns_dnssec_name *next_name = NULL;
+       bool done = false;
+
+       if (node == LDNS_RBTREE_NULL) {
+               return NULL;
+       }
+       next_node = node;
+       while (!done) {
+               if (next_node == LDNS_RBTREE_NULL) {
+                       return NULL;
+               } else {
+                       next_name = (ldns_dnssec_name *)next_node->data;
+                       if (!next_name->is_glue) {
+                               done = true;
+                       } else {
+                               next_node = ldns_rbtree_next(next_node);
+                       }
+               }
+       }
+       return next_node;
+}
+
+ldns_status
+ldns_dnssec_zone_create_nsecs(ldns_dnssec_zone *zone,
+                              ldns_rr_list *new_rrs)
+{
+
+       ldns_rbnode_t *first_node, *cur_node, *next_node;
+       ldns_dnssec_name *cur_name, *next_name;
+       ldns_rr *nsec_rr;
+       uint32_t nsec_ttl;
+       ldns_dnssec_rrsets *soa;
+       
+       /* the TTL of NSEC rrs should be set to the minimum TTL of
+        * the zone SOA (RFC4035 Section 2.3)
+        */
+       soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
+       
+       /* did the caller actually set it? if not,
+        * fall back to default ttl
+        */
+       if (soa && soa->rrs && soa->rrs->rr) {
+               nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(
+                                                    soa->rrs->rr, 6));
+       } else {
+               nsec_ttl = LDNS_DEFAULT_TTL;
+       }
+       
+       first_node = ldns_dnssec_name_node_next_nonglue(
+                              ldns_rbtree_first(zone->names));
+       cur_node = first_node;
+       if (cur_node) {
+               next_node = ldns_dnssec_name_node_next_nonglue(
+                                  ldns_rbtree_next(cur_node));
+       } else {
+               next_node = NULL;
+       }
+
+       while (cur_node && next_node) {
+               cur_name = (ldns_dnssec_name *)cur_node->data;
+               next_name = (ldns_dnssec_name *)next_node->data;
+               nsec_rr = ldns_dnssec_create_nsec(cur_name,
+                                                 next_name,
+                                                 LDNS_RR_TYPE_NSEC);
+               ldns_rr_set_ttl(nsec_rr, nsec_ttl);
+               ldns_dnssec_name_add_rr(cur_name, nsec_rr);
+               ldns_rr_list_push_rr(new_rrs, nsec_rr);
+               cur_node = next_node;
+               if (cur_node) {
+                       next_node = ldns_dnssec_name_node_next_nonglue(
+                               ldns_rbtree_next(cur_node));
+               }
+       }
+
+       if (cur_node && !next_node) {
+               cur_name = (ldns_dnssec_name *)cur_node->data;
+               next_name = (ldns_dnssec_name *)first_node->data;
+               nsec_rr = ldns_dnssec_create_nsec(cur_name,
+                                                 next_name,
+                                                 LDNS_RR_TYPE_NSEC);
+               ldns_rr_set_ttl(nsec_rr, nsec_ttl);
+               ldns_dnssec_name_add_rr(cur_name, nsec_rr);
+               ldns_rr_list_push_rr(new_rrs, nsec_rr);
+       } else {
+               printf("error\n");
+       }
+
+       return LDNS_STATUS_OK;
+}
+
+#ifdef HAVE_SSL
+ldns_status
+ldns_dnssec_zone_create_nsec3s(ldns_dnssec_zone *zone,
+                                                ldns_rr_list *new_rrs,
+                                                uint8_t algorithm,
+                                                uint8_t flags,
+                                                uint16_t iterations,
+                                                uint8_t salt_length,
+                                                uint8_t *salt)
+{
+       ldns_rbnode_t *first_name_node;
+       ldns_rbnode_t *current_name_node;
+       ldns_dnssec_name *current_name;
+       ldns_status result = LDNS_STATUS_OK;
+       ldns_rr *nsec_rr;
+       ldns_rr_list *nsec3_list;
+       uint32_t nsec_ttl;
+       ldns_dnssec_rrsets *soa;
+       
+       if (!zone || !new_rrs || !zone->names) {
+               return LDNS_STATUS_ERR;
+       }
+       
+       /* the TTL of NSEC rrs should be set to the minimum TTL of
+        * the zone SOA (RFC4035 Section 2.3)
+        */
+       soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);
+       
+       /* did the caller actually set it? if not,
+        * fall back to default ttl
+        */
+       if (soa && soa->rrs && soa->rrs->rr) {
+               nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(
+                                                    soa->rrs->rr, 6));
+       } else {
+               nsec_ttl = LDNS_DEFAULT_TTL;
+       }
+
+       nsec3_list = ldns_rr_list_new();
+
+       first_name_node = ldns_dnssec_name_node_next_nonglue(
+                                         ldns_rbtree_first(zone->names));
+       
+       current_name_node = first_name_node;
+
+       while (current_name_node &&
+              current_name_node != LDNS_RBTREE_NULL) {
+               current_name = (ldns_dnssec_name *) current_name_node->data;
+               nsec_rr = ldns_dnssec_create_nsec3(current_name,
+                                                  NULL,
+                                                  zone->soa->name,
+                                                  algorithm,
+                                                  flags,
+                                                  iterations,
+                                                  salt_length,
+                                                  salt);
+               /* by default, our nsec based generator adds rrsigs
+                * remove the bitmap for empty nonterminals */
+               if (!current_name->rrsets) {
+                       ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
+               }
+               ldns_rr_set_ttl(nsec_rr, nsec_ttl);
+               ldns_dnssec_name_add_rr(current_name, nsec_rr);
+               ldns_rr_list_push_rr(new_rrs, nsec_rr);
+               ldns_rr_list_push_rr(nsec3_list, nsec_rr);
+               current_name_node = ldns_dnssec_name_node_next_nonglue(
+                                  ldns_rbtree_next(current_name_node));
+       }
+
+       ldns_rr_list_sort_nsec3(nsec3_list);
+       ldns_dnssec_chain_nsec3_list(nsec3_list);
+       if (result != LDNS_STATUS_OK) {
+               return result;
+       }
+       
+       ldns_rr_list_free(nsec3_list);
+       return result;
+}
+#endif /* HAVE_SSL */
+
+ldns_dnssec_rrs *
+ldns_dnssec_remove_signatures(ldns_dnssec_rrs *signatures,
+                                               ldns_key_list *key_list,
+                                               int (*func)(ldns_rr *, void *),
+                                               void *arg)
+{
+       ldns_dnssec_rrs *base_rrs = signatures;
+       ldns_dnssec_rrs *cur_rr = base_rrs;
+       ldns_dnssec_rrs *prev_rr = NULL;
+       ldns_dnssec_rrs *next_rr;
+
+       uint16_t keytag;
+       size_t i;
+       int v;
+
+       key_list = key_list;
+
+       if (!cur_rr) {
+               switch(func(NULL, arg)) {
+               case LDNS_SIGNATURE_LEAVE_ADD_NEW:
+               case LDNS_SIGNATURE_REMOVE_ADD_NEW:
+               break;
+               case LDNS_SIGNATURE_LEAVE_NO_ADD:
+               case LDNS_SIGNATURE_REMOVE_NO_ADD:
+               ldns_key_list_set_use(key_list, false);
+               break;
+               default:
+                       fprintf(stderr, "[XX] unknown return value from callback\n");
+                       break;
+               }
+               return NULL;
+       }
+       v = func(cur_rr->rr, arg);
+
+       while (cur_rr) {
+               next_rr = cur_rr->next;
+               
+               switch (func(cur_rr->rr, arg)) {
+               case  LDNS_SIGNATURE_LEAVE_ADD_NEW:
+                       prev_rr = cur_rr;
+                       break;
+               case LDNS_SIGNATURE_LEAVE_NO_ADD:
+                       keytag = ldns_rdf2native_int16(
+                                          ldns_rr_rrsig_keytag(cur_rr->rr));
+                       for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+                               if (ldns_key_keytag(ldns_key_list_key(key_list, i)) ==
+                                   keytag) {
+                                       ldns_key_set_use(ldns_key_list_key(key_list, i),
+                                                                 false);
+                               }
+                       }
+                       prev_rr = cur_rr;
+                       break;
+               case LDNS_SIGNATURE_REMOVE_NO_ADD:
+                       keytag = ldns_rdf2native_int16(
+                                          ldns_rr_rrsig_keytag(cur_rr->rr));
+                       for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
+                               if (ldns_key_keytag(ldns_key_list_key(key_list, i))
+                                   == keytag) {
+                                       ldns_key_set_use(ldns_key_list_key(key_list, i),
+                                                                 false);
+                               }
+                       }
+                       if (prev_rr) {
+                               prev_rr->next = next_rr;
+                       } else {
+                               base_rrs = next_rr;
+                       }
+                       LDNS_FREE(cur_rr);
+                       break;
+               case LDNS_SIGNATURE_REMOVE_ADD_NEW:
+                       if (prev_rr) {
+                               prev_rr->next = next_rr;
+                       } else {
+                               base_rrs = next_rr;
+                       }
+                       LDNS_FREE(cur_rr);
+                       break;
+               default:
+                       fprintf(stderr, "[XX] unknown return value from callback\n");
+                       break;
+               }
+               cur_rr = next_rr;
+       }
+
+       return base_rrs;
+}
+
+#ifdef HAVE_SSL
+ldns_status
+ldns_dnssec_zone_create_rrsigs(ldns_dnssec_zone *zone,
+                               ldns_rr_list *new_rrs,
+                               ldns_key_list *key_list,
+                               int (*func)(ldns_rr *, void*),
+                               void *arg)
+{
+       return ldns_dnssec_zone_create_rrsigs_flg(zone, new_rrs, key_list, 
+               func, arg, 0);
+}
+
+/** If there are KSKs use only them and mark ZSKs unused */
+static void
+ldns_key_list_filter_for_dnskey(ldns_key_list *key_list)
+{
+       int saw_ksk = 0;
+       size_t i;
+       for(i=0; i<ldns_key_list_key_count(key_list); i++)
+               if((ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY)) {
+                       saw_ksk = 1;
+                       break;
+               }
+       if(!saw_ksk)
+               return;
+       for(i=0; i<ldns_key_list_key_count(key_list); i++)
+               if(!(ldns_key_flags(ldns_key_list_key(key_list, i))&LDNS_KEY_SEP_KEY))
+                       ldns_key_set_use(ldns_key_list_key(key_list, i), 0);
+}
+
+ldns_status
+ldns_dnssec_zone_create_rrsigs_flg(ldns_dnssec_zone *zone,
+                               ldns_rr_list *new_rrs,
+                               ldns_key_list *key_list,
+                               int (*func)(ldns_rr *, void*),
+                               void *arg,
+                              int flags)
+{
+       ldns_status result = LDNS_STATUS_OK;
+
+       ldns_rbnode_t *cur_node;
+       ldns_rr_list *rr_list;
+
+       ldns_dnssec_name *cur_name;
+       ldns_dnssec_rrsets *cur_rrset;
+       ldns_dnssec_rrs *cur_rr;
+
+       ldns_rr_list *siglist;
+       
+       size_t i;
+
+       ldns_rr_list *pubkey_list = ldns_rr_list_new();
+       zone = zone;
+       new_rrs = new_rrs;
+       key_list = key_list;
+       for (i = 0; i<ldns_key_list_key_count(key_list); i++) {
+               ldns_rr_list_push_rr(pubkey_list,
+                                                ldns_key2rr(ldns_key_list_key(key_list, i)));
+       }
+       /* TODO: callback to see is list should be signed */
+       /* TODO: remove 'old' signatures from signature list */
+       cur_node = ldns_rbtree_first(zone->names);
+       while (cur_node != LDNS_RBTREE_NULL) {
+               cur_name = (ldns_dnssec_name *) cur_node->data;
+
+               if (!cur_name->is_glue) {
+                       cur_rrset = cur_name->rrsets;
+                       while (cur_rrset) {
+                               /* reset keys to use */
+                               ldns_key_list_set_use(key_list, true);
+                               
+                               /* walk through old sigs, remove the old,
+                                  and mark which keys (not) to use) */
+                               cur_rrset->signatures =
+                                       ldns_dnssec_remove_signatures(cur_rrset->signatures,
+                                                                                       key_list,
+                                                                                       func,
+                                                                                       arg);
+                               if(!(flags&LDNS_SIGN_DNSKEY_WITH_ZSK) &&
+                                       cur_rrset->type == LDNS_RR_TYPE_DNSKEY)
+                                       ldns_key_list_filter_for_dnskey(key_list);
+                               
+                               /* TODO: just set count to zero? */
+                               rr_list = ldns_rr_list_new();
+                               
+                               cur_rr = cur_rrset->rrs;
+                               while (cur_rr) {
+                                       ldns_rr_list_push_rr(rr_list, cur_rr->rr);
+                                       cur_rr = cur_rr->next;
+                               }
+                               
+                               /* only sign non-delegation RRsets */
+                               /* (glue should have been marked earlier) */
+                               if ((ldns_rr_list_type(rr_list) != LDNS_RR_TYPE_NS ||
+                                       ldns_dname_compare(ldns_rr_list_owner(rr_list),
+                                       zone->soa->name) == 0) &&
+                                       /* OK, there is also the possibility that the record
+                                        * is glue, but at the same owner name as other records that
+                                        * are not NS nor A/AAAA. Bleh, our current data structure
+                                        * doesn't really support that... */
+                                       !((ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_A ||
+                                        ldns_rr_list_type(rr_list) == LDNS_RR_TYPE_AAAA) &&
+                                        !ldns_dname_compare(ldns_rr_list_owner(rr_list), zone->soa->name) == 0 &&
+                                        ldns_dnssec_zone_find_rrset(zone, ldns_rr_list_owner(rr_list), LDNS_RR_TYPE_NS)
+                                        )) {
+
+                                       siglist = ldns_sign_public(rr_list, key_list);
+                                       for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
+                                               if (cur_rrset->signatures) {
+                                                       ldns_dnssec_rrs_add_rr(cur_rrset->signatures,
+                                                                                          ldns_rr_list_rr(siglist,
+                                                                                                                   i));
+                                               } else {
+                                                       cur_rrset->signatures = ldns_dnssec_rrs_new();
+                                                       cur_rrset->signatures->rr =
+                                                               ldns_rr_list_rr(siglist, i);
+                                                       ldns_rr_list_push_rr(new_rrs,
+                                                                                        ldns_rr_list_rr(siglist,
+                                                                                                                 i));
+                                               }
+                                       }
+                                       ldns_rr_list_free(siglist);
+                               }
+                               
+                               ldns_rr_list_free(rr_list);
+                               
+                               cur_rrset = cur_rrset->next;
+                       }
+                       
+                       /* sign the nsec */
+                       cur_name->nsec_signatures =
+                               ldns_dnssec_remove_signatures(cur_name->nsec_signatures,
+                                                                               key_list,
+                                                                               func,
+                                                                               arg);
+                       
+                       rr_list = ldns_rr_list_new();
+                       ldns_rr_list_push_rr(rr_list, cur_name->nsec);
+                       siglist = ldns_sign_public(rr_list, key_list);
+                       
+                       for (i = 0; i < ldns_rr_list_rr_count(siglist); i++) {
+                               if (cur_name->nsec_signatures) {
+                                       ldns_dnssec_rrs_add_rr(cur_name->nsec_signatures,
+                                                                          ldns_rr_list_rr(siglist, i));
+                               } else {
+                                       cur_name->nsec_signatures = ldns_dnssec_rrs_new();
+                                       cur_name->nsec_signatures->rr =
+                                               ldns_rr_list_rr(siglist, i);
+                                       ldns_rr_list_push_rr(new_rrs,
+                                                                        ldns_rr_list_rr(siglist, i));
+                               }
+                       }
+                       
+                       ldns_rr_list_free(siglist);
+                       ldns_rr_list_free(rr_list);
+               }
+               cur_node = ldns_rbtree_next(cur_node);
+       }
+
+       ldns_rr_list_deep_free(pubkey_list);
+       return result;
+}
+
+ldns_status
+ldns_dnssec_zone_sign(ldns_dnssec_zone *zone,
+                                 ldns_rr_list *new_rrs,
+                                 ldns_key_list *key_list,
+                                 int (*func)(ldns_rr *, void *),
+                                 void *arg)
+{
+       return ldns_dnssec_zone_sign_flg(zone, new_rrs, key_list, func, arg, 0);
+}
+
+ldns_status
+ldns_dnssec_zone_sign_flg(ldns_dnssec_zone *zone,
+                                 ldns_rr_list *new_rrs,
+                                 ldns_key_list *key_list,
+                                 int (*func)(ldns_rr *, void *),
+                                 void *arg,
+                                 int flags)
+{
+       ldns_status result = LDNS_STATUS_OK;
+
+       if (!zone || !new_rrs || !key_list) {
+               return LDNS_STATUS_ERR;
+       }
+
+       /* zone is already sorted */
+       ldns_dnssec_zone_mark_glue(zone);
+       
+       /* check whether we need to add nsecs */
+       if (zone->names && !((ldns_dnssec_name *)zone->names->root->data)->nsec) {
+               result = ldns_dnssec_zone_create_nsecs(zone, new_rrs);
+               if (result != LDNS_STATUS_OK) {
+                       return result;
+               }
+       }
+
+       result = ldns_dnssec_zone_create_rrsigs_flg(zone,
+                                       new_rrs,
+                                       key_list,
+                                       func,
+                                       arg,
+                                       flags);
+
+       return result;
+}
+
+ldns_status
+ldns_dnssec_zone_sign_nsec3(ldns_dnssec_zone *zone,
+                                          ldns_rr_list *new_rrs,
+                                          ldns_key_list *key_list,
+                                          int (*func)(ldns_rr *, void *),
+                                          void *arg,
+                                          uint8_t algorithm,
+                                          uint8_t flags,
+                                          uint16_t iterations,
+                                          uint8_t salt_length,
+                                          uint8_t *salt)
+{
+       return ldns_dnssec_zone_sign_nsec3_flg(zone, new_rrs, key_list,
+               func, arg, algorithm, flags, iterations, salt_length, salt, 0);
+}
+
+ldns_status
+ldns_dnssec_zone_sign_nsec3_flg(ldns_dnssec_zone *zone,
+                                          ldns_rr_list *new_rrs,
+                                          ldns_key_list *key_list,
+                                          int (*func)(ldns_rr *, void *),
+                                          void *arg,
+                                          uint8_t algorithm,
+                                          uint8_t flags,
+                                          uint16_t iterations,
+                                          uint8_t salt_length,
+                                          uint8_t *salt,
+                                          int signflags)
+{
+       ldns_rr *nsec3, *nsec3params;
+       ldns_status result = LDNS_STATUS_OK;
+
+       /* zone is already sorted */
+       ldns_dnssec_zone_mark_glue(zone);
+
+       /* TODO if there are already nsec3s presents and their
+        * parameters are the same as these, we don't have to recreate
+        */
+       if (zone->names) {
+               /* add empty nonterminals */
+               ldns_dnssec_zone_add_empty_nonterminals(zone);
+
+               nsec3 = ((ldns_dnssec_name *)zone->names->root->data)->nsec;
+               if (nsec3 && ldns_rr_get_type(nsec3) == LDNS_RR_TYPE_NSEC3) {
+                       /* no need to recreate */
+               } else {
+                       if (!ldns_dnssec_zone_find_rrset(zone,
+                                                                          zone->soa->name,
+                                                                          LDNS_RR_TYPE_NSEC3PARAMS)) {
+                               /* create and add the nsec3params rr */
+                               nsec3params =
+                                       ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
+                               ldns_rr_set_owner(nsec3params,
+                                                          ldns_rdf_clone(zone->soa->name));
+                               ldns_nsec3_add_param_rdfs(nsec3params,
+                                                                        algorithm,
+                                                                        flags,
+                                                                        iterations,
+                                                                        salt_length,
+                                                                        salt);
+                               /* always set bit 7 of the flags to zero, according to
+                                * rfc5155 section 11 */
+                               ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params, 1)), 7, 0);
+                               ldns_dnssec_zone_add_rr(zone, nsec3params);
+                               ldns_rr_list_push_rr(new_rrs, nsec3params);
+                       }
+                       result = ldns_dnssec_zone_create_nsec3s(zone,
+                                                                                       new_rrs,
+                                                                                       algorithm,
+                                                                                       flags,
+                                                                                       iterations,
+                                                                                       salt_length,
+                                                                                       salt);
+                       if (result != LDNS_STATUS_OK) {
+                               return result;
+                       }
+               }
+
+               result = ldns_dnssec_zone_create_rrsigs_flg(zone,
+                                               new_rrs,
+                                               key_list,
+                                               func,
+                                               arg,
+                                               signflags);
+       }
+       
+       return result;
+}
+
+
+ldns_zone *
+ldns_zone_sign(const ldns_zone *zone, ldns_key_list *key_list)
+{
+       ldns_dnssec_zone *dnssec_zone;
+       ldns_zone *signed_zone;
+       ldns_rr_list *new_rrs;
+       size_t i;
+
+       signed_zone = ldns_zone_new();
+       dnssec_zone = ldns_dnssec_zone_new();
+
+       (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
+       ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone));
+       
+       for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
+               (void) ldns_dnssec_zone_add_rr(dnssec_zone,
+                                                                ldns_rr_list_rr(ldns_zone_rrs(zone),
+                                                                                         i));
+               ldns_zone_push_rr(signed_zone, 
+                                          ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
+                                                                                          i)));
+       }
+
+       new_rrs = ldns_rr_list_new();
+       (void) ldns_dnssec_zone_sign(dnssec_zone,
+                                                   new_rrs,
+                                                   key_list,
+                                                   ldns_dnssec_default_replace_signatures,
+                                                   NULL);
+
+       for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
+               ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
+                                                ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
+       }
+
+       ldns_rr_list_deep_free(new_rrs);
+       ldns_dnssec_zone_free(dnssec_zone);
+
+       return signed_zone;
+}
+
+ldns_zone *
+ldns_zone_sign_nsec3(ldns_zone *zone, ldns_key_list *key_list, uint8_t algorithm, uint8_t flags, uint16_t iterations, uint8_t salt_length, uint8_t *salt)
+{
+       ldns_dnssec_zone *dnssec_zone;
+       ldns_zone *signed_zone;
+       ldns_rr_list *new_rrs;
+       size_t i;
+
+       signed_zone = ldns_zone_new();
+       dnssec_zone = ldns_dnssec_zone_new();
+
+       (void) ldns_dnssec_zone_add_rr(dnssec_zone, ldns_zone_soa(zone));
+       ldns_zone_set_soa(signed_zone, ldns_zone_soa(zone));
+       
+       for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
+               (void) ldns_dnssec_zone_add_rr(dnssec_zone,
+                                                                ldns_rr_list_rr(ldns_zone_rrs(zone),
+                                                                                         i));
+               ldns_zone_push_rr(signed_zone, 
+                                          ldns_rr_clone(ldns_rr_list_rr(ldns_zone_rrs(zone),
+                                                                                          i)));
+       }
+
+       new_rrs = ldns_rr_list_new();
+       (void) ldns_dnssec_zone_sign_nsec3(dnssec_zone,
+                                                               new_rrs,
+                                                               key_list,
+                                                               ldns_dnssec_default_replace_signatures,
+                                                               NULL,
+                                                               algorithm,
+                                                               flags,
+                                                               iterations,
+                                                               salt_length,
+                                                               salt);
+
+       for (i = 0; i < ldns_rr_list_rr_count(new_rrs); i++) {
+               ldns_rr_list_push_rr(ldns_zone_rrs(signed_zone),
+                                                ldns_rr_clone(ldns_rr_list_rr(new_rrs, i)));
+       }
+
+       ldns_rr_list_deep_free(new_rrs);
+       ldns_dnssec_zone_free(dnssec_zone);
+
+       return signed_zone;
+}
+#endif /* HAVE_SSL */
+
diff --git a/contrib/ldns/dnssec_verify.c b/contrib/ldns/dnssec_verify.c
new file mode 100644 (file)
index 0000000..c7cd268
--- /dev/null
@@ -0,0 +1,2228 @@
+#include <ldns/config.h>
+
+#include <ldns/ldns.h>
+
+#include <strings.h>
+#include <time.h>
+
+#ifdef HAVE_SSL
+/* this entire file is rather useless when you don't have
+ * crypto...
+ */
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+
+ldns_dnssec_data_chain *
+ldns_dnssec_data_chain_new()
+{
+       ldns_dnssec_data_chain *nc = LDNS_XMALLOC(ldns_dnssec_data_chain, 1);
+       nc->rrset = NULL;
+       nc->parent_type = 0;
+       nc->parent = NULL;
+       nc->signatures = NULL;
+       nc->packet_rcode = 0;
+       nc->packet_qtype = 0;
+       nc->packet_nodata = false;
+       return nc;
+}
+
+void
+ldns_dnssec_data_chain_free(ldns_dnssec_data_chain *chain)
+{
+       LDNS_FREE(chain);
+}
+
+void
+ldns_dnssec_data_chain_deep_free(ldns_dnssec_data_chain *chain)
+{
+       ldns_rr_list_deep_free(chain->rrset);
+       ldns_rr_list_deep_free(chain->signatures);
+       if (chain->parent) {
+               ldns_dnssec_data_chain_deep_free(chain->parent);
+       }
+       LDNS_FREE(chain);
+}
+
+void
+ldns_dnssec_data_chain_print(FILE *out, const ldns_dnssec_data_chain *chain)
+{
+       ldns_lookup_table *rcode;
+       const ldns_rr_descriptor *rr_descriptor;
+       if (chain) {
+               ldns_dnssec_data_chain_print(out, chain->parent);
+               if (ldns_rr_list_rr_count(chain->rrset) > 0) {
+                       rcode = ldns_lookup_by_id(ldns_rcodes,
+                                                                (int) chain->packet_rcode);
+                       if (rcode) {
+                               fprintf(out, ";; rcode: %s\n", rcode->name);
+                       }
+
+                       rr_descriptor = ldns_rr_descript(chain->packet_qtype);
+                       if (rr_descriptor && rr_descriptor->_name) {
+                               fprintf(out, ";; qtype: %s\n", rr_descriptor->_name);
+                       } else if (chain->packet_qtype != 0) {
+                               fprintf(out, "TYPE%u", 
+                                          chain->packet_qtype);
+                       }
+                       if (chain->packet_nodata) {
+                               fprintf(out, ";; NODATA response\n");
+                       }
+                       fprintf(out, "rrset:\n");
+                       ldns_rr_list_print(out, chain->rrset);
+                       fprintf(out, "sigs:\n");
+                       ldns_rr_list_print(out, chain->signatures);
+                       fprintf(out, "---\n");
+               } else {
+                       fprintf(out, "<no data>\n");
+               }
+       }
+}
+
+static void
+ldns_dnssec_build_data_chain_dnskey(ldns_resolver *res,
+                                           uint16_t qflags,
+                                           const ldns_pkt *pkt,
+                                           ldns_rr_list *signatures,
+                                               ldns_dnssec_data_chain *new_chain,
+                                               ldns_rdf *key_name,
+                                               ldns_rr_class c) {
+       ldns_rr_list *keys;
+       ldns_pkt *my_pkt;
+       if (signatures && ldns_rr_list_rr_count(signatures) > 0) {
+               new_chain->signatures = ldns_rr_list_clone(signatures);
+               new_chain->parent_type = 0;
+
+               keys = ldns_pkt_rr_list_by_name_and_type(
+                                 pkt,
+                                key_name,
+                                LDNS_RR_TYPE_DNSKEY,
+                                LDNS_SECTION_ANY_NOQUESTION
+                         );
+               if (!keys) {
+                       my_pkt = ldns_resolver_query(res,
+                                                                       key_name,
+                                                                       LDNS_RR_TYPE_DNSKEY,
+                                                                       c,
+                                                                       qflags);
+                       keys = ldns_pkt_rr_list_by_name_and_type(
+                                         my_pkt,
+                                        key_name,
+                                        LDNS_RR_TYPE_DNSKEY,
+                                        LDNS_SECTION_ANY_NOQUESTION
+                                 );
+                       new_chain->parent = ldns_dnssec_build_data_chain(res,
+                                                                                                       qflags,
+                                                                                                       keys,
+                                                                                                       my_pkt,
+                                                                                                       NULL);
+                       new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
+                       ldns_pkt_free(my_pkt);
+               } else {
+                       new_chain->parent = ldns_dnssec_build_data_chain(res,
+                                                                                                       qflags,
+                                                                                                       keys,
+                                                                                                       pkt,
+                                                                                                       NULL);
+                       new_chain->parent->packet_qtype = LDNS_RR_TYPE_DNSKEY;
+               }
+               ldns_rr_list_deep_free(keys);
+       }
+}
+
+static void
+ldns_dnssec_build_data_chain_other(ldns_resolver *res,
+                                           uint16_t qflags,
+                                               ldns_dnssec_data_chain *new_chain,
+                                               ldns_rdf *key_name,
+                                               ldns_rr_class c,
+                                               ldns_rr_list *dss)
+{
+       /* 'self-signed', parent is a DS */
+       
+       /* okay, either we have other keys signing the current one,
+        * or the current
+        * one should have a DS record in the parent zone.
+        * How do we find this out? Try both?
+        *
+        * request DNSKEYS for current zone,
+        * add all signatures to current level
+        */
+       ldns_pkt *my_pkt;
+       ldns_rr_list *signatures2;
+       
+       new_chain->parent_type = 1;
+
+       my_pkt = ldns_resolver_query(res,
+                                                       key_name,
+                                                       LDNS_RR_TYPE_DS,
+                                                       c,
+                                                       qflags);
+       dss = ldns_pkt_rr_list_by_name_and_type(my_pkt,
+                                                                       key_name,
+                                                                       LDNS_RR_TYPE_DS,
+                                              &nbs