aboutsummaryrefslogtreecommitdiff
path: root/djbdns-1.05-dnssec.patch
diff options
context:
space:
mode:
authorHenryk Plötz <henryk@ploetzli.ch>2014-10-03 20:19:52 +0200
committerHenryk Plötz <henryk@ploetzli.ch>2014-10-03 20:29:37 +0200
commiteaaa5b4f9301ae2e5a29dd77616d8e29fd3b2c28 (patch)
treec090b31513b85dfca08b878066faf9d2893c7a7a /djbdns-1.05-dnssec.patch
parent898102385f20b06f08dc5fb379e1c9aa261a5700 (diff)
downloadtinydnssec-eaaa5b4f9301ae2e5a29dd77616d8e29fd3b2c28.tar.gz
tinydnssec-eaaa5b4f9301ae2e5a29dd77616d8e29fd3b2c28.tar.bz2
Add tinydnssec-1.05-1.3.tar.bz2
Source was http://www.tinydnssec.org/download/tinydnssec-1.05-1.3.tar.bz2, SHA1 b33d5c3e0de67f6427aad8c00a99580b59804075
Diffstat (limited to 'djbdns-1.05-dnssec.patch')
-rw-r--r--djbdns-1.05-dnssec.patch1749
1 files changed, 1749 insertions, 0 deletions
diff --git a/djbdns-1.05-dnssec.patch b/djbdns-1.05-dnssec.patch
new file mode 100644
index 0000000..d2b2323
--- /dev/null
+++ b/djbdns-1.05-dnssec.patch
@@ -0,0 +1,1749 @@
+(C) 2012 Peter Conrad <conrad@quisquis.de>
+
+This patch is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 3 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+diff -rNU3 djbdns-1.05.tds-base/axfrdns.c djbdns-1.05.tinydnssec/axfrdns.c
+--- djbdns-1.05.tds-base/axfrdns.c 2012-12-06 22:45:38.000000000 +0100
++++ djbdns-1.05.tinydnssec/axfrdns.c 2012-12-06 22:39:13.000000000 +0100
+@@ -23,6 +23,7 @@
+ #include "response.h"
+ #include "ip6.h"
+ #include "clientloc.h"
++#include "edns0.h"
+
+ extern int respond(char *,char *,char *);
+
+@@ -346,6 +347,9 @@
+ if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY))
+ strerr_die2x(111,FATAL,"bogus query: bad class");
+
++ pos = check_edns0(header, buf, len, pos);
++ if (!pos) die_truncated();
++
+ qlog(ip,port,header,zone,qtype," ");
+
+ if (byte_equal(qtype,2,DNS_T_AXFR)) {
+diff -rNU3 djbdns-1.05.tds-base/base32hex.c djbdns-1.05.tinydnssec/base32hex.c
+--- djbdns-1.05.tds-base/base32hex.c 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/base32hex.c 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,79 @@
++/* (C) 2012 Peter Conrad <conrad@quisquis.de>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "base32hex.h"
++
++#define to_32hex(c) ((c) < 10 ? (c) + '0' : (c) + 'a' - 10)
++
++/* out must point to a buffer of at least (len * 8 / 5) + 1 bytes.
++ * Encoded string is *not* padded.
++ * See RFC-4648. This implementation produces lowercase hex characters.
++ * Returns length of encoded string.
++ */
++unsigned int base32hex(char *out, uint8_t *in, unsigned int len) {
++int buf = 0, bits = 0;
++char *x = out;
++
++ while (len-- > 0) {
++ buf <<= 8;
++ buf |= *in++;
++ bits += 8;
++ while (bits >= 5) {
++ char c = (buf >> (bits - 5)) & 0x1f;
++ *x++ = to_32hex(c);
++ bits -= 5;
++ }
++ }
++ if (bits > 0) {
++ char c = (buf << (5 - bits)) & 0x1f;
++ *x++ = to_32hex(c);
++ }
++ return x - out;
++}
++
++#ifdef TEST
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++static void test(char *in, char *expected, int explen) {
++char buf[255];
++int r;
++
++ if ((r = base32hex(buf, in, strlen(in))) != explen) {
++ printf("Failed: b32h('%s') yields %d chars (expected %d)\n",
++ in, r, explen);
++ exit(1);
++ }
++ if (strncmp(buf, expected, r)) {
++ buf[r] = 0;
++ printf("Failed: b32h('%s') = '%s' (expected %s)\n",
++ in, buf, expected);
++ exit(1);
++ }
++}
++
++int main(int argc, char **argv) {
++ test("", "", 0);
++ test("f", "co", 2);
++ test("fo", "cpng", 4);
++ test("foo", "cpnmu", 5);
++ test("foob", "cpnmuog", 7);
++ test("fooba", "cpnmuoj1", 8);
++ test("foobar", "cpnmuoj1e8", 10);
++ printf("Success!\n");
++}
++
++#endif
+diff -rNU3 djbdns-1.05.tds-base/base32hex.h djbdns-1.05.tinydnssec/base32hex.h
+--- djbdns-1.05.tds-base/base32hex.h 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/base32hex.h 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,23 @@
++/* (C) 2012 Peter Conrad <conrad@quisquis.de>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _BASE32_HEX_H
++#define _BASE32_HEX_H
++
++#include <stdint.h>
++
++extern unsigned int base32hex(char *out, uint8_t *in, unsigned int len);
++
++#endif
+diff -rNU3 djbdns-1.05.tds-base/dns.h djbdns-1.05.tinydnssec/dns.h
+--- djbdns-1.05.tds-base/dns.h 2012-12-06 22:45:38.000000000 +0100
++++ djbdns-1.05.tinydnssec/dns.h 2012-12-06 22:39:13.000000000 +0100
+@@ -20,8 +20,17 @@
+ #define DNS_T_SIG "\0\30"
+ #define DNS_T_KEY "\0\31"
+ #define DNS_T_AAAA "\0\34"
++#define DNS_T_OPT "\0\51"
++#define DNS_T_DS "\0\53"
++#define DNS_T_RRSIG "\0\56"
++#define DNS_T_DNSKEY "\0\60"
++#define DNS_T_NSEC3 "\0\62"
++#define DNS_T_NSEC3PARAM "\0\63"
+ #define DNS_T_AXFR "\0\374"
+ #define DNS_T_ANY "\0\377"
++/* Pseudo-RRs for DNSSEC */
++#define DNS_T_HASHREF "\377\1"
++#define DNS_T_HASHLIST "\377\2"
+
+ struct dns_transmit {
+ char *query; /* 0, or dynamically allocated */
+diff -rNU3 djbdns-1.05.tds-base/edns0.c djbdns-1.05.tinydnssec/edns0.c
+--- djbdns-1.05.tds-base/edns0.c 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/edns0.c 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,45 @@
++/* (C) 2012 Peter Conrad <conrad@quisquis.de>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "dns.h"
++#include "edns0.h"
++#include "response.h"
++#include "uint16.h"
++
++unsigned int check_edns0(const char header[12], const char *buf, const int len, unsigned int pos)
++{
++char opt_class[2];
++char opt_ttl[4];
++
++ max_response_len = 512;
++ do_dnssec = 0;
++ if (!header[6] && !header[7] && !header[8] && !header[9]
++ && !header[10] && header[11] == 1) {
++ char nametype[3];
++ uint16 size, min_len;
++ pos = dns_packet_copy(buf,len,pos,nametype,3); if (!pos) return pos;
++ if (nametype[0] || nametype[1] || nametype[2] != DNS_T_OPT[1]) return pos;
++ pos = dns_packet_copy(buf,len,pos,opt_class,2); if (!pos) return pos;
++ pos = dns_packet_copy(buf,len,pos,opt_ttl,4); if (!pos) return pos;
++ if (opt_ttl[0]) return pos; // unsupported RCODE in query
++ if (opt_ttl[1]) return pos; // unsupported version
++ do_dnssec = opt_ttl[2] & 0x80;
++ uint16_unpack_big(opt_class, &size);
++ min_len = do_dnssec ? 1220 : 512;
++ max_response_len = size > 4000 ? 4000 : size;
++ if (max_response_len < min_len) { max_response_len = min_len; }
++ }
++ return pos;
++}
+diff -rNU3 djbdns-1.05.tds-base/edns0.h djbdns-1.05.tinydnssec/edns0.h
+--- djbdns-1.05.tds-base/edns0.h 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/edns0.h 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,22 @@
++/* (C) 2012 Peter Conrad <conrad@quisquis.de>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _EDNS0_H
++
++#define _EDNS0_H
++
++extern unsigned int check_edns0(const char *, const char *, const int, unsigned int);
++
++#endif
+diff -rNU3 djbdns-1.05.tds-base/Makefile djbdns-1.05.tinydnssec/Makefile
+--- djbdns-1.05.tds-base/Makefile 2012-12-06 22:45:45.000000000 +0100
++++ djbdns-1.05.tinydnssec/Makefile 2012-12-07 11:07:23.000000000 +0100
+@@ -53,10 +53,10 @@
+ axfrdns: \
+ load axfrdns.o iopause.o droproot.o tdlookup.o response.o qlog.o \
+ prot.o timeoutread.o timeoutwrite.o clientloc.o dns.a libtai.a alloc.a env.a \
+-cdb.a buffer.a unix.a byte.a
++cdb.a buffer.a unix.a byte.a sha1.o base32hex.o edns0.o
+ ./load axfrdns iopause.o droproot.o tdlookup.o response.o \
+ qlog.o prot.o timeoutread.o timeoutwrite.o clientloc.o dns.a libtai.a \
+- alloc.a env.a cdb.a buffer.a unix.a byte.a
++ alloc.a env.a cdb.a buffer.a unix.a byte.a sha1.o base32hex.o edns0.o
+
+ axfrdns-conf: \
+ load axfrdns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
+@@ -76,6 +76,10 @@
+ response.h uint32.h clientloc.h
+ ./compile axfrdns.c
+
++base32hex.o: \
++compile base32hex.c base32hex.h
++ ./compile base32hex.c
++
+ buffer.a: \
+ makelib buffer.o buffer_1.o buffer_2.o buffer_copy.o buffer_get.o \
+ buffer_put.o strerr_die.o strerr_sys.o
+@@ -454,10 +458,11 @@
+
+ dnsq: \
+ load dnsq.o iopause.o printrecord.o printpacket.o parsetype.o dns.a \
+-env.a libtai.a buffer.a alloc.a unix.a byte.a socket.lib
++env.a libtai.a buffer.a alloc.a unix.a byte.a socket.lib printtype.o \
++base32hex.o
+ ./load dnsq iopause.o printrecord.o printpacket.o \
+ parsetype.o dns.a env.a libtai.a buffer.a alloc.a unix.a \
+- byte.a `cat socket.lib`
++ byte.a `cat socket.lib` printtype.o base32hex.o
+
+ dnsq.o: \
+ compile dnsq.c uint16.h strerr.h buffer.h scan.h str.h byte.h error.h \
+@@ -467,10 +472,11 @@
+
+ dnsqr: \
+ load dnsqr.o iopause.o printrecord.o printpacket.o parsetype.o dns.a \
+-env.a libtai.a buffer.a alloc.a unix.a byte.a socket.lib
++env.a libtai.a buffer.a alloc.a unix.a byte.a socket.lib printtype.o \
++base32hex.o
+ ./load dnsqr iopause.o printrecord.o printpacket.o \
+ parsetype.o dns.a env.a libtai.a buffer.a alloc.a unix.a \
+- byte.a `cat socket.lib`
++ byte.a `cat socket.lib` printtype.o base32hex.o
+
+ dnsqr.o: \
+ compile dnsqr.c uint16.h strerr.h buffer.h scan.h str.h byte.h \
+@@ -480,10 +486,10 @@
+
+ dnstrace: \
+ load dnstrace.o dd.o iopause.o printrecord.o parsetype.o dns.a env.a \
+-libtai.a alloc.a buffer.a unix.a byte.a socket.lib
++libtai.a alloc.a buffer.a unix.a byte.a socket.lib printtype.o base32hex.o
+ ./load dnstrace dd.o iopause.o printrecord.o parsetype.o \
+ dns.a env.a libtai.a alloc.a buffer.a unix.a byte.a `cat \
+- socket.lib`
++ socket.lib` printtype.o base32hex.o
+
+ dnstrace.o: \
+ compile dnstrace.c uint16.h uint32.h fmt.h str.h byte.h ip4.h \
+@@ -514,6 +520,10 @@
+ compile droproot.c env.h scan.h prot.h strerr.h
+ ./compile droproot.c
+
++edns0.o: \
++compile edns0.c edns0.h uint16.h dns.h response.h iopause.h taia.h uint64.h
++ ./compile edns0.c
++
+ env.a: \
+ makelib env.o
+ ./makelib env.a env.o
+@@ -689,10 +699,10 @@
+
+ pickdns: \
+ load pickdns.o server.o iopause.o response.o droproot.o qlog.o prot.o dns.a \
+-env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
++env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib edns0.o
+ ./load pickdns server.o iopause.o response.o droproot.o qlog.o \
+ prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
+- byte.a `cat socket.lib`
++ byte.a `cat socket.lib` edns0.o
+
+ pickdns-conf: \
+ load pickdns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
+@@ -725,15 +735,19 @@
+ printpacket.o: \
+ compile printpacket.c uint16.h uint32.h error.h byte.h dns.h \
+ stralloc.h gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h \
+-printrecord.h stralloc.h printpacket.h stralloc.h
++printrecord.h stralloc.h printpacket.h stralloc.h printtype.h
+ ./compile printpacket.c
+
+ printrecord.o: \
+ compile printrecord.c uint16.h uint32.h error.h byte.h dns.h \
+ stralloc.h gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h \
+-printrecord.h stralloc.h
++printrecord.h stralloc.h printtype.h
+ ./compile printrecord.c
+
++printtype.o: \
++compile printtype.c printtype.h dns.h stralloc.h byte.h uint16.h iopause.h taia.h uint64.h
++ ./compile printtype.c
++
+ prog: \
+ dnscache-conf dnscache walldns-conf walldns rbldns-conf rbldns \
+ rbldns-data pickdns-conf pickdns pickdns-data tinydns-conf tinydns \
+@@ -767,10 +781,10 @@
+
+ rbldns: \
+ load rbldns.o server.o iopause.o response.o dd.o droproot.o qlog.o prot.o dns.a \
+-env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
++env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib edns0.o
+ ./load rbldns server.o iopause.o response.o dd.o droproot.o qlog.o \
+ prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
+- byte.a `cat socket.lib`
++ byte.a `cat socket.lib` edns0.o
+
+ rbldns-conf: \
+ load rbldns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
+@@ -840,7 +854,7 @@
+ compile server.c byte.h case.h env.h buffer.h strerr.h ip4.h uint16.h \
+ ndelay.h socket.h uint16.h droproot.h qlog.h uint16.h response.h \
+ uint32.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h uint64.h \
+-taia.h iopause.h alloc.h str.h
++taia.h iopause.h alloc.h str.h edns0.h
+ ./compile server.c
+
+ setup: \
+@@ -931,6 +945,10 @@
+ cp /dev/null haven2i.h
+ ./choose cL tryn2i haven2i.h1 haven2i.h2 socket > haven2i.h
+
++sha1.o: \
++compile sha1.c sha1.h
++ ./compile sha1.c
++
+ str_chr.o: \
+ compile str_chr.c str.h
+ ./compile str_chr.c
+@@ -1072,7 +1090,7 @@
+ tdlookup.o: \
+ compile tdlookup.c uint16.h open.h tai.h uint64.h cdb.h uint32.h \
+ byte.h case.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h \
+-taia.h seek.h response.h uint32.h ip6.h clientloc.h
++taia.h seek.h response.h uint32.h ip6.h clientloc.h sha1.h base32hex.h
+ ./compile tdlookup.c
+
+ timeoutread.o: \
+@@ -1088,10 +1106,10 @@
+ tinydns: \
+ load tinydns.o server.o iopause.o droproot.o tdlookup.o response.o qlog.o \
+ prot.o clientloc.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
+-socket.lib
++socket.lib sha1.o base32hex.o edns0.o
+ ./load tinydns server.o iopause.o droproot.o tdlookup.o response.o \
+ qlog.o prot.o clientloc.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
+- unix.a byte.a `cat socket.lib`
++ unix.a byte.a `cat socket.lib` sha1.o base32hex.o edns0.o
+
+ tinydns-conf: \
+ load tinydns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
+@@ -1126,11 +1144,12 @@
+ ./compile tinydns-edit.c
+
+ tinydns-get: \
+-load tinydns-get.o tdlookup.o response.o printpacket.o printrecord.o \
+-parsetype.o clientloc.o dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a
++load tinydns-get.o tdlookup.o sha1.o response.o printpacket.o printrecord.o \
++parsetype.o clientloc.o dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a \
++base32hex.o printtype.o
+ ./load tinydns-get tdlookup.o response.o printpacket.o \
+ printrecord.o parsetype.o clientloc.o dns.a libtai.a cdb.a buffer.a \
+- alloc.a unix.a byte.a
++ alloc.a unix.a byte.a sha1.o base32hex.o printtype.o
+
+ tinydns-get.o: \
+ compile tinydns-get.c str.h byte.h scan.h exit.h stralloc.h \
+@@ -1198,10 +1217,10 @@
+
+ walldns: \
+ load walldns.o server.o iopause.o response.o droproot.o qlog.o prot.o dd.o \
+-dns.a env.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
++dns.a env.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib edns0.o
+ ./load walldns server.o iopause.o response.o droproot.o qlog.o \
+ prot.o dd.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a \
+- byte.a `cat socket.lib`
++ byte.a `cat socket.lib` edns0.o
+
+ walldns-conf: \
+ load walldns-conf.o generic-conf.o auto_home.o buffer.a unix.a byte.a
+@@ -1227,4 +1246,4 @@
+ ./choose c trysa6 sockaddr_in6.h1 sockaddr_in6.h2 > sockaddr_in6.h
+
+ clean:
+- rm -f `cat TARGETS`
++ rm -f `cat TARGETS` data data.cdb test/[ot]*
+diff -rNU3 djbdns-1.05.tds-base/parsetype.c djbdns-1.05.tinydnssec/parsetype.c
+--- djbdns-1.05.tds-base/parsetype.c 2001-02-11 22:11:45.000000000 +0100
++++ djbdns-1.05.tinydnssec/parsetype.c 2012-12-06 22:39:13.000000000 +0100
+@@ -24,6 +24,8 @@
+ else if (case_equals(s,"key")) byte_copy(type,2,DNS_T_KEY);
+ else if (case_equals(s,"aaaa")) byte_copy(type,2,DNS_T_AAAA);
+ else if (case_equals(s,"axfr")) byte_copy(type,2,DNS_T_AXFR);
++ else if (case_equals(s,"dnskey")) byte_copy(type,2,DNS_T_DNSKEY);
++ else if (case_equals(s,"ds")) byte_copy(type,2,DNS_T_DS);
+ else
+ return 0;
+
+diff -rNU3 djbdns-1.05.tds-base/printpacket.c djbdns-1.05.tinydnssec/printpacket.c
+--- djbdns-1.05.tds-base/printpacket.c 2001-02-11 22:11:45.000000000 +0100
++++ djbdns-1.05.tinydnssec/printpacket.c 2012-12-06 22:39:13.000000000 +0100
+@@ -5,6 +5,7 @@
+ #include "dns.h"
+ #include "printrecord.h"
+ #include "printpacket.h"
++#include "printtype.h"
+
+ static char *d;
+
+@@ -67,8 +68,7 @@
+ X("weird class")
+ }
+ else {
+- uint16_unpack_big(data,&type);
+- NUM(type)
++ if (!printtype(out,data)) return 0;
+ X(" ")
+ if (!dns_domain_todot_cat(out,d)) return 0;
+ }
+diff -rNU3 djbdns-1.05.tds-base/printrecord.c djbdns-1.05.tinydnssec/printrecord.c
+--- djbdns-1.05.tds-base/printrecord.c 2012-12-06 22:45:38.000000000 +0100
++++ djbdns-1.05.tinydnssec/printrecord.c 2012-12-06 22:39:13.000000000 +0100
+@@ -5,9 +5,25 @@
+ #include "dns.h"
+ #include "printrecord.h"
+ #include "ip6.h"
++#include "base32hex.h"
++#include "printtype.h"
+
+ static char *d;
+
++static const char *HEX = "0123456789ABCDEF";
++
++static int hexout(stralloc *out,const char *buf,unsigned int len,unsigned int pos,unsigned int n) {
++ unsigned char c;
++ int i;
++
++ for (i = 0; i < n; i++) {
++ pos = dns_packet_copy(buf,len,pos,&c,1); if (!pos) return 0;
++ if (!stralloc_catb(out,&HEX[(c>>4)&0xf],1)) return 0;
++ if (!stralloc_catb(out,&HEX[c&0xf],1)) return 0;
++ }
++ return pos;
++}
++
+ unsigned int printrecord_cat(stralloc *out,const char *buf,unsigned int len,unsigned int pos,const char *q,const char qtype[2])
+ {
+ const char *x;
+@@ -18,6 +34,7 @@
+ unsigned int newpos;
+ int i;
+ unsigned char ch;
++ int rawlen;
+
+ pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
+ pos = dns_packet_copy(buf,len,pos,misc,10); if (!pos) return 0;
+@@ -33,15 +50,20 @@
+
+ if (!dns_domain_todot_cat(out,d)) return 0;
+ if (!stralloc_cats(out," ")) return 0;
+- uint32_unpack_big(misc + 4,&u32);
+- if (!stralloc_catulong0(out,u32,0)) return 0;
++ if (byte_diff(misc,2,DNS_T_OPT)) {
++ uint32_unpack_big(misc + 4,&u32);
++ if (!stralloc_catulong0(out,u32,0)) return 0;
+
+- if (byte_diff(misc + 2,2,DNS_C_IN)) {
+- if (!stralloc_cats(out," weird class\n")) return 0;
+- return newpos;
++ if (byte_diff(misc + 2,2,DNS_C_IN)) {
++ if (!stralloc_cats(out," weird class\n")) return 0;
++ return newpos;
++ }
++ } else {
++ if (!stralloc_cats(out,"0")) return 0;
+ }
+
+ x = 0;
++ rawlen = 0;
+ if (byte_equal(misc,2,DNS_T_NS)) x = " NS ";
+ if (byte_equal(misc,2,DNS_T_PTR)) x = " PTR ";
+ if (byte_equal(misc,2,DNS_T_CNAME)) x = " CNAME ";
+@@ -92,12 +114,111 @@
+ stringlen=ip6_fmt(ip6str,misc);
+ if (!stralloc_catb(out,ip6str,stringlen)) return 0;
+ }
++ else if (byte_equal(misc,2,DNS_T_DNSKEY)) {
++ pos = dns_packet_copy(buf,len,pos,misc,4); if (!pos) return 0;
++ if (!stralloc_cats(out," DNSKEY ")) return 0;
++ uint16_unpack_big(misc,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[2],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[3],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ rawlen = datalen - 4;
++ }
++ else if (byte_equal(misc,2,DNS_T_DS)) {
++ pos = dns_packet_copy(buf,len,pos,misc,4); if (!pos) return 0;
++ if (!stralloc_cats(out," DS ")) return 0;
++ uint16_unpack_big(misc,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[2],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[3],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ pos = hexout(out,buf,len,pos,datalen - 4); if (!pos) return 0;
++ }
++ else if (byte_equal(misc,2,DNS_T_RRSIG)) {
++ pos = dns_packet_copy(buf,len,pos,misc,18); if (!pos) return 0;
++ if (!stralloc_cats(out," RRSIG ")) return 0;
++ if (!printtype(out,misc)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[2],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[3],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ uint32_unpack_big(misc + 4,&u32);
++ if (!stralloc_catulong0(out,u32,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ uint32_unpack_big(misc + 8,&u32);
++ if (!stralloc_catulong0(out,u32,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ uint32_unpack_big(misc + 12,&u32);
++ if (!stralloc_catulong0(out,u32,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ uint16_unpack_big(misc + 16,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ rawlen = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
++ rawlen = datalen - 18 - (rawlen - pos);
++ pos += datalen - 18 - rawlen;
++ if (!dns_domain_todot_cat(out,d)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ }
++ else if (byte_equal(misc,2,DNS_T_NSEC3)) {
++ char nextHash[255];
++ char nextOwner[255*8/5];
++ int j;
++ pos = dns_packet_copy(buf,len,pos,misc,5); if (!pos) return 0;
++ if (!stralloc_cats(out," NSEC3 ")) return 0;
++ if (!stralloc_catulong0(out,misc[0],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[1],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ uint16_unpack_big(misc+2,&u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!misc[4])
++ if (!stralloc_cats(out,"-")) return 0;
++ pos = hexout(out,buf,len,pos,misc[4]); if (!pos) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ pos = dns_packet_copy(buf,len,pos,misc,1); if (!pos) return 0;
++ pos = dns_packet_copy(buf,len,pos,nextHash,misc[0]); if (!pos) return 0;
++ i = base32hex(nextOwner, nextHash, misc[0]);
++ if (!stralloc_catb(out,nextOwner,i)) return 0;
++ while (pos < newpos) {
++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0;
++ pos = dns_packet_copy(buf,len,pos,nextHash,misc[1]); if (!pos) return 0;
++ j = 8 * misc[1];
++ for (i = 0; i < j; i++) {
++ if (nextHash[i/8] & (1 << (7 - (i%8)))) {
++ misc[1] = i;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!printtype(out,misc)) return 0;
++ }
++ }
++ }
++ }
++ else if (byte_equal(misc,2,DNS_T_OPT)) {
++ if (!stralloc_cats(out," OPT ")) return 0;
++ uint16_unpack_big(misc+2, &u16);
++ if (!stralloc_catulong0(out,u16,0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[4],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!stralloc_catulong0(out,misc[5],0)) return 0;
++ if (!stralloc_cats(out," ")) return 0;
++ if (!hexout(out,misc,8,6,2)) return 0;
++ rawlen = datalen;
++ }
+ else {
+ if (!stralloc_cats(out," ")) return 0;
+ uint16_unpack_big(misc,&u16);
+ if (!stralloc_catulong0(out,u16,0)) return 0;
+ if (!stralloc_cats(out," ")) return 0;
+- while (datalen--) {
++ rawlen = datalen;
++ }
++ while (rawlen--) {
+ pos = dns_packet_copy(buf,len,pos,misc,1); if (!pos) return 0;
+ if ((misc[0] >= 33) && (misc[0] <= 126) && (misc[0] != '\\')) {
+ if (!stralloc_catb(out,misc,1)) return 0;
+@@ -111,7 +232,6 @@
+ if (!stralloc_catb(out,misc,4)) return 0;
+ }
+ }
+- }
+
+ if (!stralloc_cats(out,"\n")) return 0;
+ if (pos != newpos) { errno = error_proto; return 0; }
+diff -rNU3 djbdns-1.05.tds-base/printtype.c djbdns-1.05.tinydnssec/printtype.c
+--- djbdns-1.05.tds-base/printtype.c 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/printtype.c 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,47 @@
++/* (C) 2012 Peter Conrad <conrad@quisquis.de>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "byte.h"
++#include "dns.h"
++#include "uint16.h"
++#include "printtype.h"
++
++int printtype(stralloc *out, const char type[2]) {
++uint16 u16;
++
++ if (byte_equal(type,2,DNS_T_A)) return stralloc_cats(out,"A");
++ if (byte_equal(type,2,DNS_T_NS)) return stralloc_cats(out,"NS");
++ if (byte_equal(type,2,DNS_T_CNAME)) return stralloc_cats(out,"CNAME");
++ if (byte_equal(type,2,DNS_T_SOA)) return stralloc_cats(out,"SOA");
++ if (byte_equal(type,2,DNS_T_PTR)) return stralloc_cats(out,"PTR");
++ if (byte_equal(type,2,DNS_T_HINFO)) return stralloc_cats(out,"HINFO");
++ if (byte_equal(type,2,DNS_T_MX)) return stralloc_cats(out,"MX");
++ if (byte_equal(type,2,DNS_T_TXT)) return stralloc_cats(out,"TXT");
++ if (byte_equal(type,2,DNS_T_RP)) return stralloc_cats(out,"RP");
++ if (byte_equal(type,2,DNS_T_SIG)) return stralloc_cats(out,"SIG");
++ if (byte_equal(type,2,DNS_T_KEY)) return stralloc_cats(out,"KEY");
++ if (byte_equal(type,2,DNS_T_AAAA)) return stralloc_cats(out,"AAAA");
++ if (byte_equal(type,2,DNS_T_OPT)) return stralloc_cats(out,"OPT");
++ if (byte_equal(type,2,DNS_T_DS)) return stralloc_cats(out,"DS");
++ if (byte_equal(type,2,DNS_T_RRSIG)) return stralloc_cats(out,"RRSIG");
++ if (byte_equal(type,2,DNS_T_DNSKEY)) return stralloc_cats(out,"DNSKEY");
++ if (byte_equal(type,2,DNS_T_NSEC3)) return stralloc_cats(out,"NSEC3");
++ if (byte_equal(type,2,DNS_T_NSEC3PARAM)) return stralloc_cats(out,"NSEC3PARAM");
++ if (byte_equal(type,2,DNS_T_AXFR)) return stralloc_cats(out,"AXFR");
++ if (byte_equal(type,2,DNS_T_ANY)) return stralloc_cats(out,"*");
++
++ uint16_unpack_big(type,&u16);
++ return stralloc_catulong0(out,u16,0);
++}
+diff -rNU3 djbdns-1.05.tds-base/printtype.h djbdns-1.05.tinydnssec/printtype.h
+--- djbdns-1.05.tds-base/printtype.h 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/printtype.h 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,23 @@
++/* (C) 2012 Peter Conrad <conrad@quisquis.de>
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 3 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _PRINTTYPE_H
++#define _PRINTTYPE_H
++
++#include "stralloc.h"
++
++extern int printtype(stralloc *, const char *);
++
++#endif
+diff -rNU3 djbdns-1.05.tds-base/response.c djbdns-1.05.tinydnssec/response.c
+--- djbdns-1.05.tds-base/response.c 2001-02-11 22:11:45.000000000 +0100
++++ djbdns-1.05.tinydnssec/response.c 2012-12-06 22:39:13.000000000 +0100
+@@ -5,6 +5,8 @@
+
+ char response[65535];
+ unsigned int response_len = 0; /* <= 65535 */
++unsigned int max_response_len = 0; /* <= 65535 */
++unsigned int do_dnssec = 0;
+ static unsigned int tctarget;
+
+ #define NAMES 100
+diff -rNU3 djbdns-1.05.tds-base/response.h djbdns-1.05.tinydnssec/response.h
+--- djbdns-1.05.tds-base/response.h 2001-02-11 22:11:45.000000000 +0100
++++ djbdns-1.05.tinydnssec/response.h 2012-12-06 22:39:13.000000000 +0100
+@@ -5,6 +5,8 @@
+
+ extern char response[];
+ extern unsigned int response_len;
++extern unsigned int max_response_len;
++extern unsigned int do_dnssec;
+
+ extern int response_query(const char *,const char *,const char *);
+ extern void response_nxdomain(void);
+diff -rNU3 djbdns-1.05.tds-base/server.c djbdns-1.05.tinydnssec/server.c
+--- djbdns-1.05.tds-base/server.c 2012-12-06 22:45:38.000000000 +0100
++++ djbdns-1.05.tinydnssec/server.c 2012-12-06 22:39:13.000000000 +0100
+@@ -1,3 +1,4 @@
++#include "edns0.h"
+ #include "byte.h"
+ #include "case.h"
+ #include "env.h"
+@@ -63,6 +64,9 @@
+ if (header[2] & 126) goto NOTIMP;
+ if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP;
+
++ pos = check_edns0(header, buf, len, pos);
++ if (!pos) goto NOQ;
++
+ case_lowerb(q,dns_domain_length(q));
+ if (!respond(q,qtype,ip)) {
+ qlog(ip,port,header,q,qtype," - ");
+@@ -168,7 +172,7 @@
+ len = socket_recv6(udp53[i],buf,sizeof buf,ip,&port,&ifid);
+ if (len < 0) continue;
+ if (!doit()) continue;
+- if (response_len > 512) response_tc();
++ if (response_len > max_response_len) response_tc();
+ socket_send6(udp53[i],response,response_len,ip,port,ifid);
+ /* may block for buffer space; if it fails, too bad */
+ }
+diff -rNU3 djbdns-1.05.tds-base/sha1.c djbdns-1.05.tinydnssec/sha1.c
+--- djbdns-1.05.tds-base/sha1.c 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/sha1.c 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,385 @@
++/*
++SHA-1 in C
++By Steve Reid <sreid@sea-to-sky.net>
++100% Public Domain
++
++-----------------
++Modified 7/98
++By James H. Brown <jbrown@burgoyne.com>
++Still 100% Public Domain
++
++Corrected a problem which generated improper hash values on 16 bit machines
++Routine SHA1Update changed from
++ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
++len)
++to
++ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
++long len)
++
++The 'len' parameter was declared an int which works fine on 32 bit machines.
++However, on 16 bit machines an int is too small for the shifts being done
++against
++it. This caused the hash function to generate incorrect values if len was
++greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
++
++Since the file IO in main() reads 16K at a time, any file 8K or larger would
++be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
++"a"s).
++
++I also changed the declaration of variables i & j in SHA1Update to
++unsigned long from unsigned int for the same reason.
++
++These changes should make no difference to any 32 bit implementations since
++an
++int and a long are the same size in those environments.
++
++--
++I also corrected a few compiler warnings generated by Borland C.
++1. Added #include <process.h> for exit() prototype
++2. Removed unused variable 'j' in SHA1Final
++3. Changed exit(0) to return(0) at end of main.
++
++ALL changes I made can be located by searching for comments containing 'JHB'
++-----------------
++Modified 8/98
++By Steve Reid <sreid@sea-to-sky.net>
++Still 100% public domain
++
++1- Removed #include <process.h> and used return() instead of exit()
++2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
++3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
++
++-----------------
++Modified 4/01
++By Saul Kravitz <Saul.Kravitz@celera.com>
++Still 100% PD
++Modified to run on Compaq Alpha hardware.
++
++-----------------
++Modified 07/2002
++By Ralph Giles <giles@ghostscript.com>
++Still 100% public domain
++modified for use with stdint types, autoconf
++code cleanup, removed attribution comments
++switched SHA1Final() argument order for consistency
++use SHA1_ prefix for public api
++move public api to sha1.h
++
++-----------------
++Modified 08/2012
++By Peter Conrad <conrad@quisquis.de>
++Still 100% public domain
++
++Taken from http://svn.ghostscript.com/jbig2dec/trunk/ for inclusion in tinydns
++Added/removed some includes
++Replaced WORDS_BIGENDIAN with BYTE_ORDER == BIG_ENDIAN check
++Test succeeds on x86_64
++*/
++
++/*
++Test Vectors (from FIPS PUB 180-1)
++"abc"
++ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
++"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
++ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
++A million repetitions of "a"
++ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
++*/
++
++/* #define SHA1HANDSOFF */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <endian.h>
++#include <stdio.h>
++#include <string.h>
++
++#include "sha1.h"
++
++void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
++
++#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
++
++/* blk0() and blk() perform the initial expand. */
++/* I got the idea of expanding during the round function from SSLeay */
++/* FIXME: can we do this in an endian-proof way? */
++#if BYTE_ORDER == BIG_ENDIAN
++#define blk0(i) block->l[i]
++#else
++#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
++ |(rol(block->l[i],8)&0x00FF00FF))
++#endif
++#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
++ ^block->l[(i+2)&15]^block->l[i&15],1))
++
++/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
++#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
++#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
++#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
++#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
++#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
++
++
++#ifdef VERBOSE /* SAK */
++void SHAPrintContext(SHA1_CTX *context, char *msg){
++ printf("%s (%d,%d) %x %x %x %x %x\n",
++ msg,
++ context->count[0], context->count[1],
++ context->state[0],
++ context->state[1],
++ context->state[2],
++ context->state[3],
++ context->state[4]);
++}
++#endif /* VERBOSE */
++
++/* Hash a single 512-bit block. This is the core of the algorithm. */
++void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
++{
++ uint32_t a, b, c, d, e;
++ typedef union {
++ uint8_t c[64];
++ uint32_t l[16];
++ } CHAR64LONG16;
++ CHAR64LONG16* block;
++
++#ifdef SHA1HANDSOFF
++ static uint8_t workspace[64];
++ block = (CHAR64LONG16*)workspace;
++ memcpy(block, buffer, 64);
++#else
++ block = (CHAR64LONG16*)buffer;
++#endif
++
++ /* Copy context->state[] to working vars */
++ a = state[0];
++ b = state[1];
++ c = state[2];
++ d = state[3];
++ e = state[4];
++
++ /* 4 rounds of 20 operations each. Loop unrolled. */
++ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
++ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
++ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
++ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
++ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
++ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
++ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
++ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
++ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
++ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
++ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
++ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
++ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
++ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
++ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
++ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
++ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
++ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
++ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
++ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
++
++ /* Add the working vars back into context.state[] */
++ state[0] += a;
++ state[1] += b;
++ state[2] += c;
++ state[3] += d;
++ state[4] += e;
++
++ /* Wipe variables */
++ a = b = c = d = e = 0;
++}
++
++
++/* SHA1Init - Initialize new context */
++void SHA1_Init(SHA1_CTX* context)
++{
++ /* SHA1 initialization constants */
++ context->state[0] = 0x67452301;
++ context->state[1] = 0xEFCDAB89;
++ context->state[2] = 0x98BADCFE;
++ context->state[3] = 0x10325476;
++ context->state[4] = 0xC3D2E1F0;
++ context->count[0] = context->count[1] = 0;
++}
++
++
++/* Run your data through this. */
++void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len)
++{
++ size_t i, j;
++
++#ifdef VERBOSE
++ SHAPrintContext(context, "before");
++#endif
++
++ j = (context->count[0] >> 3) & 63;
++ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
++ context->count[1] += (len >> 29);
++ if ((j + len) > 63) {
++ memcpy(&context->buffer[j], data, (i = 64-j));
++ SHA1_Transform(context->state, context->buffer);
++ for ( ; i + 63 < len; i += 64) {
++ SHA1_Transform(context->state, data + i);
++ }
++ j = 0;
++ }
++ else i = 0;
++ memcpy(&context->buffer[j], &data[i], len - i);
++
++#ifdef VERBOSE
++ SHAPrintContext(context, "after ");
++#endif
++}
++
++
++/* Add padding and return the message digest. */
++void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE])
++{
++ uint32_t i;
++ uint8_t finalcount[8];
++
++ for (i = 0; i < 8; i++) {
++ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
++ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
++ }
++ SHA1_Update(context, (uint8_t *)"\200", 1);
++ while ((context->count[0] & 504) != 448) {
++ SHA1_Update(context, (uint8_t *)"\0", 1);
++ }
++ SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
++ for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
++ digest[i] = (uint8_t)
++ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
++ }
++
++ /* Wipe variables */
++ i = 0;
++ memset(context->buffer, 0, 64);
++ memset(context->state, 0, 20);
++ memset(context->count, 0, 8);
++ memset(finalcount, 0, 8); /* SWR */
++
++#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */
++ SHA1_Transform(context->state, context->buffer);
++#endif
++}
++
++/*************************************************************/
++
++#if 0
++int main(int argc, char** argv)
++{
++int i, j;
++SHA1_CTX context;
++unsigned char digest[SHA1_DIGEST_SIZE], buffer[16384];
++FILE* file;
++
++ if (argc > 2) {
++ puts("Public domain SHA-1 implementation - by Steve Reid <sreid@sea-to-sky.net>");
++ puts("Modified for 16 bit environments 7/98 - by James H. Brown <jbrown@burgoyne.com>"); /* JHB */
++ puts("Produces the SHA-1 hash of a file, or stdin if no file is specified.");
++ return(0);
++ }
++ if (argc < 2) {
++ file = stdin;
++ }
++ else {
++ if (!(file = fopen(argv[1], "rb"))) {
++ fputs("Unable to open file.", stderr);
++ return(-1);
++ }
++ }
++ SHA1_Init(&context);
++ while (!feof(file)) { /* note: what if ferror(file) */
++ i = fread(buffer, 1, 16384, file);
++ SHA1_Update(&context, buffer, i);
++ }
++ SHA1_Final(&context, digest);
++ fclose(file);
++ for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) {
++ for (j = 0; j < 4; j++) {
++ printf("%02X", digest[i*4+j]);
++ }
++ putchar(' ');
++ }
++ putchar('\n');
++ return(0); /* JHB */
++}
++#endif
++
++/* self test */
++
++#ifdef TEST
++
++static char *test_data[] = {
++ "abc",
++ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
++ "A million repetitions of 'a'"};
++static char *test_results[] = {
++ "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
++ "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
++ "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"};
++
++
++void digest_to_hex(const uint8_t digest[SHA1_DIGEST_SIZE], char *output)
++{
++ int i,j;
++ char *c = output;
++
++ for (i = 0; i < SHA1_DIGEST_SIZE/4; i++) {
++ for (j = 0; j < 4; j++) {
++ sprintf(c,"%02X", digest[i*4+j]);
++ c += 2;
++ }
++ sprintf(c, " ");
++ c += 1;
++ }
++ *(c - 1) = '\0';
++}
++
++int main(int argc, char** argv)
++{
++ int k;
++ SHA1_CTX context;
++ uint8_t digest[20];
++ char output[80];
++
++ fprintf(stdout, "verifying SHA-1 implementation... ");
++
++ for (k = 0; k < 2; k++){
++ SHA1_Init(&context);
++ SHA1_Update(&context, (uint8_t*)test_data[k], strlen(test_data[k]));
++ SHA1_Final(&context, digest);
++ digest_to_hex(digest, output);
++
++ if (strcmp(output, test_results[k])) {
++ fprintf(stdout, "FAIL\n");
++ fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[k]);
++ fprintf(stderr,"\t%s returned\n", output);
++ fprintf(stderr,"\t%s is correct\n", test_results[k]);
++ return (1);
++ }
++ }
++ /* million 'a' vector we feed separately */
++ SHA1_Init(&context);
++ for (k = 0; k < 1000000; k++)
++ SHA1_Update(&context, (uint8_t*)"a", 1);
++ SHA1_Final(&context, digest);
++ digest_to_hex(digest, output);
++ if (strcmp(output, test_results[2])) {
++ fprintf(stdout, "FAIL\n");
++ fprintf(stderr,"* hash of \"%s\" incorrect:\n", test_data[2]);
++ fprintf(stderr,"\t%s returned\n", output);
++ fprintf(stderr,"\t%s is correct\n", test_results[2]);
++ return (1);
++ }
++
++ /* success */
++ fprintf(stdout, "ok\n");
++ return(0);
++}
++#endif /* TEST */
+diff -rNU3 djbdns-1.05.tds-base/sha1.h djbdns-1.05.tinydnssec/sha1.h
+--- djbdns-1.05.tds-base/sha1.h 1970-01-01 01:00:00.000000000 +0100
++++ djbdns-1.05.tinydnssec/sha1.h 2012-12-06 22:39:13.000000000 +0100
+@@ -0,0 +1,29 @@
++/* public api for steve reid's public domain SHA-1 implementation */
++/* this file is in the public domain */
++
++#ifndef __SHA1_H
++#define __SHA1_H
++
++#include <stdint.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct {
++ uint32_t state[5];
++ uint32_t count[2];
++ uint8_t buffer[64];
++} SHA1_CTX;
++
++#define SHA1_DIGEST_SIZE 20
++
++void SHA1_Init(SHA1_CTX* context);
++void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len);
++void SHA1_Final(SHA1_CTX* context, uint8_t digest[SHA1_DIGEST_SIZE]);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* __SHA1_H */
+diff -rNU3 djbdns-1.05.tds-base/TARGETS djbdns-1.05.tinydnssec/TARGETS
+--- djbdns-1.05.tds-base/TARGETS 2012-12-06 22:45:38.000000000 +0100
++++ djbdns-1.05.tinydnssec/TARGETS 2012-12-06 22:39:13.000000000 +0100
+@@ -240,3 +240,8 @@
+ socket_accept6.o
+ socket_connect6.o
+ socket_tcp6.o
++base32hex.o
++sha1.o
++base32hex.o
++printtype.o
++edns0.o
+diff -rNU3 djbdns-1.05.tds-base/tdlookup.c djbdns-1.05.tinydnssec/tdlookup.c
+--- djbdns-1.05.tds-base/tdlookup.c 2012-12-06 22:45:38.000000000 +0100
++++ djbdns-1.05.tinydnssec/tdlookup.c 2012-12-07 11:01:39.000000000 +0100
+@@ -10,6 +10,9 @@
+ #include "response.h"
+ #include "ip6.h"
+ #include "clientloc.h"
++#include "alloc.h"
++#include "sha1.h"
++#include "base32hex.h"
+
+ static int want(const char *owner,const char type[2])
+ {
+@@ -34,7 +37,7 @@
+ }
+
+ static char *d1;
+-
++static char *wantAddr;
+ static char clientloc[2];
+ static struct tai now;
+ static struct cdb c;
+@@ -44,10 +47,18 @@
+ static unsigned int dpos;
+ static char type[2];
+ static uint32 ttl;
++static char *nsec3;
++static char *cname = 0;
+
++/* returns -1 on failure,
++ * returns 0 on not found
++ * returns 1 when found
++ * returns 2 when flagwild is true and no wildcard match has been found but
++ * a direct match exists. This is for RFC-1034 section 4.3.3 compatibility.
++ */
+ static int find(char *d,int flagwild)
+ {
+- int r;
++ int r, direct=0;
+ char ch;
+ struct tai cutoff;
+ char ttd[8];
+@@ -57,7 +68,9 @@
+
+ for (;;) {
+ r = cdb_findnext(&c,d,dns_domain_length(d));
+- if (r <= 0) return r;
++ if (r < 0) return r; /* -1 */
++ if (r == 0) { return flagwild ? direct ? 2 : 0
++ : 0; }
+ dlen = cdb_datalen(&c);
+ if (dlen > sizeof data) return -1;
+ if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return -1;
+@@ -68,6 +81,7 @@
+ dpos = dns_packet_copy(data,dlen,dpos,recordloc,2); if (!dpos) return -1;
+ if (byte_diff(recordloc,2,clientloc)) continue;
+ }
++ direct = direct || (ch != '*');
+ if (flagwild != (ch == '*')) continue;
+ dpos = dns_packet_copy(data,dlen,dpos,ttlstr,4); if (!dpos) return -1;
+ uint32_unpack_big(ttlstr,&ttl);
+@@ -105,6 +119,123 @@
+ return response_addname(d1);
+ }
+
++static int addNSEC3(char *hashName)
++{
++int r;
++
++ cdb_findstart(&c);
++ while (r = find(hashName,0)) {
++ if (r == -1) return 0;
++ if (byte_equal(type,2,DNS_T_NSEC3)) {
++ if (!response_rstart(hashName,DNS_T_NSEC3,ttl)) return 0;
++ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
++ response_rfinish(RESPONSE_AUTHORITY);
++ }
++ else if (do_dnssec && byte_equal(type,2,DNS_T_RRSIG) && dlen > dpos+18
++ && byte_equal(data+dpos,2,DNS_T_NSEC3)) {
++ if (!response_rstart(hashName,DNS_T_RRSIG,ttl)) return 0;
++ if (!dobytes(18)) return 0;
++ if (!doname()) return 0;
++ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
++ response_rfinish(RESPONSE_AUTHORITY);
++ }
++ }
++ return 1;
++}
++
++static int addNSEC3Cover(char *name, char *control, int wild)
++{
++SHA1_CTX ctx;
++int algo = 0, flags = 0, saltlen = 0, r;
++uint16 iterations = 0;
++char salt[255];
++uint8_t digest[SHA1_DIGEST_SIZE];
++
++ /* Search NSEC3PARAM to find hash parameters */
++ cdb_findstart(&c);
++ while (r = find(control,0)) {
++ if (r == -1) return 0;
++ if (byte_equal(type,2,DNS_T_NSEC3PARAM) && dlen - dpos > 5) {
++ algo = data[dpos];
++ flags = data[dpos+1];
++ uint16_unpack_big(data + dpos + 2, &iterations);
++ saltlen = data[dpos+4];
++ if (algo != 1 || flags || dlen - dpos - 5 < saltlen) {
++ algo = 0;
++ } else {
++ byte_copy(salt,saltlen, data + dpos + 5);
++ break;
++ }
++ }
++ }
++ if (algo != 1) return 0; /* not found or unsupported algorithm / flags */
++
++ /* Compute hash value */
++ case_lowerb(name,dns_domain_length(name));
++ SHA1_Init(&ctx);
++ if (wild) SHA1_Update(&ctx, "\1*", 2);
++ SHA1_Update(&ctx, name, dns_domain_length(name));
++ SHA1_Update(&ctx, salt, saltlen);
++ SHA1_Final(&ctx, digest);
++ while (iterations-- > 0) {
++ SHA1_Init(&ctx);
++ SHA1_Update(&ctx, digest, SHA1_DIGEST_SIZE);
++ SHA1_Update(&ctx, salt, saltlen);
++ SHA1_Final(&ctx, digest);
++ }
++
++ /* Find covering hash */
++ char nibble = ((digest[0] >> 4) & 0xf) + '0';
++ if (nibble > '9') { nibble += 'a' - '9' - 1; }
++ salt[0] = 1;
++ salt[1] = nibble;
++ byte_copy(salt+2, dns_domain_length(control), control);
++ cdb_findstart(&c);
++ while (r = find(salt,0)) {
++ if (r == -1) return 0;
++ if (byte_equal(type,2,DNS_T_HASHLIST) && dlen - dpos >= SHA1_DIGEST_SIZE) {
++ int hpos = dpos + SHA1_DIGEST_SIZE;
++ while (byte_diff(digest,SHA1_DIGEST_SIZE,data+hpos) > 0 && hpos < dlen) hpos += SHA1_DIGEST_SIZE;
++ hpos -= SHA1_DIGEST_SIZE;
++ *salt = base32hex(salt+1,data+hpos,SHA1_DIGEST_SIZE);
++ byte_copy(salt + *salt + 1, dns_domain_length(control), control);
++ break;
++ }
++ }
++ if (*salt == 1) return 0; /* not found */
++ return addNSEC3(salt);
++}
++
++static int addClosestEncloserProof(char *name, char *control, int includeWild)
++{
++char *q = name;
++char *hashName = 0;
++int r;
++
++ while (*q) {
++ cdb_findstart(&c);
++ while (r = find(q,0)) {
++ if (r == -1) return 0;
++ if (byte_equal(type,2,DNS_T_HASHREF) && dlen > dpos) {
++ if (!dns_packet_getname(data,dlen,dpos,&hashName)) return 0;
++ break;
++ }
++ }
++ if (hashName) {
++ int rc = addNSEC3(hashName);
++ alloc_free(hashName);
++ if (!rc) return 0;
++ hashName = 0;
++ break;
++ }
++ name = q;
++ q += *q + 1;
++ }
++ if (!*q) return 0;
++ if (includeWild && !addNSEC3Cover(q, control, 1)) return 0;
++ return addNSEC3Cover(name, control, 0);
++}
++
+ static int doit(char *q,char qtype[2])
+ {
+ unsigned int bpos;
+@@ -118,6 +249,8 @@
+ int r;
+ int flagns;
+ int flagauthoritative;
++ int flagsigned;
++ char *flagcname;
+ char x[20];
+ uint16 u16;
+ char addr[8][4];
+@@ -132,18 +265,28 @@
+ for (;;) {
+ flagns = 0;
+ flagauthoritative = 0;
++ flagsigned = 0;
+ cdb_findstart(&c);
+ while (r = find(control,0)) {
+ if (r == -1) return 0;
+ if (byte_equal(type,2,DNS_T_SOA)) flagauthoritative = 1;
+- if (byte_equal(type,2,DNS_T_NS)) flagns = 1;
++ else if (byte_equal(type,2,DNS_T_NS)) flagns = 1;
++ else if (byte_equal(type,2,DNS_T_DNSKEY)) flagsigned |= 1;
++ else if (byte_equal(type,2,DNS_T_RRSIG)) flagsigned |= 2;
++ else if (byte_equal(type,2,DNS_T_NSEC3PARAM)) flagsigned |= 4;
+ }
++ flagsigned = (flagsigned == 7);
+ if (flagns) break;
+- if (!*control) return 0; /* q is not within our bailiwick */
++ if (!*control) {
++ if (!cname) return 0; /* q is not within our bailiwick */
++ response[2] &= ~4; /* CNAME chain ends in external reference */
++ return 1;
++ }
+ control += *control;
+ control += 1;
+ }
+
++ wild = q;
+ if (!flagauthoritative) {
+ response[2] &= ~4;
+ goto AUTHORITY; /* q is in a child zone */
+@@ -152,7 +295,11 @@
+
+ flaggavesoa = 0;
+ flagfound = 0;
+- wild = q;
++ flagcname = 0;
++ if (nsec3) {
++ alloc_free(nsec3);
++ nsec3 = 0;
++ }
+
+ for (;;) {
+ addrnum = addr6num = 0;
+@@ -160,10 +307,29 @@
+ cdb_findstart(&c);
+ while (r = find(wild,wild != q)) {
+ if (r == -1) return 0;
++ if (r == 2) break;
+ flagfound = 1;
+ if (flaggavesoa && byte_equal(type,2,DNS_T_SOA)) continue;
+- if (byte_diff(type,2,qtype) && byte_diff(qtype,2,DNS_T_ANY) && byte_diff(type,2,DNS_T_CNAME)) continue;
+- if (byte_equal(type,2,DNS_T_A) && (dlen - dpos == 4)) {
++ if (do_dnssec && byte_equal(type,2,DNS_T_HASHREF) && dlen > dpos) {
++ if (!dns_packet_getname(data,dlen,dpos,&nsec3)) return 0;
++ }
++ if (byte_diff(type,2,qtype) && byte_diff(qtype,2,DNS_T_ANY) && byte_diff(type,2,DNS_T_CNAME)
++ && (!do_dnssec || byte_diff(type,2,DNS_T_RRSIG))) continue;
++ if (byte_equal(type,2,DNS_T_HASHREF) || byte_equal(type,2,DNS_T_HASHLIST)) continue;
++ if (do_dnssec && byte_equal(type,2,DNS_T_RRSIG) && dlen - dpos > 18) {
++ char sigtype[2];
++ struct tai valid;
++ uint32 validFrom, validUntil;
++ byte_copy(sigtype,2,data + dpos);
++ if (byte_diff(sigtype,2,qtype) && byte_diff(qtype,2,DNS_T_ANY) && byte_diff(sigtype,2,DNS_T_CNAME)) continue;
++ uint32_unpack_big(data + dpos + 12, &validFrom);
++ tai_unix(&valid, validFrom);
++ if (tai_less(&now, &valid)) continue;
++ uint32_unpack_big(data + dpos + 8, &validUntil);
++ tai_unix(&valid, validUntil);
++ if (tai_less(&valid, &now)) continue;
++ }
++ if (byte_equal(type,2,DNS_T_A) && (dlen - dpos == 4) && (!do_dnssec || addrnum < 8)) {
+ addrttl = ttl;
+ i = dns_random(addrnum + 1);
+ if (i < 8) {
+@@ -174,7 +340,7 @@
+ if (addrnum < 1000000) ++addrnum;
+ continue;
+ }
+- if (byte_equal(type,2,DNS_T_AAAA) && (dlen - dpos == 16)) {
++ if (byte_equal(type,2,DNS_T_AAAA) && (dlen - dpos == 16) && (!do_dnssec || addr6num < 8)) {
+ addr6ttl = ttl;
+ i = dns_random(addr6num + 1);
+ if (i < 8) {
+@@ -188,6 +354,9 @@
+ if (!response_rstart(q,type,ttl)) return 0;
+ if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_CNAME) || byte_equal(type,2,DNS_T_PTR)) {
+ if (!doname()) return 0;
++ if (byte_equal(type,2,DNS_T_CNAME) && byte_diff(qtype,2,DNS_T_CNAME)) {
++ if (!dns_domain_copy(&flagcname,d1)) return 0;
++ }
+ }
+ else if (byte_equal(type,2,DNS_T_MX)) {
+ if (!dobytes(2)) return 0;
+@@ -199,10 +368,18 @@
+ if (!dobytes(20)) return 0;
+ flaggavesoa = 1;
+ }
++ else if (byte_equal(type,2,DNS_T_RRSIG) && dlen - dpos > 18) {
++ char sigtype[2];
++ byte_copy(sigtype,2,data + dpos);
++ if (!dobytes(18)) return 0;
++ if (!doname()) return 0;
++ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
++ }
+ else
+ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
+ response_rfinish(RESPONSE_ANSWER);
+ }
++ if (r == 2) break;
+ for (i = 0;i < addrnum;++i)
+ if (i < 8) {
+ if (!response_rstart(q,DNS_T_A,addrttl)) return 0;
+@@ -223,6 +400,16 @@
+ wild += 1;
+ }
+
++ if (flagcname) {
++ if (response[RESPONSE_ANSWER+1] >= 100) {
++ dns_domain_free(&flagcname); /* most likely a loop */
++ return 0;
++ }
++ if (cname) dns_domain_free(&cname);
++ cname = flagcname;
++ return doit(cname, qtype);
++ }
++
+ if (!flagfound)
+ response_nxdomain();
+
+@@ -230,22 +417,49 @@
+ AUTHORITY:
+ aupos = response_len;
+
+- if (flagauthoritative && (aupos == anpos)) {
+- cdb_findstart(&c);
+- while (r = find(control,0)) {
+- if (r == -1) return 0;
+- if (byte_equal(type,2,DNS_T_SOA)) {
+- if (!response_rstart(control,DNS_T_SOA,ttl)) return 0;
+- if (!doname()) return 0;
+- if (!doname()) return 0;
+- if (!dobytes(20)) return 0;
+- response_rfinish(RESPONSE_AUTHORITY);
+- break;
++ if (flagauthoritative && (aupos == anpos)) { /* NODATA or NXDOMAIN */
++ if (!flaggavesoa) {
++ cdb_findstart(&c);
++ while (r = find(control,0)) {
++ if (r == -1) return 0;
++ if (!flaggavesoa && byte_equal(type,2,DNS_T_SOA)) {
++ if (!response_rstart(control,DNS_T_SOA,ttl)) return 0;
++ if (!doname()) return 0;
++ if (!doname()) return 0;
++ if (!dobytes(20)) return 0;
++ response_rfinish(RESPONSE_AUTHORITY);
++ flaggavesoa = 1;
++ }
++ else if (do_dnssec && byte_equal(type,2,DNS_T_RRSIG) && dlen > dpos+18
++ && byte_equal(data+dpos,2,DNS_T_SOA)) {
++ if (!response_rstart(control,DNS_T_RRSIG,ttl)) return 0;
++ if (!dobytes(18)) return 0;
++ if (!doname()) return 0;
++ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
++ response_rfinish(RESPONSE_AUTHORITY);
++ }
++ }
++ }
++ if (do_dnssec && flagsigned) {
++ if (flagfound && nsec3) { /* NODATA */
++ if (!addNSEC3(nsec3)) return 0;
++ if (wild != q) { /* Wildcard NODATA */
++ if (!addClosestEncloserProof(q, control, 0)) return 0;
++ }
++ }
++ else { /* NXDOMAIN, or query for NSEC3 owner name */
++ if (!addClosestEncloserProof(q, control, 1)) return 0;
+ }
+ }
+ }
+- else
++ else {
++ if (do_dnssec && wild != q && flagsigned) { /* Wildcard answer */
++ char *nextCloser = q;
++ while (nextCloser + *nextCloser + 1 < wild) { nextCloser += *nextCloser + 1; }
++ if (!addNSEC3Cover(nextCloser, control, 0)) return 0;
++ }
+ if (want(control,DNS_T_NS)) {
++ int have_ds = 0;
+ cdb_findstart(&c);
+ while (r = find(control,0)) {
+ if (r == -1) return 0;
+@@ -254,10 +468,33 @@
+ if (!doname()) return 0;
+ response_rfinish(RESPONSE_AUTHORITY);
+ }
++ else if (do_dnssec && byte_equal(type,2,DNS_T_DS)) {
++ if (!response_rstart(control,DNS_T_DS,ttl)) return 0;
++ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
++ response_rfinish(RESPONSE_AUTHORITY);
++ have_ds = 1;
++ }
++ else if (do_dnssec && byte_equal(type,2,DNS_T_RRSIG) && dlen > dpos+18
++ && (byte_equal(data+dpos,2,DNS_T_NS)
++ || byte_equal(data+dpos,2,DNS_T_DS))) {
++ if (!response_rstart(control,DNS_T_RRSIG,ttl)) return 0;
++ if (!dobytes(18)) return 0;
++ if (!doname()) return 0;
++ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
++ response_rfinish(RESPONSE_AUTHORITY);
++ }
+ }
++ if (do_dnssec && !flagauthoritative && !have_ds) { addNSEC3(control); }
+ }
++ }
+
+ arpos = response_len;
++ if (do_dnssec) {
++ /* Add EDNS0 OPT RR */
++ if (!response_rstart("",DNS_T_OPT,1 << 15)) return 0;
++ uint16_pack_big(response+arpos+3, 512);
++ response_rfinish(RESPONSE_ADDITIONAL);
++ }
+
+ bpos = anpos;
+ while (bpos < arpos) {
+@@ -265,25 +502,33 @@
+ bpos = dns_packet_copy(response,arpos,bpos,x,10); if (!bpos) return 0;
+ if (byte_equal(x,2,DNS_T_NS) || byte_equal(x,2,DNS_T_MX)) {
+ if (byte_equal(x,2,DNS_T_NS)) {
+- if (!dns_packet_getname(response,arpos,bpos,&d1)) return 0;
++ if (!dns_packet_getname(response,arpos,bpos,&wantAddr)) return 0;
+ }
+ else
+- if (!dns_packet_getname(response,arpos,bpos + 2,&d1)) return 0;
+- case_lowerb(d1,dns_domain_length(d1));
+- if (want(d1,DNS_T_A)) {
++ if (!dns_packet_getname(response,arpos,bpos + 2,&wantAddr)) return 0;
++ case_lowerb(wantAddr,dns_domain_length(wantAddr));
++ if (want(wantAddr,DNS_T_A)) {
+ cdb_findstart(&c);
+- while (r = find(d1,0)) {
++ while (r = find(wantAddr,0)) {
+ if (r == -1) return 0;
+ if (byte_equal(type,2,DNS_T_A)) {
+- if (!response_rstart(d1,DNS_T_A,ttl)) return 0;
++ if (!response_rstart(wantAddr,DNS_T_A,ttl)) return 0;
+ if (!dobytes(4)) return 0;
+ response_rfinish(RESPONSE_ADDITIONAL);
+ }
+ else if (byte_equal(type,2,DNS_T_AAAA)) {
+- if (!response_rstart(d1,DNS_T_AAAA,ttl)) return 0;
++ if (!response_rstart(wantAddr,DNS_T_AAAA,ttl)) return 0;
+ if (!dobytes(16)) return 0;
+ response_rfinish(RESPONSE_ADDITIONAL);
+ }
++ else if (do_dnssec && byte_equal(type,2,DNS_T_RRSIG) && dlen > dpos+18
++ && (byte_equal(data+dpos,2,DNS_T_A) || byte_equal(data+dpos,2,DNS_T_AAAA))) {
++ if (!response_rstart(wantAddr,DNS_T_RRSIG,ttl)) return 0;
++ if (!dobytes(18)) return 0;
++ if (!doname()) return 0;
++ if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
++ response_rfinish(RESPONSE_ADDITIONAL);
++ }
+ }
+ }
+ }
+@@ -291,10 +536,10 @@
+ bpos += u16;
+ }
+
+- if (flagauthoritative && (response_len > 512)) {
++ if (flagauthoritative && (response_len > max_response_len)) {
+ byte_zero(response + RESPONSE_ADDITIONAL,2);
+ response_len = arpos;
+- if (response_len > 512) {
++ if (!do_dnssec && response_len > max_response_len) {
+ byte_zero(response + RESPONSE_AUTHORITY,2);
+ response_len = aupos;
+ }
+@@ -316,6 +561,9 @@
+ cdb_init(&c,fd);
+
+ r = doit(q,qtype);
++ if (cname) {
++ dns_domain_free(&cname);
++ }
+
+ cdb_free(&c);
+ close(fd);
+diff -rNU3 djbdns-1.05.tds-base/tinydns-data.c djbdns-1.05.tinydnssec/tinydns-data.c
+--- djbdns-1.05.tds-base/tinydns-data.c 2012-12-06 22:45:38.000000000 +0100
++++ djbdns-1.05.tinydnssec/tinydns-data.c 2012-12-06 22:39:13.000000000 +0100
+@@ -436,7 +436,7 @@
+ i = 0;
+ while (i < f[1].len) {
+ k = f[1].len - i;
+- if (k > 127) k = 127;
++ if (k > 255) k = 255;
+ ch = k;
+ rr_add(&ch,1);
+ rr_add(f[1].s + i,k);
+diff -rNU3 djbdns-1.05.tds-base/tinydns-get.c djbdns-1.05.tinydnssec/tinydns-get.c
+--- djbdns-1.05.tds-base/tinydns-get.c 2001-02-11 22:11:45.000000000 +0100
++++ djbdns-1.05.tinydnssec/tinydns-get.c 2012-12-06 22:39:13.000000000 +0100
+@@ -19,7 +19,7 @@
+
+ void usage(void)
+ {
+- strerr_die1x(100,"tinydns-get: usage: tinydns-get type name [ip]");
++ strerr_die1x(100,"tinydns-get: usage: tinydns-get [-s | -S] type name [ip]");
+ }
+ void oops(void)
+ {
+@@ -39,6 +39,14 @@
+ if (!*argv) usage();
+
+ if (!*++argv) usage();
++
++ max_response_len = 512;
++ if ((*argv)[0] == '-') {
++ if ((*argv)[1] != 's' && (*argv)[1] != 'S' || (*argv)[2]) usage();
++ do_dnssec = 1;
++ max_response_len = (*argv)[1] == 's' ? 1220 : 4000;
++ if (!*++argv) usage();
++ }
+ if (!parsetype(*argv,type)) usage();
+
+ if (!*++argv) usage();