<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>TINYDNS</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -339,3 +339,23 @@
 		glueless every day.
 20010106
 	version: djbdns 1.03.
+20010113
+	ui: increased MAXALIAS to 16.
+	ui: dnscache no longer caches SERVFAIL. per-ip is obviously the
+		way to go.
+	ui: tinydns et al. now respond FORMERR to non-Internet-class
+		queries.
+	ui: tdlookup now returns A records in a random order in the
+		answer section, and truncates the list after 8 records.
+	ui: tinydns-data skips lines starting -.
+20010114
+	internal: documented the tinydns data.cdb format.
+	ui: tinydns-data, tinydns, tinydns-get, axfrdns support client
+		differentiation.
+	ui: dnsqr aborts if it is given an extra argument.
+20010117
+	ui: dnstracesort removes duplicate lines.
+	ui: dnstracesort prints glue.
+	ui: dnstrace uses a ``start'' IP address for the root glue.
+20010121
+	version: djbdns 1.04.</diff>
      <filename>CHANGES</filename>
    </modified>
    <modified>
      <diff>@@ -7,6 +7,7 @@ SYSDEPS
 TARGETS
 Makefile
 dnsroots.global
+TINYDNS
 conf-cc
 conf-ld
 conf-home</diff>
      <filename>FILES</filename>
    </modified>
    <modified>
      <diff>@@ -979,10 +979,10 @@ timeoutwrite.h
 
 tinydns: \
 load tinydns.o server.o droproot.o tdlookup.o response.o qlog.o \
-prot.o libtai.a dns.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
+prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
 socket.lib
 	./load tinydns server.o droproot.o tdlookup.o response.o \
-	qlog.o prot.o libtai.a dns.a env.a cdb.a alloc.a buffer.a \
+	qlog.o prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
 	unix.a byte.a  `cat socket.lib`
 
 tinydns-conf: \
@@ -1019,20 +1019,21 @@ dns.h stralloc.h iopause.h taia.h tai.h uint64.h taia.h
 
 tinydns-get: \
 load tinydns-get.o tdlookup.o response.o printpacket.o printrecord.o \
-parsetype.o libtai.a cdb.a dns.a buffer.a alloc.a unix.a byte.a
+parsetype.o dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a
 	./load tinydns-get tdlookup.o response.o printpacket.o \
-	printrecord.o parsetype.o libtai.a cdb.a dns.a buffer.a \
+	printrecord.o parsetype.o dns.a libtai.a cdb.a buffer.a \
 	alloc.a unix.a byte.a 
 
 tinydns-get.o: \
 compile tinydns-get.c str.h byte.h scan.h exit.h stralloc.h \
 gen_alloc.h buffer.h strerr.h uint16.h response.h uint32.h case.h \
-printpacket.h stralloc.h parsetype.h dns.h stralloc.h iopause.h \
+printpacket.h stralloc.h parsetype.h ip4.h dns.h stralloc.h iopause.h \
 taia.h tai.h uint64.h taia.h
 	./compile tinydns-get.c
 
 tinydns.o: \
-compile tinydns.c
+compile tinydns.c dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h \
+uint64.h taia.h
 	./compile tinydns.c
 
 uint16_pack.o: \
@@ -1063,15 +1064,15 @@ choose compile load tryulong64.c uint64.h1 uint64.h2
 	./choose clr tryulong64 uint64.h1 uint64.h2 &gt; uint64.h
 
 unix.a: \
-makelib error.o error_str.o ndelay_off.o ndelay_on.o open_read.o \
-open_trunc.o openreadclose.o readclose.o seek_set.o socket_accept.o \
-socket_bind.o socket_conn.o socket_listen.o socket_recv.o \
-socket_send.o socket_tcp.o socket_udp.o buffer_read.o buffer_write.o
-	./makelib unix.a error.o error_str.o ndelay_off.o \
-	ndelay_on.o open_read.o open_trunc.o openreadclose.o \
-	readclose.o seek_set.o socket_accept.o socket_bind.o \
-	socket_conn.o socket_listen.o socket_recv.o socket_send.o \
-	socket_tcp.o socket_udp.o buffer_read.o buffer_write.o
+makelib buffer_read.o buffer_write.o error.o error_str.o ndelay_off.o \
+ndelay_on.o open_read.o open_trunc.o openreadclose.o readclose.o \
+seek_set.o socket_accept.o socket_bind.o socket_conn.o \
+socket_listen.o socket_recv.o socket_send.o socket_tcp.o socket_udp.o
+	./makelib unix.a buffer_read.o buffer_write.o error.o \
+	error_str.o ndelay_off.o ndelay_on.o open_read.o \
+	open_trunc.o openreadclose.o readclose.o seek_set.o \
+	socket_accept.o socket_bind.o socket_conn.o socket_listen.o \
+	socket_recv.o socket_send.o socket_tcp.o socket_udp.o
 
 utime: \
 load utime.o byte.a</diff>
      <filename>Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
-djbdns 1.03
-20010106
+djbdns 1.04
+20010121
 Copyright 2001
 D. J. Bernstein
 </diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -5,9 +5,8 @@ try to get the root authorities to set up a secure, usable NS-list system
 have dnscache-conf keep track of copies of dnsroots.global
 incorporate automatic NS-list upgrades
 
-consider merging pickdns and tinydns
+consider dead-server table in dnscache or in kernel
 
-consider dead-server table in dnscache
-
-IPv6 records
+IPv6 lookups
+maybe reverse IPv6 lookups; what a mess
 DNS over IPv6</diff>
      <filename>TODO</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-djbdns 1.03
+djbdns 1.04</diff>
      <filename>VERSION</filename>
    </modified>
    <modified>
      <diff>@@ -121,6 +121,10 @@ void get(char *buf,unsigned int len)
   }
 }
 
+char ip[4];
+unsigned long port;
+char clientloc[2];
+
 struct tai now;
 char data[32767];
 uint32 dlen;
@@ -145,6 +149,7 @@ int build(stralloc *sa,char *q,int flagsoa)
   unsigned int rdatapos;
   char misc[20];
   char type[2];
+  char recordloc[2];
   char ttl[4];
   char ttd[8];
   struct tai cutoff;
@@ -156,6 +161,11 @@ int build(stralloc *sa,char *q,int flagsoa)
 
   if (!stralloc_copyb(sa,&quot;\0\0\200\200\0\0\0\1\0\0\0\0&quot;,12)) nomem();
   copy(misc,1);
+  if ((misc[0] == '=' + 1) || (misc[0] == '*' + 1)) {
+    --misc[0];
+    copy(recordloc,2);
+    if (byte_diff(recordloc,2,clientloc)) return 0;
+  }
   if (misc[0] == '*') {
     if (flagsoa) return 0;
     if (!stralloc_catb(sa,&quot;\1*&quot;,2)) nomem();
@@ -220,6 +230,20 @@ void doaxfr(void)
 
   tai_now(&amp;now);
   cdb_init(&amp;c,fdcdb);
+
+  byte_zero(clientloc,2);
+  key[0] = 0;
+  key[1] = '%';
+  byte_copy(key + 2,4,ip);
+  r = cdb_find(&amp;c,key,6);
+  if (!r) r = cdb_find(&amp;c,key,5);
+  if (!r) r = cdb_find(&amp;c,key,4);
+  if (!r) r = cdb_find(&amp;c,key,3);
+  if (!r) r = cdb_find(&amp;c,key,2);
+  if (r == -1) die_cdbread();
+  if (r &amp;&amp; (cdb_datalen(&amp;c) == 2))
+    if (cdb_read(&amp;c,clientloc,2,cdb_datapos(&amp;c)) == -1) die_cdbread();
+
   cdb_findstart(&amp;c);
   for (;;) {
     r = cdb_findnext(&amp;c,zone,zonelen);
@@ -230,6 +254,7 @@ void doaxfr(void)
     if (cdb_read(&amp;c,data,dlen,cdb_datapos(&amp;c)) == -1) die_cdbformat();
     if (build(&amp;soa,zone,1)) break;
   }
+
   cdb_free(&amp;c);
   print(soa.s,soa.len);
 
@@ -257,6 +282,7 @@ void doaxfr(void)
     if (dlen &gt; sizeof data) die_cdbformat();
     get(data,dlen);
 
+    if ((klen &gt; 1) &amp;&amp; (key[0] == 0)) continue; /* location */
     if (klen &lt; 1) die_cdbformat();
     if (dns_packet_getname(key,klen,0,&amp;q) != klen) die_cdbformat();
     if (!dns_domain_suffix(q,zone)) continue;
@@ -279,13 +305,12 @@ void netread(char *buf,unsigned int len)
   }
 }
 
-char ip[4];
-unsigned long port;
-
 char tcpheader[2];
 char buf[512];
 uint16 len;
 
+static char seed[128];
+
 int main()
 {
   unsigned int pos;
@@ -294,6 +319,7 @@ int main()
   const char *x;
 
   droproot(FATAL);
+  dns_random_init(seed);
 
   axfr = env_get(&quot;AXFR&quot;);
   </diff>
      <filename>axfrdns.c</filename>
    </modified>
    <modified>
      <diff>@@ -41,6 +41,8 @@ int main(int argc,char **argv)
   if (!*++argv) usage();
   if (!dns_domain_fromdot(&amp;q,*argv,str_len(*argv))) oops();
 
+  if (*++argv) usage();
+
   if (!stralloc_copys(&amp;out,&quot;&quot;)) oops();
   uint16_unpack_big(type,&amp;u16);
   if (!stralloc_catulong0(&amp;out,u16,0)) oops();</diff>
      <filename>dnsqr.c</filename>
    </modified>
    <modified>
      <diff>@@ -400,7 +400,7 @@ int main(int argc,char **argv)
 
   dns_random_init(seed);
 
-  if (!stralloc_copys(&amp;querystr,&quot;0:.:.::&quot;)) nomem();
+  if (!stralloc_copys(&amp;querystr,&quot;0:.:.:start:&quot;)) nomem();
 
   if (!address_alloc_readyplus(&amp;address,1)) nomem();
   if (!query_alloc_readyplus(&amp;query,1)) nomem();</diff>
      <filename>dnstrace.c</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,19 @@
-
-sort -t: +0 -2 +4 +3 -4 +2 -3 | awk -F: '
+awk -F: '
+  BEGIN { OFS=&quot;:&quot; }
   {
-    if ($5 == &quot;A&quot;) next
-    if ($5 == &quot;NS&quot;) next
     if ($5 == &quot;tx&quot;) next
-
+    if ($5 == &quot;A&quot;) {
+      print &quot;glue&quot;,$6,$3,$4,&quot;answer&quot;,$6&quot; A &quot;$7
+      next
+    }
+    if ($5 == &quot;NS&quot;) {
+      print &quot;glue&quot;,$6,$3,$4,&quot;answer&quot;,$6&quot; NS &quot;$7
+      next
+    }
+    print
+  }
+' | sort -t: +0 -2 +4 +3 -4 +2 -3 | uniq | awk -F: '
+  {
     type = $1
     q = $2
     c = $3</diff>
      <filename>dnstracesort.sh</filename>
    </modified>
    <modified>
      <diff>@@ -175,12 +175,6 @@ void log_cachednxdomain(const char *dn)
   line();
 }
 
-void log_cachedservfail(const char *dn)
-{
-  string(&quot;cached servfail &quot;); name(dn);
-  line();
-}
-
 void log_nxdomain(const char server[4],const char *q,unsigned int ttl)
 {
   string(&quot;nxdomain &quot;); ip(server); space(); number(ttl); space();</diff>
      <filename>log.c</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,6 @@ extern void log_tcpclose(const char *,unsigned int);
 extern void log_cachedanswer(const char *,const char *);
 extern void log_cachedcname(const char *,const char *);
 extern void log_cachednxdomain(const char *);
-extern void log_cachedservfail(const char *);
 extern void log_cachedns(const char *,const char *);
 
 extern void log_tx(const char *,const char *,const char *,const char *,unsigned int);</diff>
      <filename>log.h</filename>
    </modified>
    <modified>
      <diff>@@ -197,7 +197,6 @@ static int doit(struct query *z,int state)
   errno = error_io;
   if (state == 1) goto HAVEPACKET;
   if (state == -1) {
-    cachegeneric(DNS_T_AXFR,z-&gt;name[z-&gt;level],&quot;&quot;,0,60);
     log_servfail(z-&gt;name[z-&gt;level]);
     goto SERVFAIL;
   }
@@ -251,13 +250,6 @@ static int doit(struct query *z,int state)
       goto NXDOMAIN;
     }
 
-    byte_copy(key,2,DNS_T_AXFR);
-    cached = cache_get(key,dlen + 2,&amp;cachedlen,&amp;ttl);
-    if (cached) {
-      log_cachedservfail(d);
-      goto SERVFAIL;
-    }
-
     byte_copy(key,2,DNS_T_CNAME);
     cached = cache_get(key,dlen + 2,&amp;cachedlen,&amp;ttl);
     if (cached) {</diff>
      <filename>query.c</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@
 #include &quot;uint32.h&quot;
 
 #define QUERY_MAXLEVEL 5
-#define QUERY_MAXALIAS 4
+#define QUERY_MAXALIAS 16
 #define QUERY_MAXNS 16
 
 struct query {</diff>
      <filename>query.h</filename>
    </modified>
    <modified>
      <diff>@@ -190,47 +190,6 @@ dnsname: fatal: unable to parse IP address 1.2.3
 127.5.6.7+one two three
 10+one two three
 0
---- tinydns-data does not complain about large packets
-0
-1 www.movie.edu:
-591 bytes, 1+35+0+0 records, response, authoritative, noerror
-query: 1 www.movie.edu
-answer: www.movie.edu 86400 A 1.2.3.5
-answer: www.movie.edu 86400 A 1.2.3.6
-answer: www.movie.edu 86400 A 1.2.3.7
-answer: www.movie.edu 86400 A 1.2.3.8
-answer: www.movie.edu 86400 A 1.2.3.9
-answer: www.movie.edu 86400 A 1.2.3.10
-answer: www.movie.edu 86400 A 1.2.3.11
-answer: www.movie.edu 86400 A 1.2.3.12
-answer: www.movie.edu 86400 A 1.2.3.13
-answer: www.movie.edu 86400 A 1.2.3.14
-answer: www.movie.edu 86400 A 1.2.3.15
-answer: www.movie.edu 86400 A 1.2.3.16
-answer: www.movie.edu 86400 A 1.2.3.17
-answer: www.movie.edu 86400 A 1.2.3.18
-answer: www.movie.edu 86400 A 1.2.3.19
-answer: www.movie.edu 86400 A 1.2.3.20
-answer: www.movie.edu 86400 A 1.2.3.21
-answer: www.movie.edu 86400 A 1.2.3.22
-answer: www.movie.edu 86400 A 1.2.3.23
-answer: www.movie.edu 86400 A 1.2.3.24
-answer: www.movie.edu 86400 A 1.2.3.25
-answer: www.movie.edu 86400 A 1.2.3.26
-answer: www.movie.edu 86400 A 1.2.3.27
-answer: www.movie.edu 86400 A 1.2.3.28
-answer: www.movie.edu 86400 A 1.2.3.29
-answer: www.movie.edu 86400 A 1.2.3.30
-answer: www.movie.edu 86400 A 1.2.3.31
-answer: www.movie.edu 86400 A 1.2.3.32
-answer: www.movie.edu 86400 A 1.2.3.33
-answer: www.movie.edu 86400 A 1.2.3.34
-answer: www.movie.edu 86400 A 1.2.3.35
-answer: www.movie.edu 86400 A 1.2.3.36
-answer: www.movie.edu 86400 A 1.2.3.37
-answer: www.movie.edu 86400 A 1.2.3.38
-answer: www.movie.edu 86400 A 1.2.3.39
-0
 --- tinydns-data complains about unrecognized initial characters
 tinydns-data: fatal: unable to parse data line 3: unrecognized leading character
 111
@@ -242,12 +201,12 @@ tinydns-data: fatal: unable to create data.tmp: symbolic link loop
 --- tinydns-data produces A records
 1 wormhole.movie.edu:
 117 bytes, 1+2+2+1 records, response, authoritative, noerror
-query: 1 wormhole.movie.edu
+additional: a.ns.movie.edu 259200 A 192.249.249.3
 answer: wormhole.movie.edu 86400 A 192.249.249.1
 answer: wormhole.movie.edu 86400 A 192.253.253.1
 authority: movie.edu 259200 NS a.ns.movie.edu
 authority: movie.edu 259200 NS wormhole.movie.edu
-additional: a.ns.movie.edu 259200 A 192.249.249.3
+query: 1 wormhole.movie.edu
 0
 --- tinydns-data produces NS records
 2 movie.edu:
@@ -526,9 +485,9 @@ query: 255 test
 answer: test 98765 SOA primary.server host.master 1234567 2345678 3456789 4567890 5678901
 answer: test 37 NS ns.test
 answer: test 41 MX 0 mx.test
-answer: test 39 A 1.2.3.4
 answer: test 42 16 \004Text
 answer: test 43 12345 Binary
+answer: test 39 A 1.2.3.4
 additional: ns.test 37 A 1.2.3.4
 additional: mx.test 41 A 1.2.3.4
 0
@@ -809,11 +768,11 @@ answer: 127.43.123.234 655360 A 127.43.123.234
 0
 255 www.test:
 91 bytes, 1+2+1+1 records, response, authoritative, noerror
-query: 255 www.test
+additional: ns.test 259200 A 127.43.0.2
 answer: www.test 86400 A 127.43.0.100
 answer: www.test 86400 A 127.43.0.101
 authority: test 259200 NS ns.test
-additional: ns.test 259200 A 127.43.0.2
+query: 255 www.test
 0
 255 test:
 173 bytes, 1+4+0+3 records, response, authoritative, noerror
@@ -900,6 +859,102 @@ answer: 1.0.0.4.rbl.test 2048 16 \037See\040http://www.rbl.test/4.0.0.1
 34 bytes, 1+0+0+0 records, response, authoritative, nxdomain
 query: 255 0.0.0.4.rbl.test
 0
+--- tinydns handles differentiation
+
+0
+127.43.0.102 
+0
+
+127.43.0.100
+127.43.0.102
+0
+
+127.43.0.100
+127.43.0.102
+0
+255 pick.test5:
+81 bytes, 1+0+1+0 records, response, authoritative, nxdomain
+query: 255 pick.test5
+authority: test5 2560 SOA me.ns.test5 hostmaster.test5 987654321 16384 2048 1048576 2560
+0
+255 pick2.test5:
+81 bytes, 1+1+1+1 records, response, authoritative, noerror
+query: 255 pick2.test5
+answer: pick2.test5 86400 A 127.43.0.102
+authority: test5 259200 NS me.ns.test5
+additional: me.ns.test5 259200 A 127.43.0.2
+0
+255 pick3.test5:
+97 bytes, 1+2+1+1 records, response, authoritative, noerror
+additional: me.ns.test5 259200 A 127.43.0.2
+answer: pick3.test5 86400 A 127.43.0.100
+answer: pick3.test5 86400 A 127.43.0.102
+authority: test5 259200 NS me.ns.test5
+query: 255 pick3.test5
+0
+103 bytes, 1+2+1+1 records, response, authoritative, noerror
+255 really.wild.test5:
+additional: me.ns.test5 259200 A 127.43.0.2
+answer: really.wild.test5 86400 A 127.43.0.100
+answer: really.wild.test5 86400 A 127.43.0.102
+authority: test5 259200 NS me.ns.test5
+query: 255 really.wild.test5
+0
+--- tinydns-get handles differentiation
+255 pick.test5:
+80 bytes, 1+1+1+1 records, response, authoritative, noerror
+query: 255 pick.test5
+answer: pick.test5 86400 A 127.43.0.101
+authority: test5 259200 NS ex.ns.test5
+additional: ex.ns.test5 259200 A 127.43.0.2
+0
+255 pick2.test5:
+82 bytes, 1+0+1+0 records, response, authoritative, nxdomain
+query: 255 pick2.test5
+authority: test5 2560 SOA ex.ns.test5 hostmaster.test5 987654321 16384 2048 1048576 2560
+0
+255 pick3.test5:
+97 bytes, 1+2+1+1 records, response, authoritative, noerror
+additional: ex.ns.test5 259200 A 127.43.0.2
+answer: pick3.test5 86400 A 127.43.0.100
+answer: pick3.test5 86400 A 127.43.0.101
+authority: test5 259200 NS ex.ns.test5
+query: 255 pick3.test5
+0
+103 bytes, 1+2+1+1 records, response, authoritative, noerror
+255 really.wild.test5:
+additional: ex.ns.test5 259200 A 127.43.0.2
+answer: really.wild.test5 86400 A 127.43.0.100
+answer: really.wild.test5 86400 A 127.43.0.101
+authority: test5 259200 NS ex.ns.test5
+query: 255 really.wild.test5
+0
+255 pick.test5:
+81 bytes, 1+0+1+0 records, response, authoritative, nxdomain
+query: 255 pick.test5
+authority: test5 2560 SOA i4.ns.test5 hostmaster.test5 987654321 16384 2048 1048576 2560
+0
+255 pick2.test5:
+82 bytes, 1+0+1+0 records, response, authoritative, nxdomain
+query: 255 pick2.test5
+authority: test5 2560 SOA i4.ns.test5 hostmaster.test5 987654321 16384 2048 1048576 2560
+0
+255 pick3.test5:
+97 bytes, 1+2+1+1 records, response, authoritative, noerror
+additional: i4.ns.test5 259200 A 127.43.0.2
+answer: pick3.test5 86400 A 127.43.0.100
+answer: pick3.test5 86400 A 127.43.0.104
+authority: test5 259200 NS i4.ns.test5
+query: 255 pick3.test5
+0
+103 bytes, 1+2+1+1 records, response, authoritative, noerror
+255 really.wild.test5:
+additional: i4.ns.test5 259200 A 127.43.0.2
+answer: really.wild.test5 86400 A 127.43.0.100
+answer: really.wild.test5 86400 A 127.43.0.104
+authority: test5 259200 NS i4.ns.test5
+query: 255 really.wild.test5
+0
 --- pickdns works
 127.43.0.101 
 0
@@ -944,6 +999,44 @@ Ztest:ns.test.:hostmaster.test.:987654321:16384:2048:1048576:2560:2560
 &amp;rbl.test::ns.rbl.test.:259200
 +ns.rbl.test:127.43.0.5:259200
 :big.test:16:\1770123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456\1777890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123\1774567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\1771234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567\1778901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234\1775678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901\1772345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678o901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789:86400
+--- axfrdns handles differentiation
+0
+#987654321 auto axfr-get
+Ztest5:me.ns.test5.:hostmaster.test5.:987654321:16384:2048:1048576:2560:2560
+&amp;test5::me.ns.test5.:259200
++me.ns.test5:127.43.0.2:259200
++pick2.test5:127.43.0.102:86400
++pick3.test5:127.43.0.100:86400
++pick3.test5:127.43.0.102:86400
++\052.wild.test5:127.43.0.100:86400
++\052.wild.test5:127.43.0.102:86400
+0
+#987654321 auto axfr-get
+Ztest5:i3.ns.test5.:hostmaster.test5.:987654321:16384:2048:1048576:2560:2560
+&amp;test5::i3.ns.test5.:259200
++i3.ns.test5:127.43.0.2:259200
++pick3.test5:127.43.0.100:86400
++pick3.test5:127.43.0.103:86400
++\052.wild.test5:127.43.0.100:86400
++\052.wild.test5:127.43.0.103:86400
+0
+#987654321 auto axfr-get
+Ztest5:i4.ns.test5.:hostmaster.test5.:987654321:16384:2048:1048576:2560:2560
+&amp;test5::i4.ns.test5.:259200
++i4.ns.test5:127.43.0.2:259200
++pick3.test5:127.43.0.100:86400
++pick3.test5:127.43.0.104:86400
++\052.wild.test5:127.43.0.100:86400
++\052.wild.test5:127.43.0.104:86400
+0
+#987654321 auto axfr-get
+Ztest5:i5.ns.test5.:hostmaster.test5.:987654321:16384:2048:1048576:2560:2560
+&amp;test5::i5.ns.test5.:259200
++i5.ns.test5:127.43.0.2:259200
++pick3.test5:127.43.0.100:86400
++pick3.test5:127.43.0.105:86400
++\052.wild.test5:127.43.0.100:86400
++\052.wild.test5:127.43.0.105:86400
 --- axfrdns gives authoritative answers
 255 test4:
 727 bytes, 1+12+0+0 records, response, authoritative, noerror</diff>
      <filename>rts.exp</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@
 # You are running as root.
 # You have dns{cache,log}, {tiny,pick,wall,axfr,rbl}dns accounts.
 # You have local IP addresses 127.43.0.{1,2,3,4,5}.
+# You are connected to the Internet.
 #
 # Some features not tested here:
 # dns_random works.
@@ -39,6 +40,7 @@ DNSCACHEIP=127.555.0.1; export DNSCACHEIP
 echo '--- dnscache-conf works'
 dnscache-conf dnscache dnslog $service/dnscache 127.555.0.1
 echo 127.555.0.2 &gt; $service/dnscache/root/servers/tEST
+echo 127.555.0.2 &gt; $service/dnscache/root/servers/tEST5
 echo 127.555.0.4 &gt; $service/dnscache/root/servers/43.127.iN-aDDR.aRPA
 touch $service/dnscache/root/ip/127.43.0.1
 supervise $service/dnscache | supervise $service/dnscache/log &amp;
@@ -182,49 +184,6 @@ echo $?
 
 
 echo '
-.movie.edu:1.2.3.4
-+www.movie.edu:1.2.3.5
-+www.movie.edu:1.2.3.6
-+www.movie.edu:1.2.3.7
-+www.movie.edu:1.2.3.8
-+www.movie.edu:1.2.3.9
-+www.movie.edu:1.2.3.10
-+www.movie.edu:1.2.3.11
-+www.movie.edu:1.2.3.12
-+www.movie.edu:1.2.3.13
-+www.movie.edu:1.2.3.14
-+www.movie.edu:1.2.3.15
-+www.movie.edu:1.2.3.16
-+www.movie.edu:1.2.3.17
-+www.movie.edu:1.2.3.18
-+www.movie.edu:1.2.3.19
-+www.movie.edu:1.2.3.20
-+www.movie.edu:1.2.3.21
-+www.movie.edu:1.2.3.22
-+www.movie.edu:1.2.3.23
-+www.movie.edu:1.2.3.24
-+www.movie.edu:1.2.3.25
-+www.movie.edu:1.2.3.26
-+www.movie.edu:1.2.3.27
-+www.movie.edu:1.2.3.28
-+www.movie.edu:1.2.3.29
-+www.movie.edu:1.2.3.30
-+www.movie.edu:1.2.3.31
-+www.movie.edu:1.2.3.32
-+www.movie.edu:1.2.3.33
-+www.movie.edu:1.2.3.34
-+www.movie.edu:1.2.3.35
-+www.movie.edu:1.2.3.36
-+www.movie.edu:1.2.3.37
-+www.movie.edu:1.2.3.38
-+www.movie.edu:1.2.3.39
-' &gt; rts-tmp/data
-
-echo '--- tinydns-data does not complain about large packets'
-( cd rts-tmp; tinydns-data; echo $? )
-( cd rts-tmp; tinydns-get a www.movie.edu; echo $? )
-
-echo '
 =movie.edu:1.2.3.4
 *star
 ' &gt; rts-tmp/data
@@ -286,7 +245,7 @@ echo '--- tinydns-data handles simple example'
 ( cd rts-tmp; tinydns-data; echo $? )
 
 echo '--- tinydns-data produces A records'
-( cd rts-tmp; tinydns-get 1 wormhole.movie.edu; echo $? )
+( cd rts-tmp; tinydns-get 1 wormhole.movie.edu | sort; echo $? )
 
 echo '--- tinydns-data produces NS records'
 ( cd rts-tmp; tinydns-get 2 movie.edu; echo $? )
@@ -551,6 +510,32 @@ C*.Www.Test2:Www.Test2:5000
 '\''Test4:801234567890123456789012345678901234567890123456789
 '\''Test4:901234567890123456789012345678901234567890123456789
 '\''Big.Test:0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+%i3:127.555.0.3
+%i4:127.555.0.4
+%i5:127.555.0.5
+%ME:127
+%EX
+.Test5:127.555.0.2:ex:::EX
+.Test5:127.555.0.2:me:::ME
+.Test5:127.555.0.2:i3:::i3
+.Test5:127.555.0.2:i4:::i4
+.Test5:127.555.0.2:i5:::i5
+-Pick.Test5:127.555.0.100:::EX
++Pick.Test5:127.555.0.101:::EX
+-Pick2.Test5:127.555.0.102:::ME
++Pick2.Test5:127.555.0.102:::ME
++Pick3.Test5:127.555.0.100
++Pick3.Test5:127.555.0.101:::EX
++Pick3.Test5:127.555.0.102:::ME
++Pick3.Test5:127.555.0.103:::i3
++Pick3.Test5:127.555.0.104:::i4
++Pick3.Test5:127.555.0.105:::i5
++*.Wild.Test5:127.555.0.100
++*.Wild.Test5:127.555.0.101:::EX
++*.Wild.Test5:127.555.0.102:::ME
++*.Wild.Test5:127.555.0.103:::i3
++*.Wild.Test5:127.555.0.104:::i4
++*.Wild.Test5:127.555.0.105:::i5
 ' &gt; $service/tinydns/root/data
 utime $service/tinydns/root/data 987654321
 ( cd $service/tinydns/root; tinydns-data )
@@ -595,7 +580,7 @@ echo '
 ( cd $service/rbldns/root; rbldns-data )
 
 echo '
-127.:allow,AXFR=&quot;tEsT/TeSt2&quot;
+127.:allow,AXFR=&quot;tEsT/TeSt2/TEst5&quot;
 :deny
 ' &gt; $service/axfrdns/tcp
 ( cd $service/axfrdns; tcprules tcp.cdb tcp.tmp &lt; tcp )
@@ -610,7 +595,7 @@ dnsip WWW.TEST | tr ' ' '\012' | sort
 echo $?
 dnsmx TEST
 echo $?
-dnsq 255 WWW.TEST 127.555.0.2
+dnsq 255 WWW.TEST 127.555.0.2 | sort
 echo $?
 dnsq Any TEST 127.555.0.2
 echo $?
@@ -668,6 +653,36 @@ echo $?
 dnsq 255 0.0.0.4.rbl.test 127.555.0.5
 echo $?
 
+echo '--- tinydns handles differentiation'
+dnsip PICK.TEST5 
+echo $?
+dnsip PICK2.TEST5 
+echo $?
+dnsip PICK3.TEST5  | tr ' ' '\012' | sort
+echo $?
+dnsip REALLY.WILD.TEST5  | tr ' ' '\012' | sort
+echo $?
+dnsq 255 PICK.TEST5 127.555.0.2
+echo $?
+dnsq 255 PICK2.TEST5 127.555.0.2
+echo $?
+dnsq 255 PICK3.TEST5 127.555.0.2 | sort
+echo $?
+dnsq 255 REALLY.WILD.TEST5 127.555.0.2 | sort
+echo $?
+
+echo '--- tinydns-get handles differentiation'
+( cd rts-tmp/service/tinydns/root
+  tinydns-get 255 PICK.TEST5 1.2.3.4; echo $?
+  tinydns-get 255 PICK2.TEST5 1.2.3.4; echo $?
+  tinydns-get 255 PICK3.TEST5 1.2.3.4 | sort; echo $?
+  tinydns-get 255 REALLY.WILD.TEST5 1.2.3.4 | sort; echo $?
+  tinydns-get 255 PICK.TEST5 127.555.0.4; echo $?
+  tinydns-get 255 PICK2.TEST5 127.555.0.4; echo $?
+  tinydns-get 255 PICK3.TEST5 127.555.0.4 | sort; echo $?
+  tinydns-get 255 REALLY.WILD.TEST5 127.555.0.4 | sort; echo $?
+)
+
 echo '--- pickdns works'
 dnsip PICK.TEST
 echo $?
@@ -697,6 +712,23 @@ tcpclient -RHl0 127.43.0.2 53 axfr-get TEST rts-tmp/zone rts-tmp/zone.tmp
 echo $?
 cat rts-tmp/zone
 
+echo '--- axfrdns handles differentiation'
+tcpclient -RHl0 -i 127.43.0.2 127.43.0.2 53 axfr-get TEST5 rts-tmp/zone5 rts-tmp/zone5.tmp
+echo $?
+cat rts-tmp/zone5
+rm rts-tmp/zone5
+tcpclient -RHl0 -i 127.43.0.3 127.43.0.2 53 axfr-get TEST5 rts-tmp/zone5 rts-tmp/zone5.tmp
+echo $?
+cat rts-tmp/zone5
+rm rts-tmp/zone5
+tcpclient -RHl0 -i 127.43.0.4 127.43.0.2 53 axfr-get TEST5 rts-tmp/zone5 rts-tmp/zone5.tmp
+echo $?
+cat rts-tmp/zone5
+rm rts-tmp/zone5
+tcpclient -RHl0 -i 127.43.0.5 127.43.0.2 53 axfr-get TEST5 rts-tmp/zone5 rts-tmp/zone5.tmp
+echo $?
+cat rts-tmp/zone5
+
 echo '--- axfrdns gives authoritative answers'
 dnsq any Test4 127.43.0.2
 echo $?</diff>
      <filename>rts.tests</filename>
    </modified>
    <modified>
      <diff>@@ -45,7 +45,7 @@ static int doit(void)
   if (byte_equal(qclass,2,DNS_C_IN))
     response[2] |= 4;
   else
-    if (byte_diff(qclass,2,DNS_C_ANY)) goto NOQ;
+    if (byte_diff(qclass,2,DNS_C_ANY)) goto WEIRDCLASS;
   response[3] &amp;= ~128;
   if (!(header[2] &amp; 1)) response[2] &amp;= ~1;
 
@@ -66,6 +66,13 @@ static int doit(void)
   qlog(ip,port,header,q,qtype,&quot; I &quot;);
   return 1;
 
+  WEIRDCLASS:
+  response[3] &amp;= ~15;
+  response[3] |= 1;
+  byte_copy(response + response_len - 2,2,qclass);
+  qlog(ip,port,header,q,qtype,&quot; C &quot;);
+  return 1;
+
   NOQ:
   qlog(ip,port,&quot;\0\0&quot;,&quot;&quot;,&quot;\0\0&quot;,&quot; / &quot;);
   return 0;</diff>
      <filename>server.c</filename>
    </modified>
    <modified>
      <diff>@@ -33,8 +33,10 @@ static int want(const char *owner,const char type[2])
 
 static char *d1;
 
+static char clientloc[2];
 static struct tai now;
 static struct cdb c;
+
 static char data[32767];
 static uint32 dlen;
 static unsigned int dpos;
@@ -48,6 +50,7 @@ static int find(char *d,int flagwild)
   struct tai cutoff;
   char ttd[8];
   char ttlstr[4];
+  char recordloc[2];
   double newttl;
 
   for (;;) {
@@ -58,6 +61,11 @@ static int find(char *d,int flagwild)
     if (cdb_read(&amp;c,data,dlen,cdb_datapos(&amp;c)) == -1) return -1;
     dpos = dns_packet_copy(data,dlen,0,type,2); if (!dpos) return -1;
     dpos = dns_packet_copy(data,dlen,dpos,&amp;ch,1); if (!dpos) return -1;
+    if ((ch == '=' + 1) || (ch == '*' + 1)) {
+      --ch;
+      dpos = dns_packet_copy(data,dlen,dpos,recordloc,2); if (!dpos) return -1;
+      if (byte_diff(recordloc,2,clientloc)) continue;
+    }
     if (flagwild != (ch == '*')) continue;
     dpos = dns_packet_copy(data,dlen,dpos,ttlstr,4); if (!dpos) return -1;
     uint32_unpack_big(ttlstr,&amp;ttl);
@@ -110,6 +118,10 @@ static int doit(char *q,char qtype[2])
   int flagauthoritative;
   char x[20];
   uint16 u16;
+  char addr[8][4];
+  int addrnum;
+  uint32 addrttl;
+  int i;
 
   anpos = response_len;
 
@@ -140,12 +152,25 @@ static int doit(char *q,char qtype[2])
   wild = q;
 
   for (;;) {
+    addrnum = 0;
+    addrttl = 0;
     cdb_findstart(&amp;c);
     while (r = find(wild,wild != q)) {
       if (r == -1) return 0;
       flagfound = 1;
       if (flaggavesoa &amp;&amp; byte_equal(type,2,DNS_T_SOA)) continue;
       if (byte_diff(type,2,qtype) &amp;&amp; byte_diff(qtype,2,DNS_T_ANY) &amp;&amp; byte_diff(type,2,DNS_T_CNAME)) continue;
+      if (byte_equal(type,2,DNS_T_A) &amp;&amp; (dlen - dpos == 4)) {
+	addrttl = ttl;
+	i = dns_random(addrnum + 1);
+	if (i &lt; 8) {
+	  if ((i &lt; addrnum) &amp;&amp; (addrnum &lt; 8))
+	    byte_copy(addr[addrnum],4,addr[i]);
+	  byte_copy(addr[i],4,data + dpos);
+	}
+	if (addrnum &lt; 1000000) ++addrnum;
+	continue;
+      }
       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;
@@ -164,6 +189,13 @@ static int doit(char *q,char qtype[2])
         if (!response_addbytes(data + dpos,dlen - dpos)) return 0;
       response_rfinish(RESPONSE_ANSWER);
     }
+    for (i = 0;i &lt; addrnum;++i)
+      if (i &lt; 8) {
+	if (!response_rstart(q,DNS_T_A,addrttl)) return 0;
+	if (!response_addbytes(addr[i],4)) return 0;
+	response_rfinish(RESPONSE_ANSWER);
+      }
+
     if (flagfound) break;
     if (wild == control) break;
     if (!*wild) break; /* impossible */
@@ -249,14 +281,30 @@ static int doit(char *q,char qtype[2])
 int respond(char *q,char qtype[2],char ip[4])
 {
   int fd;
-  int result;
+  int r;
+  char key[6];
 
   tai_now(&amp;now);
   fd = open_read(&quot;data.cdb&quot;);
   if (fd == -1) return 0;
   cdb_init(&amp;c,fd);
-  result = doit(q,qtype);
+
+  byte_zero(clientloc,2);
+  key[0] = 0;
+  key[1] = '%';
+  byte_copy(key + 2,4,ip);
+  r = cdb_find(&amp;c,key,6);
+  if (!r) r = cdb_find(&amp;c,key,5);
+  if (!r) r = cdb_find(&amp;c,key,4);
+  if (!r) r = cdb_find(&amp;c,key,3);
+  if (!r) r = cdb_find(&amp;c,key,2);
+  if (r == -1) return 0;
+  if (r &amp;&amp; (cdb_datalen(&amp;c) == 2))
+    if (cdb_read(&amp;c,clientloc,2,cdb_datapos(&amp;c)) == -1) return 0;
+
+  r = doit(q,qtype);
+
   cdb_free(&amp;c);
   close(fd);
-  return result;
+  return r;
 }</diff>
      <filename>tdlookup.c</filename>
    </modified>
    <modified>
      <diff>@@ -53,6 +53,30 @@ void ttdparse(stralloc *sa,char ttd[8])
   }
 }
 
+void locparse(stralloc *sa,char loc[2])
+{
+  loc[0] = (sa-&gt;len &gt; 0) ? sa-&gt;s[0] : 0;
+  loc[1] = (sa-&gt;len &gt; 1) ? sa-&gt;s[1] : 0;
+}
+
+void ipprefix_cat(stralloc *out,char *s)
+{
+  unsigned long u;
+  char ch;
+  unsigned int j;
+
+  for (;;)
+    if (*s == '.')
+      ++s;
+    else {
+      j = scan_ulong(s,&amp;u);
+      if (!j) return;
+      s += j;
+      ch = u;
+      if (!stralloc_catb(out,&amp;ch,1)) nomem();
+    }
+}
+
 void txtparse(stralloc *sa)
 {
   char ch;
@@ -109,11 +133,16 @@ void rr_addname(const char *d)
 {
   rr_add(d,dns_domain_length(d));
 }
-void rr_start(const char type[2],unsigned long ttl,const char ttd[8])
+void rr_start(const char type[2],unsigned long ttl,const char ttd[8],const char loc[2])
 {
   char buf[4];
   if (!stralloc_copyb(&amp;result,type,2)) nomem();
-  rr_add(&quot;=&quot;,1);
+  if (byte_equal(loc,2,&quot;\0\0&quot;))
+    rr_add(&quot;=&quot;,1);
+  else {
+    rr_add(&quot;&gt;&quot;,1);
+    rr_add(loc,2);
+  }
   uint32_pack_big(buf,ttl);
   rr_add(buf,4);
   rr_add(ttd,8);
@@ -122,7 +151,7 @@ void rr_finish(const char *owner)
 {
   if (byte_equal(owner,2,&quot;\1*&quot;)) {
     owner += 2;
-    result.s[2] = '*';
+    result.s[2] -= 19;
   }
   if (!stralloc_copyb(&amp;key,owner,dns_domain_length(owner))) nomem();
   case_lowerb(key.s,key.len);
@@ -137,7 +166,7 @@ static stralloc line;
 int match = 1;
 unsigned long linenum = 0;
 
-#define NUMFIELDS 10
+#define NUMFIELDS 15
 static stralloc f[NUMFIELDS];
 
 static char *d1;
@@ -161,6 +190,7 @@ int main()
   char ch;
   unsigned long ttl;
   char ttd[8];
+  char loc[2];
   unsigned long u;
   char ip[4];
   char type[2];
@@ -192,6 +222,7 @@ int main()
     }
     if (!line.len) continue;
     if (line.s[0] == '#') continue;
+    if (line.s[0] == '-') continue;
 
     j = 1;
     for (i = 0;i &lt; NUMFIELDS;++i) {
@@ -207,6 +238,15 @@ int main()
 
     switch(line.s[0]) {
 
+      case '%':
+	locparse(&amp;f[0],loc);
+	if (!stralloc_copyb(&amp;key,&quot;\0%&quot;,2)) nomem();
+	if (!stralloc_0(&amp;f[1])) nomem();
+	ipprefix_cat(&amp;key,f[1].s);
+        if (cdb_make_add(&amp;cdb,key.s,key.len,loc,2) == -1)
+          die_datatmp();
+	break;
+
       case 'Z':
 	if (!dns_domain_fromdot(&amp;d1,f[0].s,f[0].len)) nomem();
 
@@ -229,8 +269,9 @@ int main()
 	if (!stralloc_0(&amp;f[8])) nomem();
 	if (!scan_ulong(f[8].s,&amp;ttl)) ttl = TTL_NEGATIVE;
 	ttdparse(&amp;f[9],ttd);
+	locparse(&amp;f[10],loc);
 
-	rr_start(DNS_T_SOA,ttl,ttd);
+	rr_start(DNS_T_SOA,ttl,ttd,loc);
 	if (!dns_domain_fromdot(&amp;d2,f[1].s,f[1].len)) nomem();
 	rr_addname(d2);
 	if (!dns_domain_fromdot(&amp;d2,f[2].s,f[2].len)) nomem();
@@ -244,6 +285,7 @@ int main()
 	if (!stralloc_0(&amp;f[3])) nomem();
 	if (!scan_ulong(f[3].s,&amp;ttl)) ttl = TTL_NS;
 	ttdparse(&amp;f[4],ttd);
+	locparse(&amp;f[5],loc);
 
 	if (!stralloc_0(&amp;f[1])) nomem();
 
@@ -254,7 +296,7 @@ int main()
 	if (!dns_domain_fromdot(&amp;d2,f[2].s,f[2].len)) nomem();
 
 	if (line.s[0] == '.') {
-	  rr_start(DNS_T_SOA,ttl ? TTL_NEGATIVE : 0,ttd);
+	  rr_start(DNS_T_SOA,ttl ? TTL_NEGATIVE : 0,ttd,loc);
 	  rr_addname(d2);
 	  rr_add(&quot;\12hostmaster&quot;,11);
 	  rr_addname(d1);
@@ -262,12 +304,12 @@ int main()
 	  rr_finish(d1);
 	}
 
-	rr_start(DNS_T_NS,ttl,ttd);
+	rr_start(DNS_T_NS,ttl,ttd,loc);
 	rr_addname(d2);
 	rr_finish(d1);
 
 	if (ip4_scan(f[1].s,ip)) {
-	  rr_start(DNS_T_A,ttl,ttd);
+	  rr_start(DNS_T_A,ttl,ttd,loc);
 	  rr_add(ip,4);
 	  rr_finish(d2);
 	}
@@ -279,17 +321,18 @@ int main()
 	if (!stralloc_0(&amp;f[2])) nomem();
 	if (!scan_ulong(f[2].s,&amp;ttl)) ttl = TTL_POSITIVE;
 	ttdparse(&amp;f[3],ttd);
+	locparse(&amp;f[4],loc);
 
 	if (!stralloc_0(&amp;f[1])) nomem();
 
 	if (ip4_scan(f[1].s,ip)) {
-	  rr_start(DNS_T_A,ttl,ttd);
+	  rr_start(DNS_T_A,ttl,ttd,loc);
 	  rr_add(ip,4);
 	  rr_finish(d1);
 
 	  if (line.s[0] == '=') {
 	    dns_name4_domain(dptr,ip);
-	    rr_start(DNS_T_PTR,ttl,ttd);
+	    rr_start(DNS_T_PTR,ttl,ttd,loc);
 	    rr_addname(d1);
 	    rr_finish(dptr);
 	  }
@@ -301,6 +344,7 @@ int main()
 	if (!stralloc_0(&amp;f[4])) nomem();
 	if (!scan_ulong(f[4].s,&amp;ttl)) ttl = TTL_POSITIVE;
 	ttdparse(&amp;f[5],ttd);
+	locparse(&amp;f[6],loc);
 
 	if (!stralloc_0(&amp;f[1])) nomem();
 
@@ -313,14 +357,14 @@ int main()
 	if (!stralloc_0(&amp;f[3])) nomem();
 	if (!scan_ulong(f[3].s,&amp;u)) u = 0;
 
-	rr_start(DNS_T_MX,ttl,ttd);
+	rr_start(DNS_T_MX,ttl,ttd,loc);
 	uint16_pack_big(buf,u);
 	rr_add(buf,2);
 	rr_addname(d2);
 	rr_finish(d1);
 
 	if (ip4_scan(f[1].s,ip)) {
-	  rr_start(DNS_T_A,ttl,ttd);
+	  rr_start(DNS_T_A,ttl,ttd,loc);
 	  rr_add(ip,4);
 	  rr_finish(d2);
 	}
@@ -332,11 +376,12 @@ int main()
 	if (!stralloc_0(&amp;f[2])) nomem();
 	if (!scan_ulong(f[2].s,&amp;ttl)) ttl = TTL_POSITIVE;
 	ttdparse(&amp;f[3],ttd);
+	locparse(&amp;f[4],loc);
 
 	if (line.s[0] == 'C')
-	  rr_start(DNS_T_CNAME,ttl,ttd);
+	  rr_start(DNS_T_CNAME,ttl,ttd,loc);
 	else
-	  rr_start(DNS_T_PTR,ttl,ttd);
+	  rr_start(DNS_T_PTR,ttl,ttd,loc);
 	rr_addname(d2);
 	rr_finish(d1);
 	break;
@@ -346,8 +391,9 @@ int main()
 	if (!stralloc_0(&amp;f[2])) nomem();
 	if (!scan_ulong(f[2].s,&amp;ttl)) ttl = TTL_POSITIVE;
 	ttdparse(&amp;f[3],ttd);
+	locparse(&amp;f[4],loc);
 
-	rr_start(DNS_T_TXT,ttl,ttd);
+	rr_start(DNS_T_TXT,ttl,ttd,loc);
 
 	txtparse(&amp;f[1]);
 	i = 0;
@@ -368,6 +414,7 @@ int main()
 	if (!stralloc_0(&amp;f[3])) nomem();
 	if (!scan_ulong(f[3].s,&amp;ttl)) ttl = TTL_POSITIVE;
 	ttdparse(&amp;f[4],ttd);
+	locparse(&amp;f[5],loc);
 
 	if (!stralloc_0(&amp;f[1])) nomem();
 	scan_ulong(f[1].s,&amp;u);
@@ -389,7 +436,7 @@ int main()
 
 	txtparse(&amp;f[2]);
 
-	rr_start(type,ttl,ttd);
+	rr_start(type,ttl,ttd,loc);
 	rr_add(f[2].s,f[2].len);
 	rr_finish(d1);
 	break;</diff>
      <filename>tinydns-data.c</filename>
    </modified>
    <modified>
      <diff>@@ -10,20 +10,22 @@
 #include &quot;case.h&quot;
 #include &quot;printpacket.h&quot;
 #include &quot;parsetype.h&quot;
+#include &quot;ip4.h&quot;
 #include &quot;dns.h&quot;
 
 #define FATAL &quot;tinydns-get: fatal: &quot;
 
 void usage(void)
 {
-  strerr_die1x(100,&quot;tinydns-get: usage: tinydns-get type name&quot;);
+  strerr_die1x(100,&quot;tinydns-get: usage: tinydns-get type name [ip]&quot;);
 }
 void oops(void)
 {
   strerr_die2sys(111,FATAL,&quot;unable to parse: &quot;);
 }
 
-char type[2];
+static char ip[4];
+static char type[2];
 static char *q;
 
 static stralloc out;
@@ -40,6 +42,10 @@ int main(int argc,char **argv)
   if (!*++argv) usage();
   if (!dns_domain_fromdot(&amp;q,*argv,str_len(*argv))) oops();
 
+  if (*++argv) {
+    if (!ip4_scan(*argv,ip)) usage();
+  }
+
   if (!stralloc_copys(&amp;out,&quot;&quot;)) oops();
   uint16_unpack_big(type,&amp;u16);
   if (!stralloc_catulong0(&amp;out,u16,0)) oops();
@@ -58,7 +64,7 @@ int main(int argc,char **argv)
     response[3] |= 4;
   }
   else
-    if (!respond(q,type,&quot;\0\0\0\0&quot;)) goto DONE;
+    if (!respond(q,type,ip)) goto DONE;
 
   if (!printpacket_cat(&amp;out,response,response_len)) oops();
 </diff>
      <filename>tinydns-get.c</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,10 @@
+#include &quot;dns.h&quot;
+
 const char *fatal = &quot;tinydns: fatal: &quot;;
 
+static char seed[128];
+
 void initialize(void)
 {
-  ;
+  dns_random_init(seed);
 }</diff>
      <filename>tinydns.c</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2ba504ae479a8cb3dc2182d14db4f51f6c738b50</id>
    </parent>
  </parents>
  <author>
    <name>Nick Andrew</name>
    <email>nick@nick-andrew.net</email>
  </author>
  <url>http://github.com/nickandrew/djbdns/commit/bdde5c4d5ef62f5f2186de3e8432d294da14997c</url>
  <id>bdde5c4d5ef62f5f2186de3e8432d294da14997c</id>
  <committed-date>2009-06-07T05:35:42-07:00</committed-date>
  <authored-date>2009-06-07T05:35:42-07:00</authored-date>
  <message>djbdns 1.04</message>
  <tree>3e7bf5a0b0289ac5251c5a14b83113715617000e</tree>
  <committer>
    <name>Nick Andrew</name>
    <email>nick@nick-andrew.net</email>
  </committer>
</commit>
