[OpenWrt-Devel] [PATCH] Update: djbdns 1.05-4 to 1.05-5

Johnny Halfmoon jhalfmoon at milksnot.com
Tue Sep 8 21:53:17 CEST 2009


By request of Florian (https://dev.openwrt.org/ticket/5764) , this patch is hereby being resubmitted.

- - -

This is an update to the djbdns package. This version has been tested on 2 machines for 3 months now and has proven stable. The README contains information about all new and existing patches. Changes:

1.05-5 20090522 jhalfmoon
enhancement - added patch: dnsroots_updated
enhancement - added patch: tinydns_one_second
enhancement - added patch: srv-records-and-axfrget
enhancement - added patch: dnscache_less_chatty_log
enhancement - added patch: tinydns_mmap_leak
enhancement - added patch: dnscache_dpos_tcp_servfail
enhancement - added patch: dnscache_negative_ttls
enhancement - added patch: dnscache_sigpipe_fix
enhancement - added patch: dnscache_big_udp_packets
enhancement - added patch: dnscache_ignoreip2 (Note: disabled in config by default!)
enhancement - added HIDETTL config option
change - Corrected a typo in the axfrdns description in the Makefile.
change - Cleaned up some lines in the Makefile
change - dnsroots.global now gets copied from the djbdns source folder instead of from the package/files folder.
change - The dnscache-multiple-ip patch was removed as it served no purpose
change - Renamed a few patches to be more consistent with the other patches
change - Updated the README file to reflect the changes

Signed-off-by: Johnny Halfmoon <jhalfmoon at milksnot.com>


Index: files/dnscache/servers/@
===================================================================
--- files/dnscache/servers/@	(revision 16393)
+++ files/dnscache/servers/@	(working copy)
@@ -1,13 +0,0 @@
-198.41.0.4 
-192.228.79.201 
-192.33.4.12 
-128.8.10.90 
-192.203.230.10 
-192.5.5.241 
-192.112.36.4 
-128.63.2.53 
-192.36.148.17 
-192.58.128.30 
-193.0.14.129 
-199.7.83.42 
-202.12.27.33 
Index: files/dnscache/dnsroots.global
===================================================================
--- files/dnscache/dnsroots.global	(revision 16393)
+++ files/dnscache/dnsroots.global	(working copy)
@@ -1,13 +0,0 @@
-198.41.0.4 
-192.228.79.201 
-192.33.4.12 
-128.8.10.90 
-192.203.230.10 
-192.5.5.241 
-192.112.36.4 
-128.63.2.53 
-192.36.148.17 
-192.58.128.30 
-193.0.14.129 
-199.7.83.42 
-202.12.27.33 
Index: files/dnscache/ignoreip-update
===================================================================
--- files/dnscache/ignoreip-update	(revision 0)
+++ files/dnscache/ignoreip-update	(revision 0)
@@ -0,0 +1,95 @@
+#!/bin/sh
+# 
+# update-ignoreip version 0.1
+# Written by J.P. Larocque, <piranha at thoughtcrime.us>, OpenPGP 0x0c14cdda
+# This software is in the public domain.
+# 
+# This script is intended for djbdns users that have applied Russell
+# Nelson's patch to circumvent wildcard A records in TLDs:
+#
+#     http://tinydns.org/djbdns-1.05-ignoreip2.patch
+#
+# This script will try the wildcard name for each TLD in the
+# 'stupid_tlds' variable (eg, '*.com', '*.cx', etc.).  For those
+# addresses that resolve, they get added to your dnscache
+# 'root/ignoreip' file, and dnscache is restarted.
+# 
+# Run this script from your dnscache directory.  This script depends
+# on a proper PATH.  Old 'root/ignoreips' entries are kept (and dups
+# removed), so you can add this program to a cron job to keep ahead
+# of new bogus redirection addresses added by Verisign and other TLD
+# operators.
+# 
+# Adding this script to a cron job was its intended purpose, but
+# please don't do so without understanding how it works and what could
+# happen if it breaks.
+# 
+# The latest version of this program can be found at the URL:
+#       http://ely.ath.cx/~piranha/software/ignoreip-update/
+# This program has been signed with my public key.  Its fingerprint is:
+#       810B A0AC A7F7 2899 46D2  F2F6 3E7D 5279 0C14 CDDA
+# The detached signature can be found at the URL:
+#       http://ely.ath.cx/~piranha/software/ignoreip-update/ignoreip-update-0.1.asc
+# 
+# Changelog:
+#   version 0.1 (2003/Sep/17)
+#       Initially written and released.
+
+stupid_tlds='ac cc com cx museum net nu ph sh tm ws'
+ignoreip='root/ignoreip'
+
+set -e
+
+me="`basename "$0"`"
+
+if [ ! -d 'root' ]; then
+	echo "$me: run me from the dnscache directory" >&2
+	exit 1
+fi
+
+# I originally implemented this with random names, then realized all
+# the current $stupid_tlds answer to "*.$stupid_tld" just like any
+# other random name.  This code may be useful in the future, if an
+# arms race of sorts develops.  (Sigh.)
+
+if which md5sum > /dev/null 2>&1; then
+	hash_prog=md5sum
+elif which md5 > /dev/null 2>&1; then
+	hash_prog=md5
+else    
+	echo "$me: can't find a suitable hash program" >&2
+	exit 1
+fi
+
+[ "$1" = '-v' ] && verbose=1 || verbose=''
+
+temp1="`mktemp "ignoreip-update-$$-1-XXXXXX"`"
+temp2="`mktemp "ignoreip-update-$$-2-XXXXXX"`"
+trap 'rm -f "$temp1" "$temp2"' EXIT
+
+## Generate random name
+#rand="`dd if=/dev/urandom bs=16 count=1 2> /dev/null | "$hash_prog"`"
+
+# Do lookups on random addresses; break into one addres/line; remove
+# empty lines
+for stupid_tld in $stupid_tlds; do
+	dnsip "$rand.$stupid_tld"
+	#dnsip "*.$stupid_tld"
+done | xargs -n 1 echo | grep '.' > "$temp1"
+
+# Abort if there were no new bogus addresses
+[ ! -s "$temp1" ] && exit
+
+# Remove duplicates (from old list and, eg, .sh/.tm)
+touch "$ignoreip"
+sort "$ignoreip" "$temp1" | uniq > "$temp2"
+
+if [ "$verbose" ]; then
+	diff -u "$ignoreip" "$temp2" || true
+fi
+
+# Update list and restart dnscache
+chmod 644 "$temp2"
+mv "$temp2" "$ignoreip"
+#svc -t .
+

Property changes on: files/dnscache/ignoreip-update
___________________________________________________________________
Added: svn:executable
   + *

Index: files/djbdns.conf
===================================================================
--- files/djbdns.conf	(revision 16393)
+++ files/djbdns.conf	(working copy)
@@ -8,10 +8,17 @@
 	option 'interfacesend' 'wan'
 	option 'defaultallowif' 'lan wan'
 	option 'cachesize' '1000000'
+	option 'hidettl' '0'
 	option 'forwardonly' '1'
 	option 'useresolvconf' '1'
 	list 'resolver' '208.67.222.222'
 	list 'resolver' '208.67.220.220'
+	option 'useignore' '0'
+	list 'ignoreip' '203.119.4.28'
+	list 'ignoreip' '212.181.91.6'
+	list 'ignoreip' '62.4.64.119'
+	list 'ignoreip' '64.70.19.33'
+	list 'ignoreip' '69.25.75.72'
 	option 'logging' '0'
 
 config 'tinydns'
Index: files/dnscache.init
===================================================================
--- files/dnscache.init	(revision 16393)
+++ files/dnscache.init	(working copy)
@@ -16,9 +16,9 @@
     config_load djbdns
     config_foreach get_userids global
     mkdir -p $ROOT
-    cp -fa /etc/dnscache/ip $ROOT
-    cp -fa /etc/dnscache/servers $ROOT
+    cp -fa /etc/dnscache/* $ROOT
     rm -f $ROOT/resolvers
+    rm -f $ROOT/ignoreip
     chown -R $UID:$GID $ROOT
     config_foreach start_dnscache dnscache
 }
@@ -35,16 +35,25 @@
     echo $1 >> $ROOT/resolvers
 }
 
+append_ignore() {
+    echo $1 >> $ROOT/ignoreip
+}
+
 start_dnscache() {
     local cfg="$1"
     config_get logging        "$cfg" logging
     config_get useresolvconf  "$cfg" useresolvconf
-    config_get ifaces         "$cfg" interface
+    config_get iface          "$cfg" interface
     config_get ifacesend      "$cfg" interfacesend
     config_get defaultallowif "$cfg" defaultallowif
     config_get CACHESIZE      "$cfg" cachesize
     config_get FORWARDONLY    "$cfg" forwardonly
+    config_get HIDETTL        "$cfg" hidettl
     config_list_foreach       "$cfg" "resolver" append_server
+    config_get useignore      "$cfg" useignore
+    if [ "$useignore" == "1" ] ; then
+        config_list_foreach   "$cfg" "ignoreip" append_ignore
+    fi
 # Add some interface network addresses to list of allowed IP addresses (assumes /24 networks)
     include /lib/network
     scan_interfaces
@@ -58,15 +67,13 @@
         done
     fi
 # Translate listen interface names to IP addresses
-    IP=""
-    for iface in $ifaces; do
-       config_get ipaddr "$iface" ipaddr
-       IP="$ipaddr/$IP"
-    done
-# Strip trailing slashes
-    IP=`echo $IP|sed 's/\/\+$//g'`
+    config_get IP "$iface" ipaddr
 # Translante send interface name to an IP address
     config_get IPSEND "$ifacesend" ipaddr
+# Unset HIDETTL if equal to 0
+    if [ "$HIDETTL" == "0" ] ; then
+        export -n HIDETTL
+    fi
 # If forwardingonly set then activate list of resolvers
     if [ "$FORWARDONLY" == "0" ] ; then
         # Unset FORWARDONLY if equal to '0'
@@ -90,7 +97,7 @@
      fi
     export IP 
     export ROOT
-# dnscache likes to receive a 128bit random seed
+# dnscache likes to receive a 128 byte random seed
     dd if=/dev/urandom of=$ROOT/randomseed bs=128 count=1  > /dev/null 2>&1
     if [ "$DEBUG" == 1 ] ; then
         $DAEMON < /$ROOT/randomseed
Index: patches/250-dnscache-slogging.patch
===================================================================
--- patches/250-dnscache-slogging.patch	(revision 0)
+++ patches/250-dnscache-slogging.patch	(revision 0)
@@ -0,0 +1,122 @@
+--- /home/uwe/djbdns-1.05/server.c	Sun Feb 11 21:11:45 2001
++++ ./server.c	Fri May  4 07:40:54 2001
+@@ -25,12 +25,63 @@
+ 
+ static char *q;
+ 
++static uint64 stats_numq;
++static uint64 stats_plus;
++static uint64 stats_minus;
++static uint64 stats_nx;
++static uint64 stats_notimp;
++static uint64 stats_weird;
++static uint64 stats_noq;
++
++/* work around gcc 2.95.2 bug */
++#define number(x) ( (u64 = (x)), u64_print() )
++static uint64 u64;
++static void u64_print(void)
++{
++  char ubuf[20];
++  unsigned int pos;
++
++  pos = sizeof ubuf;
++  do {
++    if (!pos) break;
++    ubuf[--pos] = '0' + (u64 % 10);
++    u64 /= 10;
++  } while(u64);
++
++  buffer_put(buffer_2,ubuf + pos,sizeof ubuf - pos);
++}
++
++static void string(const char *s)
++{
++  buffer_puts(buffer_2,s);
++}
++
++static void line(void)
++{
++  string("\n");
++  buffer_flush(buffer_2);
++}
++
++static void log_stats(void)
++{
++  string("stats ");
++  number(stats_numq); string(" ");
++  number(stats_plus); string(" ");
++  number(stats_minus); string(" ");
++  number(stats_nx); string(" ");
++  number(stats_notimp); string(" ");
++  number(stats_weird); string(" ");
++  number(stats_noq);
++  line();
++}
++
+ static int doit(void)
+ {
+   unsigned int pos;
+   char header[12];
+   char qtype[2];
+   char qclass[2];
++  stats_numq++;
+ 
+   if (len >= sizeof buf) goto NOQ;
+   pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ;
+@@ -56,25 +105,37 @@
+ 
+   case_lowerb(q,dns_domain_length(q));
+   if (!respond(q,qtype,ip)) {
++    stats_minus++;
+     qlog(ip,port,header,q,qtype," - ");
+     return 0;
+   }
+-  qlog(ip,port,header,q,qtype," + ");
++
++  if ((response[2] & 4) && (response[3] & 3)) {
++    stats_nx++;
++    qlog(ip,port,header,q,qtype," N ");
++  }
++  else {
++    stats_plus++;
++    qlog(ip,port,header,q,qtype," + ");
++  }
+   return 1;
+ 
+   NOTIMP:
++  stats_notimp++;
+   response[3] &= ~15;
+   response[3] |= 4;
+   qlog(ip,port,header,q,qtype," I ");
+   return 1;
+ 
+   WEIRDCLASS:
++  stats_weird++;
+   response[3] &= ~15;
+   response[3] |= 1;
+   qlog(ip,port,header,q,qtype," C ");
+   return 1;
+ 
+   NOQ:
++  stats_noq++;
+   qlog(ip,port,"\0\0","","\0\0"," / ");
+   return 0;
+ }
+@@ -83,6 +137,7 @@
+ {
+   char *x;
+   int udp53;
++  unsigned char flag=0;
+ 
+   x = env_get("IP");
+   if (!x)
+@@ -106,6 +161,8 @@
+   buffer_putsflush(buffer_2,starting);
+ 
+   for (;;) {
++    if ((flag++)%32==1)
++      log_stats();
+     len = socket_recv4(udp53,buf,sizeof buf,ip,&port);
+     if (len < 0) continue;
+     if (!doit()) continue;
Index: patches/090-tinydns-one-second.patch
===================================================================
--- patches/090-tinydns-one-second.patch	(revision 0)
+++ patches/090-tinydns-one-second.patch	(revision 0)
@@ -0,0 +1,42 @@
+diff -urN djbdns-1.05.orig/tdlookup.c djbdns-1.05/tdlookup.c
+--- djbdns-1.05.orig/tdlookup.c	2001-02-11 22:11:45.000000000 +0100
++++ djbdns-1.05/tdlookup.c	2004-04-18 13:56:13.000000000 +0200
+@@ -280,15 +280,24 @@
+ 
+ int respond(char *q,char qtype[2],char ip[4])
+ {
+-  int fd;
++  static struct tai cdb_valid = { 0 };
++  static int fd = -1;
++  struct tai one_second;
+   int r;
+   char key[6];
+ 
+   tai_now(&now);
+-  fd = open_read("data.cdb");
+-  if (fd == -1) return 0;
+-  cdb_init(&c,fd);
+-
++  if (tai_less(&cdb_valid, &now)) {
++    if (fd != -1) {
++      cdb_free(&c);
++      close(fd);
++    }
++    fd = open_read("data.cdb");
++    if (fd == -1) return 0;
++    cdb_init(&c,fd);
++    tai_uint(&one_second, 1);
++    tai_add(&cdb_valid, &now, &one_second);
++  }
+   byte_zero(clientloc,2);
+   key[0] = 0;
+   key[1] = '%';
+@@ -304,7 +313,5 @@
+ 
+   r = doit(q,qtype);
+ 
+-  cdb_free(&c);
+-  close(fd);
+   return r;
+ }
+
Index: patches/110-dnscache-cachestats.patch
===================================================================
--- patches/110-dnscache-cachestats.patch	(revision 0)
+++ patches/110-dnscache-cachestats.patch	(revision 0)
@@ -0,0 +1,89 @@
+#
+# This patch to djbdns 1.05 modifies the dnscache program to keep a
+# counter of cache hits and cache misses.
+#
+# Two new fields are added to the ``stats'' output line:
+#  . the fifth number is the number of cache hits
+#  . the sixth number is the number of cache misses
+# e.g.
+#  @400000003fa92ccc317d70f4 stats 3 1201 1 0 21 49
+# indicates 21 hits and 49 misses.
+#
+# James Raftery <james at now.ie>  6 Nov. 2003
+#
+--- djbdns-1.05.orig/cache.c	Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/cache.c	Wed Nov  5 17:21:06 2003
+@@ -7,6 +7,11 @@
+ 
+ uint64 cache_motion = 0;
+ 
++/* record cache stats */
++/* James Raftery <james at now.ie> 6 Nov. 2003 */
++uint64 cache_hit = 0;
++uint64 cache_miss = 0;
++
+ static char *x = 0;
+ static uint32 size;
+ static uint32 hsize;
+@@ -112,15 +117,20 @@
+         if (u > size - pos - 20 - keylen) cache_impossible();
+         *datalen = u;
+ 
++        cache_hit++;
+         return x + pos + 20 + keylen;
+       }
+     }
+     nextpos = prevpos ^ get4(pos);
+     prevpos = pos;
+     pos = nextpos;
+-    if (++loop > 100) return 0; /* to protect against hash flooding */
++    if (++loop > 100) { /* to protect against hash flooding */
++      cache_miss++;
++      return 0;
++    }
+   }
+ 
++  cache_miss++;
+   return 0;
+ }
+ 
+--- djbdns-1.05.orig/cache.h	Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/cache.h	Wed Nov  5 17:13:36 2003
+@@ -5,6 +5,12 @@
+ #include "uint64.h"
+ 
+ extern uint64 cache_motion;
++
++/* record cache stats */
++/* James Raftery <james at now.ie> 6 Nov. 2003 */
++extern uint64 cache_hit;
++extern uint64 cache_miss;
++
+ extern int cache_init(unsigned int);
+ extern void cache_set(const char *,unsigned int,const char *,unsigned int,uint32);
+ extern char *cache_get(const char *,unsigned int,unsigned int *,uint32 *);
+--- djbdns-1.05.orig/log.c	Sun Feb 11 21:11:45 2001
++++ djbdns-1.05/log.c	Wed Nov  5 17:21:12 2003
+@@ -276,6 +276,12 @@
+ {
+   extern uint64 numqueries;
+   extern uint64 cache_motion;
++
++  /* record cache stats */
++  /* James Raftery <james at now.ie> 6 Nov. 2003 */
++  extern uint64 cache_hit;
++  extern uint64 cache_miss;
++
+   extern int uactive;
+   extern int tactive;
+ 
+@@ -283,6 +289,8 @@
+   number(numqueries); space();
+   number(cache_motion); space();
+   number(uactive); space();
+-  number(tactive);
++  number(tactive); space();
++  number(cache_hit); space();
++  number(cache_miss);
+   line();
+ }
Index: patches/320-bugfix3-cache-soa-records.patch
===================================================================
--- patches/320-bugfix3-cache-soa-records.patch	(revision 16393)
+++ patches/320-bugfix3-cache-soa-records.patch	(working copy)
@@ -1,70 +0,0 @@
-diff --git a/query.c b/query.c
-index 46cdc00..4574e97 100644
---- a/query.c
-+++ b/query.c
-@@ -319,6 +319,29 @@ static int doit(struct query *z,int state)
-       }
-     }
- 
-+    if (typematch(DNS_T_SOA,dtype)) {
-+      byte_copy(key,2,DNS_T_SOA);
-+      cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
-+      if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
-+        log_cachedanswer(d,DNS_T_SOA);
-+        if (!rqa(z)) goto DIE;
-+        pos = 0;
-+        while (pos = dns_packet_copy(cached,cachedlen,pos,misc,20)) {
-+          pos = dns_packet_getname(cached,cachedlen,pos,&t2);
-+          if (!pos) break;
-+          pos = dns_packet_getname(cached,cachedlen,pos,&t3);
-+          if (!pos) break;
-+          if (!response_rstart(d,DNS_T_SOA,ttl)) goto DIE;
-+          if (!response_addname(t2)) goto DIE;
-+          if (!response_addname(t3)) goto DIE;
-+          if (!response_addbytes(misc,20)) goto DIE;
-+          response_rfinish(RESPONSE_ANSWER);
-+        }
-+        cleanup(z);
-+        return 1;
-+      }
-+    }
-+
-     if (typematch(DNS_T_A,dtype)) {
-       byte_copy(key,2,DNS_T_A);
-       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
-@@ -351,7 +374,7 @@ static int doit(struct query *z,int state)
-       }
-     }
- 
--    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
-+    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_SOA,dtype)) {
-       byte_copy(key,2,dtype);
-       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
-       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
-@@ -585,15 +608,24 @@ static int doit(struct query *z,int state)
-     else if (byte_equal(type,2,DNS_T_AXFR))
-       ;
-     else if (byte_equal(type,2,DNS_T_SOA)) {
-+      int non_authority = 0;
-+      save_start();
-       while (i < j) {
-         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
-         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
-         pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE;
-         pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE;
--        if (records[i] < posauthority)
-+        if (records[i] < posauthority) {
-           log_rrsoa(whichserver,t1,t2,t3,misc,ttl);
-+          save_data(misc,20);
-+          save_data(t2,dns_domain_length(t2));
-+          save_data(t3,dns_domain_length(t3));
-+          non_authority++;
-+        }
-         ++i;
-       }
-+      if (non_authority)
-+        save_finish(DNS_T_SOA,t1,ttl);
-     }
-     else if (byte_equal(type,2,DNS_T_CNAME)) {
-       pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE;
-
Index: patches/310-bugfix-dnscache-merge-outgoing-requests.patch
===================================================================
--- patches/310-bugfix-dnscache-merge-outgoing-requests.patch	(revision 0)
+++ patches/310-bugfix-dnscache-merge-outgoing-requests.patch	(revision 0)
@@ -0,0 +1,349 @@
+diff --git a/Makefile b/Makefile
+index 1429643..bc047c0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -318,11 +318,11 @@ stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+ 	./compile dns_txt.c
+ 
+ dnscache: \
+-load dnscache.o droproot.o okclient.o log.o cache.o query.o \
++load dnscache.o droproot.o okclient.o log.o cache.o query.o qmerge.o \
+ response.o dd.o roots.o iopause.o prot.o dns.a env.a alloc.a buffer.a \
+ libtai.a unix.a byte.a socket.lib
+ 	./load dnscache droproot.o okclient.o log.o cache.o \
+-	query.o response.o dd.o roots.o iopause.o prot.o dns.a \
++	query.o qmerge.o response.o dd.o roots.o iopause.o prot.o dns.a \
+ 	env.a alloc.a buffer.a libtai.a unix.a byte.a  `cat \
+ 	socket.lib`
+ 
+@@ -343,7 +343,7 @@ compile dnscache.c env.h exit.h scan.h strerr.h error.h ip4.h \
+ uint16.h uint64.h socket.h uint16.h dns.h stralloc.h gen_alloc.h \
+ iopause.h taia.h tai.h uint64.h taia.h taia.h byte.h roots.h fmt.h \
+ iopause.h query.h dns.h uint32.h alloc.h response.h uint32.h cache.h \
+-uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h
++uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h maxclient.h
+ 	./compile dnscache.c
+ 
+ dnsfilter: \
+@@ -687,11 +687,16 @@ qlog.o: \
+ compile qlog.c buffer.h qlog.h uint16.h
+ 	./compile qlog.c
+ 
++qmerge.o: \
++compile qmerge.c qmerge.h dns.h stralloc.h gen_alloc.h iopause.h \
++taia.h tai.h uint64.h log.h maxclient.h
++	./compile qmerge.c
++
+ query.o: \
+ compile query.c error.h roots.h log.h uint64.h case.h cache.h \
+ uint32.h uint64.h byte.h dns.h stralloc.h gen_alloc.h iopause.h \
+ taia.h tai.h uint64.h taia.h uint64.h uint32.h uint16.h dd.h alloc.h \
+-response.h uint32.h query.h dns.h uint32.h
++response.h uint32.h query.h dns.h uint32.h qmerge.h
+ 	./compile query.c
+ 
+ random-ip: \
+diff --git a/dnscache.c b/dnscache.c
+index 8c899a3..5ccb16a 100644
+--- a/dnscache.c
++++ b/dnscache.c
+@@ -19,6 +19,7 @@
+ #include "response.h"
+ #include "cache.h"
+ #include "ndelay.h"
++#include "maxclient.h"
+ #include "log.h"
+ #include "okclient.h"
+ #include "droproot.h"
+@@ -54,7 +55,6 @@ uint64 numqueries = 0;
+ 
+ static int udp53;
+ 
+-#define MAXUDP 200
+ static struct udpclient {
+   struct query q;
+   struct taia start;
+@@ -131,7 +131,6 @@ void u_new(void)
+ 
+ static int tcp53;
+ 
+-#define MAXTCP 20
+ struct tcpclient {
+   struct query q;
+   struct taia start;
+diff --git a/log.c b/log.c
+index c43e8b0..b8cd7ce 100644
+--- a/log.c
++++ b/log.c
+@@ -150,6 +150,13 @@ void log_tx(const char *q,const char qtype[2],const char *control,const char ser
+   line();
+ }
+ 
++void log_tx_piggyback(const char *q, const char qtype[2], const char *control)
++{
++  string("txpb ");
++  logtype(qtype); space(); name(q); space(); name(control);
++  line();
++}
++
+ void log_cachedanswer(const char *q,const char type[2])
+ {
+   string("cached "); logtype(type); space();
+diff --git a/log.h b/log.h
+index fe62fa3..d9a829b 100644
+--- a/log.h
++++ b/log.h
+@@ -18,6 +18,7 @@ extern void log_cachednxdomain(const char *);
+ extern void log_cachedns(const char *,const char *);
+ 
+ extern void log_tx(const char *,const char *,const char *,const char *,unsigned int);
++extern void log_tx_piggyback(const char *,const char *,const char *);
+ 
+ extern void log_nxdomain(const char *,const char *,unsigned int);
+ extern void log_nodata(const char *,const char *,const char *,unsigned int);
+diff --git a/maxclient.h b/maxclient.h
+new file mode 100644
+index 0000000..e52fcd1
+--- /dev/null
++++ b/maxclient.h
+@@ -0,0 +1,7 @@
++#ifndef MAXCLIENT_H
++#define MAXCLIENT_H
++
++#define MAXUDP 200
++#define MAXTCP 20
++
++#endif /* MAXCLIENT_H */
+diff --git a/qmerge.c b/qmerge.c
+new file mode 100644
+index 0000000..7c92299
+--- /dev/null
++++ b/qmerge.c
+@@ -0,0 +1,115 @@
++#include "qmerge.h"
++#include "byte.h"
++#include "log.h"
++#include "maxclient.h"
++
++#define QMERGE_MAX (MAXUDP+MAXTCP)
++struct qmerge inprogress[QMERGE_MAX];
++
++static
++int qmerge_key_init(struct qmerge_key *qmk, const char *q, const char qtype[2],
++    const char *control)
++{
++  if (!dns_domain_copy(&qmk->q, q)) return 0;
++  byte_copy(qmk->qtype, 2, qtype);
++  if (!dns_domain_copy(&qmk->control, control)) return 0;
++  return 1;
++}
++
++static
++int qmerge_key_equal(struct qmerge_key *a, struct qmerge_key *b)
++{
++  return
++    byte_equal(a->qtype, 2, b->qtype) &&
++    dns_domain_equal(a->q, b->q) &&
++    dns_domain_equal(a->control, b->control);
++}
++
++static
++void qmerge_key_free(struct qmerge_key *qmk)
++{
++  dns_domain_free(&qmk->q);
++  dns_domain_free(&qmk->control);
++}
++
++void qmerge_free(struct qmerge **x)
++{
++  struct qmerge *qm;
++
++  qm = *x;
++  *x = 0;
++  if (!qm || !qm->active) return;
++
++  qm->active--;
++  if (!qm->active) {
++    qmerge_key_free(&qm->key);
++    dns_transmit_free(&qm->dt);
++  }
++}
++
++int qmerge_start(struct qmerge **qm, const char servers[64], int flagrecursive,
++    const char *q, const char qtype[2], const char localip[4],
++    const char *control)
++{
++  struct qmerge_key k;
++  int i;
++  int r;
++
++  qmerge_free(qm);
++
++  byte_zero(&k, sizeof k);
++  if (!qmerge_key_init(&k, q, qtype, control)) return -1;
++  for (i = 0; i < QMERGE_MAX; i++) {
++    if (!inprogress[i].active) continue;
++    if (!qmerge_key_equal(&k, &inprogress[i].key)) continue;
++    log_tx_piggyback(q, qtype, control);
++    inprogress[i].active++;
++    *qm = &inprogress[i];
++    qmerge_key_free(&k);
++    return 0;
++  }
++
++  for (i = 0; i < QMERGE_MAX; i++)
++    if (!inprogress[i].active)
++      break;
++  if (i == QMERGE_MAX) return -1;
++
++  log_tx(q, qtype, control, servers, 0);
++  r = dns_transmit_start(&inprogress[i].dt, servers, flagrecursive, q, qtype, localip);
++  if (r == -1) { qmerge_key_free(&k); return -1; }
++  inprogress[i].active++;
++  inprogress[i].state = 0;
++  qmerge_key_free(&inprogress[i].key);
++  byte_copy(&inprogress[i].key, sizeof k, &k);
++  *qm = &inprogress[i];
++  return 0;
++}
++
++void qmerge_io(struct qmerge *qm, iopause_fd *io, struct taia *deadline)
++{
++  if (qm->state == 0) {
++    dns_transmit_io(&qm->dt, io, deadline);
++    qm->state = 1;
++  }
++  else {
++    io->fd = -1;
++    io->events = 0;
++  }
++}
++
++int qmerge_get(struct qmerge **x, const iopause_fd *io, const struct taia *when)
++{
++  int r;
++  struct qmerge *qm;
++
++  qm = *x;
++  if (qm->state == -1) return -1; /* previous error */
++  if (qm->state == 0) return 0; /* no packet */
++  if (qm->state == 2) return 1; /* already got packet */
++
++  r = dns_transmit_get(&qm->dt, io, when);
++  if (r == -1) { qm->state = -1; return -1; } /* error */
++  if (r == 0) { qm->state = 0; return 0; } /* must wait for i/o */
++  if (r == 1) { qm->state = 2; return 1; } /* got packet */
++  return -1; /* bug */
++}
+diff --git a/qmerge.h b/qmerge.h
+new file mode 100644
+index 0000000..9a58157
+--- /dev/null
++++ b/qmerge.h
+@@ -0,0 +1,24 @@
++#ifndef QMERGE_H
++#define QMERGE_H
++
++#include "dns.h"
++
++struct qmerge_key {
++  char *q;
++  char qtype[2];
++  char *control;
++};
++
++struct qmerge {
++  int active;
++  struct qmerge_key key;
++  struct dns_transmit dt;
++  int state; /* -1 = error, 0 = need io, 1 = need get, 2 = got packet */
++};
++
++extern int qmerge_start(struct qmerge **,const char *,int,const char *,const char *,const char *,const char *);
++extern void qmerge_io(struct qmerge *,iopause_fd *,struct taia *);
++extern int qmerge_get(struct qmerge **,const iopause_fd *,const struct taia *);
++extern void qmerge_free(struct qmerge **);
++
++#endif /* QMERGE_H */
+diff --git a/query.c b/query.c
+index 46cdc00..f091fdd 100644
+--- a/query.c
++++ b/query.c
+@@ -81,7 +81,7 @@ static void cleanup(struct query *z)
+   int j;
+   int k;
+ 
+-  dns_transmit_free(&z->dt);
++  qmerge_free(&z->qm);
+   for (j = 0;j < QUERY_MAXALIAS;++j)
+     dns_domain_free(&z->alias[j]);
+   for (j = 0;j < QUERY_MAXLEVEL;++j) {
+@@ -429,14 +429,8 @@ static int doit(struct query *z,int state)
+   if (j == 64) goto SERVFAIL;
+ 
+   dns_sortip(z->servers[z->level],64);
+-  if (z->level) {
+-    log_tx(z->name[z->level],DNS_T_A,z->control[z->level],z->servers[z->level],z->level);
+-    if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],DNS_T_A,z->localip) == -1) goto DIE;
+-  }
+-  else {
+-    log_tx(z->name[0],z->type,z->control[0],z->servers[0],0);
+-    if (dns_transmit_start(&z->dt,z->servers[0],flagforwardonly,z->name[0],z->type,z->localip) == -1) goto DIE;
+-  }
++  dtype = z->level ? DNS_T_A : z->type;
++  if (qmerge_start(&z->qm,z->servers[z->level],flagforwardonly,z->name[z->level],dtype,z->localip,z->control[z->level]) == -1) goto DIE;
+   return 0;
+ 
+ 
+@@ -450,10 +444,10 @@ static int doit(struct query *z,int state)
+ 
+   HAVEPACKET:
+   if (++z->loop == 100) goto DIE;
+-  buf = z->dt.packet;
+-  len = z->dt.packetlen;
++  buf = z->qm->dt.packet;
++  len = z->qm->dt.packetlen;
+ 
+-  whichserver = z->dt.servers + 4 * z->dt.curserver;
++  whichserver = z->qm->dt.servers + 4 * z->qm->dt.curserver;
+   control = z->control[z->level];
+   d = z->name[z->level];
+   dtype = z->level ? DNS_T_A : z->type;
+@@ -836,7 +830,7 @@ int query_start(struct query *z,char *dn,char type[2],char class[2],char localip
+ 
+ int query_get(struct query *z,iopause_fd *x,struct taia *stamp)
+ {
+-  switch(dns_transmit_get(&z->dt,x,stamp)) {
++  switch(qmerge_get(&z->qm,x,stamp)) {
+     case 1:
+       return doit(z,1);
+     case -1:
+@@ -847,5 +841,5 @@ int query_get(struct query *z,iopause_fd *x,struct taia *stamp)
+ 
+ void query_io(struct query *z,iopause_fd *x,struct taia *deadline)
+ {
+-  dns_transmit_io(&z->dt,x,deadline);
++  qmerge_io(z->qm,x,deadline);
+ }
+diff --git a/query.h b/query.h
+index eff68b2..06feab4 100644
+--- a/query.h
++++ b/query.h
+@@ -1,7 +1,7 @@
+ #ifndef QUERY_H
+ #define QUERY_H
+ 
+-#include "dns.h"
++#include "qmerge.h"
+ #include "uint32.h"
+ 
+ #define QUERY_MAXLEVEL 5
+@@ -20,7 +20,7 @@ struct query {
+   char localip[4];
+   char type[2];
+   char class[2];
+-  struct dns_transmit dt;
++  struct qmerge *qm;
+ } ;
+ 
+ extern int query_start(struct query *,char *,char *,char *,char *);
Index: patches/050-tinydns-mmap-leak.patch
===================================================================
--- patches/050-tinydns-mmap-leak.patch	(revision 0)
+++ patches/050-tinydns-mmap-leak.patch	(revision 0)
@@ -0,0 +1,23 @@
+diff -u djbdns-1.05/tdlookup.c djbdns-1.05-p/tdlookup.c
+--- djbdns-1.05/tdlookup.c      2001-02-11 16:11:45.000000000 -0500
++++ djbdns-1.05-p/tdlookup.c    2006-11-16 12:00:09.000000000 -0500
+@@ -298,9 +298,17 @@
+   if (!r) r = cdb_find(&c,key,4);
+   if (!r) r = cdb_find(&c,key,3);
+   if (!r) r = cdb_find(&c,key,2);
+-  if (r == -1) return 0;
++  if (r == -1) {
++    cdb_free(&c);
++    close(fd);
++    return 0;
++  }
+   if (r && (cdb_datalen(&c) == 2))
+-    if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) return 0;
++    if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) {
++      cdb_free(&c);
++      close(fd);
++      return 0;
++    }
+
+   r = doit(q,qtype);
+
Index: patches/270-dnscache-sigpipe-fix.patch
===================================================================
--- patches/270-dnscache-sigpipe-fix.patch	(revision 0)
+++ patches/270-dnscache-sigpipe-fix.patch	(revision 0)
@@ -0,0 +1,21 @@
+*** old/dnscache.c     Sun Feb 11 13:11:45 2001
+--- new/dnscache.c  Tue Mar 18 17:22:03 2003
+***************
+*** 1,4 ****
+--- 1,5 ----
+  #include <unistd.h>
++ #include <signal.h>
+  #include "env.h"
+  #include "exit.h"
+  #include "scan.h"
+***************
+*** 391,396 ****
+--- 392,398 ----
+    char *x;
+    unsigned long cachesize;
+  
++   signal(SIGPIPE, SIG_IGN);
+    x = env_get("IP");
+    if (!x)
+      strerr_die2x(111,FATAL,"$IP not set");
+
Index: patches/250-djbdns-1.05-slogging.patch
===================================================================
--- patches/250-djbdns-1.05-slogging.patch	(revision 16393)
+++ patches/250-djbdns-1.05-slogging.patch	(working copy)
@@ -1,122 +0,0 @@
---- /home/uwe/djbdns-1.05/server.c	Sun Feb 11 21:11:45 2001
-+++ ./server.c	Fri May  4 07:40:54 2001
-@@ -25,12 +25,63 @@
- 
- static char *q;
- 
-+static uint64 stats_numq;
-+static uint64 stats_plus;
-+static uint64 stats_minus;
-+static uint64 stats_nx;
-+static uint64 stats_notimp;
-+static uint64 stats_weird;
-+static uint64 stats_noq;
-+
-+/* work around gcc 2.95.2 bug */
-+#define number(x) ( (u64 = (x)), u64_print() )
-+static uint64 u64;
-+static void u64_print(void)
-+{
-+  char ubuf[20];
-+  unsigned int pos;
-+
-+  pos = sizeof ubuf;
-+  do {
-+    if (!pos) break;
-+    ubuf[--pos] = '0' + (u64 % 10);
-+    u64 /= 10;
-+  } while(u64);
-+
-+  buffer_put(buffer_2,ubuf + pos,sizeof ubuf - pos);
-+}
-+
-+static void string(const char *s)
-+{
-+  buffer_puts(buffer_2,s);
-+}
-+
-+static void line(void)
-+{
-+  string("\n");
-+  buffer_flush(buffer_2);
-+}
-+
-+static void log_stats(void)
-+{
-+  string("stats ");
-+  number(stats_numq); string(" ");
-+  number(stats_plus); string(" ");
-+  number(stats_minus); string(" ");
-+  number(stats_nx); string(" ");
-+  number(stats_notimp); string(" ");
-+  number(stats_weird); string(" ");
-+  number(stats_noq);
-+  line();
-+}
-+
- static int doit(void)
- {
-   unsigned int pos;
-   char header[12];
-   char qtype[2];
-   char qclass[2];
-+  stats_numq++;
- 
-   if (len >= sizeof buf) goto NOQ;
-   pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto NOQ;
-@@ -56,25 +105,37 @@
- 
-   case_lowerb(q,dns_domain_length(q));
-   if (!respond(q,qtype,ip)) {
-+    stats_minus++;
-     qlog(ip,port,header,q,qtype," - ");
-     return 0;
-   }
--  qlog(ip,port,header,q,qtype," + ");
-+
-+  if ((response[2] & 4) && (response[3] & 3)) {
-+    stats_nx++;
-+    qlog(ip,port,header,q,qtype," N ");
-+  }
-+  else {
-+    stats_plus++;
-+    qlog(ip,port,header,q,qtype," + ");
-+  }
-   return 1;
- 
-   NOTIMP:
-+  stats_notimp++;
-   response[3] &= ~15;
-   response[3] |= 4;
-   qlog(ip,port,header,q,qtype," I ");
-   return 1;
- 
-   WEIRDCLASS:
-+  stats_weird++;
-   response[3] &= ~15;
-   response[3] |= 1;
-   qlog(ip,port,header,q,qtype," C ");
-   return 1;
- 
-   NOQ:
-+  stats_noq++;
-   qlog(ip,port,"\0\0","","\0\0"," / ");
-   return 0;
- }
-@@ -83,6 +137,7 @@
- {
-   char *x;
-   int udp53;
-+  unsigned char flag=0;
- 
-   x = env_get("IP");
-   if (!x)
-@@ -106,6 +161,8 @@
-   buffer_putsflush(buffer_2,starting);
- 
-   for (;;) {
-+    if ((flag++)%32==1)
-+      log_stats();
-     len = socket_recv4(udp53,buf,sizeof buf,ip,&port);
-     if (len < 0) continue;
-     if (!doit()) continue;
Index: patches/010-crosscompile.patch
===================================================================
--- patches/010-crosscompile.patch	(revision 0)
+++ patches/010-crosscompile.patch	(revision 0)
@@ -0,0 +1,171 @@
+diff -urN djbdns-1.05/Makefile djbdns-1.05.new/Makefile
+--- djbdns-1.05/Makefile	2001-02-11 23:11:45.000000000 +0200
++++ djbdns-1.05.new/Makefile	2007-09-30 15:09:51.000000000 +0300
+@@ -29,10 +29,6 @@
+ compile auto-str.c buffer.h exit.h
+ 	./compile auto-str.c
+ 
+-auto_home.c: \
+-auto-str conf-home
+-	./auto-str auto_home `head -1 conf-home` > auto_home.c
+-
+ auto_home.o: \
+ compile auto_home.c
+ 	./compile auto_home.c
+@@ -221,10 +217,6 @@
+ uint64.h taia.h dd.h
+ 	./compile dd.c
+ 
+-direntry.h: \
+-choose compile trydrent.c direntry.h1 direntry.h2
+-	./choose c trydrent direntry.h1 direntry.h2 > direntry.h
+-
+ dns.a: \
+ makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o dns_mx.o \
+ dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
+@@ -508,12 +500,6 @@
+ 	  *) cat hasdevtcp.h1 ;; \
+ 	esac ) > hasdevtcp.h
+ 
+-hasshsgr.h: \
+-choose compile load tryshsgr.c hasshsgr.h1 hasshsgr.h2 chkshsgr \
+-warn-shsgr
+-	./chkshsgr || ( cat warn-shsgr; exit 1 )
+-	./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h
+-
+ hier.o: \
+ compile hier.c auto_home.h
+ 	./compile hier.c
+@@ -534,10 +520,6 @@
+ compile instcheck.c strerr.h error.h exit.h
+ 	./compile instcheck.c
+ 
+-iopause.h: \
+-choose compile load trypoll.c iopause.h1 iopause.h2
+-	./choose clr trypoll iopause.h1 iopause.h2 > iopause.h
+-
+ iopause.o: \
+ compile iopause.c taia.h tai.h uint64.h select.h iopause.h taia.h
+ 	./compile iopause.c
+@@ -766,10 +748,6 @@
+ compile seek_set.c seek.h
+ 	./compile seek_set.c
+ 
+-select.h: \
+-choose compile trysysel.c select.h1 select.h2
+-	./choose c trysysel select.h1 select.h2 > select.h
+-
+ server.o: \
+ 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 \
+@@ -1060,10 +1038,6 @@
+ compile uint32_unpack.c uint32.h
+ 	./compile uint32_unpack.c
+ 
+-uint64.h: \
+-choose compile load tryulong64.c uint64.h1 uint64.h2
+-	./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h
+-
+ unix.a: \
+ 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 \
+diff -urN djbdns-1.05/auto_home.c djbdns-1.05.new/auto_home.c
+--- djbdns-1.05/auto_home.c	1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/auto_home.c	2007-09-30 13:32:06.000000000 +0300
+@@ -0,0 +1,3 @@
++const char auto_home[] = "\
++\057\165\163\162\
++";
+diff -urN djbdns-1.05/conf-cc djbdns-1.05.new/conf-cc
+--- djbdns-1.05/conf-cc	2007-09-30 14:11:35.000000000 +0300
++++ djbdns-1.05.new/conf-cc	2007-09-30 15:10:46.000000000 +0300
+@@ -1,3 +1,3 @@
+-gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings
++$TARGET_CC $TARGET_CFLAGS -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -include errno.h
+ 
+ This will be used to compile .c files.
+diff -urN djbdns-1.05/conf-home djbdns-1.05.new/conf-home
+--- djbdns-1.05/conf-home	2001-02-11 23:11:45.000000000 +0200
++++ djbdns-1.05.new/conf-home	2007-09-30 14:10:46.000000000 +0300
+@@ -1,4 +1,4 @@
+-/usr/local
++/usr
+ 
+ This is the dnscache home directory. Programs will be installed in
+ .../bin.
+diff -urN djbdns-1.05/conf-ld djbdns-1.05.new/conf-ld
+--- djbdns-1.05/conf-ld	2001-02-11 23:11:45.000000000 +0200
++++ djbdns-1.05.new/conf-ld	2007-09-30 15:11:00.000000000 +0300
+@@ -1,3 +1,3 @@
+-gcc -s
++$TARGET_CC -s $TARGET_LDFLAGS
+ 
+ This will be used to link .o files into an executable.
+diff -urN djbdns-1.05/direntry.h djbdns-1.05.new/direntry.h
+--- djbdns-1.05/direntry.h	1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/direntry.h	2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1,10 @@
++#ifndef DIRENTRY_H
++#define DIRENTRY_H
++
++/* sysdep: +dirent */
++
++#include <sys/types.h>
++#include <dirent.h>
++#define direntry struct dirent
++
++#endif
+diff -urN djbdns-1.05/hasshsgr.h djbdns-1.05.new/hasshsgr.h
+--- djbdns-1.05/hasshsgr.h	1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/hasshsgr.h	2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1 @@
++/* sysdep: -shortsetgroups */
+diff -urN djbdns-1.05/iopause.h djbdns-1.05.new/iopause.h
+--- djbdns-1.05/iopause.h	1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/iopause.h	2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1,18 @@
++#ifndef IOPAUSE_H
++#define IOPAUSE_H
++
++/* sysdep: +poll */
++#define IOPAUSE_POLL
++
++#include <sys/types.h>
++#include <poll.h>
++
++typedef struct pollfd iopause_fd;
++#define IOPAUSE_READ POLLIN
++#define IOPAUSE_WRITE POLLOUT
++
++#include "taia.h"
++
++extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *);
++
++#endif
+diff -urN djbdns-1.05/select.h djbdns-1.05.new/select.h
+--- djbdns-1.05/select.h	1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/select.h	2007-09-30 13:14:14.000000000 +0300
+@@ -0,0 +1,11 @@
++#ifndef SELECT_H
++#define SELECT_H
++
++/* sysdep: +sysselect */
++
++#include <sys/types.h>
++#include <sys/time.h>
++#include <sys/select.h>
++extern int select();
++
++#endif
+diff -urN djbdns-1.05/uint64.h djbdns-1.05.new/uint64.h
+--- djbdns-1.05/uint64.h	1970-01-01 03:00:00.000000000 +0300
++++ djbdns-1.05.new/uint64.h	2007-09-30 13:23:48.000000000 +0300
+@@ -0,0 +1,8 @@
++#ifndef UINT64_H
++#define UINT64_H
++
++/* sysdep: -ulong64 */
++
++typedef unsigned long long uint64;
++
++#endif
Index: patches/310-bugfix2-merge-outgoing-requests.patch
===================================================================
--- patches/310-bugfix2-merge-outgoing-requests.patch	(revision 16393)
+++ patches/310-bugfix2-merge-outgoing-requests.patch	(working copy)
@@ -1,349 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 1429643..bc047c0 100644
---- a/Makefile
-+++ b/Makefile
-@@ -318,11 +318,11 @@ stralloc.h iopause.h taia.h tai.h uint64.h taia.h
- 	./compile dns_txt.c
- 
- dnscache: \
--load dnscache.o droproot.o okclient.o log.o cache.o query.o \
-+load dnscache.o droproot.o okclient.o log.o cache.o query.o qmerge.o \
- response.o dd.o roots.o iopause.o prot.o dns.a env.a alloc.a buffer.a \
- libtai.a unix.a byte.a socket.lib
- 	./load dnscache droproot.o okclient.o log.o cache.o \
--	query.o response.o dd.o roots.o iopause.o prot.o dns.a \
-+	query.o qmerge.o response.o dd.o roots.o iopause.o prot.o dns.a \
- 	env.a alloc.a buffer.a libtai.a unix.a byte.a  `cat \
- 	socket.lib`
- 
-@@ -343,7 +343,7 @@ compile dnscache.c env.h exit.h scan.h strerr.h error.h ip4.h \
- uint16.h uint64.h socket.h uint16.h dns.h stralloc.h gen_alloc.h \
- iopause.h taia.h tai.h uint64.h taia.h taia.h byte.h roots.h fmt.h \
- iopause.h query.h dns.h uint32.h alloc.h response.h uint32.h cache.h \
--uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h
-+uint32.h uint64.h ndelay.h log.h uint64.h okclient.h droproot.h maxclient.h
- 	./compile dnscache.c
- 
- dnsfilter: \
-@@ -687,11 +687,16 @@ qlog.o: \
- compile qlog.c buffer.h qlog.h uint16.h
- 	./compile qlog.c
- 
-+qmerge.o: \
-+compile qmerge.c qmerge.h dns.h stralloc.h gen_alloc.h iopause.h \
-+taia.h tai.h uint64.h log.h maxclient.h
-+	./compile qmerge.c
-+
- query.o: \
- compile query.c error.h roots.h log.h uint64.h case.h cache.h \
- uint32.h uint64.h byte.h dns.h stralloc.h gen_alloc.h iopause.h \
- taia.h tai.h uint64.h taia.h uint64.h uint32.h uint16.h dd.h alloc.h \
--response.h uint32.h query.h dns.h uint32.h
-+response.h uint32.h query.h dns.h uint32.h qmerge.h
- 	./compile query.c
- 
- random-ip: \
-diff --git a/dnscache.c b/dnscache.c
-index 8c899a3..5ccb16a 100644
---- a/dnscache.c
-+++ b/dnscache.c
-@@ -22,6 +22,7 @@
- #include "log.h"
- #include "okclient.h"
- #include "droproot.h"
-+#include "maxclient.h"
- 
- static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2])
- {
-@@ -54,7 +55,6 @@ uint64 numqueries = 0;
- 
- static int udp53;
- 
--#define MAXUDP 200
- static struct udpclient {
-   struct query q;
-   struct taia start;
-@@ -131,7 +131,6 @@ void u_new(void)
- 
- static int tcp53;
- 
--#define MAXTCP 20
- struct tcpclient {
-   struct query q;
-   struct taia start;
-diff --git a/log.c b/log.c
-index c43e8b0..b8cd7ce 100644
---- a/log.c
-+++ b/log.c
-@@ -150,6 +150,13 @@ void log_tx(const char *q,const char qtype[2],const char *control,const char ser
-   line();
- }
- 
-+void log_tx_piggyback(const char *q, const char qtype[2], const char *control)
-+{
-+  string("txpb ");
-+  logtype(qtype); space(); name(q); space(); name(control);
-+  line();
-+}
-+
- void log_cachedanswer(const char *q,const char type[2])
- {
-   string("cached "); logtype(type); space();
-diff --git a/log.h b/log.h
-index fe62fa3..d9a829b 100644
---- a/log.h
-+++ b/log.h
-@@ -18,6 +18,7 @@ extern void log_cachednxdomain(const char *);
- extern void log_cachedns(const char *,const char *);
- 
- extern void log_tx(const char *,const char *,const char *,const char *,unsigned int);
-+extern void log_tx_piggyback(const char *,const char *,const char *);
- 
- extern void log_nxdomain(const char *,const char *,unsigned int);
- extern void log_nodata(const char *,const char *,const char *,unsigned int);
-diff --git a/maxclient.h b/maxclient.h
-new file mode 100644
-index 0000000..e52fcd1
---- /dev/null
-+++ b/maxclient.h
-@@ -0,0 +1,7 @@
-+#ifndef MAXCLIENT_H
-+#define MAXCLIENT_H
-+
-+#define MAXUDP 200
-+#define MAXTCP 20
-+
-+#endif /* MAXCLIENT_H */
-diff --git a/qmerge.c b/qmerge.c
-new file mode 100644
-index 0000000..7c92299
---- /dev/null
-+++ b/qmerge.c
-@@ -0,0 +1,115 @@
-+#include "qmerge.h"
-+#include "byte.h"
-+#include "log.h"
-+#include "maxclient.h"
-+
-+#define QMERGE_MAX (MAXUDP+MAXTCP)
-+struct qmerge inprogress[QMERGE_MAX];
-+
-+static
-+int qmerge_key_init(struct qmerge_key *qmk, const char *q, const char qtype[2],
-+    const char *control)
-+{
-+  if (!dns_domain_copy(&qmk->q, q)) return 0;
-+  byte_copy(qmk->qtype, 2, qtype);
-+  if (!dns_domain_copy(&qmk->control, control)) return 0;
-+  return 1;
-+}
-+
-+static
-+int qmerge_key_equal(struct qmerge_key *a, struct qmerge_key *b)
-+{
-+  return
-+    byte_equal(a->qtype, 2, b->qtype) &&
-+    dns_domain_equal(a->q, b->q) &&
-+    dns_domain_equal(a->control, b->control);
-+}
-+
-+static
-+void qmerge_key_free(struct qmerge_key *qmk)
-+{
-+  dns_domain_free(&qmk->q);
-+  dns_domain_free(&qmk->control);
-+}
-+
-+void qmerge_free(struct qmerge **x)
-+{
-+  struct qmerge *qm;
-+
-+  qm = *x;
-+  *x = 0;
-+  if (!qm || !qm->active) return;
-+
-+  qm->active--;
-+  if (!qm->active) {
-+    qmerge_key_free(&qm->key);
-+    dns_transmit_free(&qm->dt);
-+  }
-+}
-+
-+int qmerge_start(struct qmerge **qm, const char servers[64], int flagrecursive,
-+    const char *q, const char qtype[2], const char localip[4],
-+    const char *control)
-+{
-+  struct qmerge_key k;
-+  int i;
-+  int r;
-+
-+  qmerge_free(qm);
-+
-+  byte_zero(&k, sizeof k);
-+  if (!qmerge_key_init(&k, q, qtype, control)) return -1;
-+  for (i = 0; i < QMERGE_MAX; i++) {
-+    if (!inprogress[i].active) continue;
-+    if (!qmerge_key_equal(&k, &inprogress[i].key)) continue;
-+    log_tx_piggyback(q, qtype, control);
-+    inprogress[i].active++;
-+    *qm = &inprogress[i];
-+    qmerge_key_free(&k);
-+    return 0;
-+  }
-+
-+  for (i = 0; i < QMERGE_MAX; i++)
-+    if (!inprogress[i].active)
-+      break;
-+  if (i == QMERGE_MAX) return -1;
-+
-+  log_tx(q, qtype, control, servers, 0);
-+  r = dns_transmit_start(&inprogress[i].dt, servers, flagrecursive, q, qtype, localip);
-+  if (r == -1) { qmerge_key_free(&k); return -1; }
-+  inprogress[i].active++;
-+  inprogress[i].state = 0;
-+  qmerge_key_free(&inprogress[i].key);
-+  byte_copy(&inprogress[i].key, sizeof k, &k);
-+  *qm = &inprogress[i];
-+  return 0;
-+}
-+
-+void qmerge_io(struct qmerge *qm, iopause_fd *io, struct taia *deadline)
-+{
-+  if (qm->state == 0) {
-+    dns_transmit_io(&qm->dt, io, deadline);
-+    qm->state = 1;
-+  }
-+  else {
-+    io->fd = -1;
-+    io->events = 0;
-+  }
-+}
-+
-+int qmerge_get(struct qmerge **x, const iopause_fd *io, const struct taia *when)
-+{
-+  int r;
-+  struct qmerge *qm;
-+
-+  qm = *x;
-+  if (qm->state == -1) return -1; /* previous error */
-+  if (qm->state == 0) return 0; /* no packet */
-+  if (qm->state == 2) return 1; /* already got packet */
-+
-+  r = dns_transmit_get(&qm->dt, io, when);
-+  if (r == -1) { qm->state = -1; return -1; } /* error */
-+  if (r == 0) { qm->state = 0; return 0; } /* must wait for i/o */
-+  if (r == 1) { qm->state = 2; return 1; } /* got packet */
-+  return -1; /* bug */
-+}
-diff --git a/qmerge.h b/qmerge.h
-new file mode 100644
-index 0000000..9a58157
---- /dev/null
-+++ b/qmerge.h
-@@ -0,0 +1,24 @@
-+#ifndef QMERGE_H
-+#define QMERGE_H
-+
-+#include "dns.h"
-+
-+struct qmerge_key {
-+  char *q;
-+  char qtype[2];
-+  char *control;
-+};
-+
-+struct qmerge {
-+  int active;
-+  struct qmerge_key key;
-+  struct dns_transmit dt;
-+  int state; /* -1 = error, 0 = need io, 1 = need get, 2 = got packet */
-+};
-+
-+extern int qmerge_start(struct qmerge **,const char *,int,const char *,const char *,const char *,const char *);
-+extern void qmerge_io(struct qmerge *,iopause_fd *,struct taia *);
-+extern int qmerge_get(struct qmerge **,const iopause_fd *,const struct taia *);
-+extern void qmerge_free(struct qmerge **);
-+
-+#endif /* QMERGE_H */
-diff --git a/query.c b/query.c
-index 46cdc00..f091fdd 100644
---- a/query.c
-+++ b/query.c
-@@ -81,7 +81,7 @@ static void cleanup(struct query *z)
-   int j;
-   int k;
- 
--  dns_transmit_free(&z->dt);
-+  qmerge_free(&z->qm);
-   for (j = 0;j < QUERY_MAXALIAS;++j)
-     dns_domain_free(&z->alias[j]);
-   for (j = 0;j < QUERY_MAXLEVEL;++j) {
-@@ -429,14 +429,8 @@ static int doit(struct query *z,int state)
-   if (j == 64) goto SERVFAIL;
- 
-   dns_sortip(z->servers[z->level],64);
--  if (z->level) {
--    log_tx(z->name[z->level],DNS_T_A,z->control[z->level],z->servers[z->level],z->level);
--    if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],DNS_T_A,z->localip) == -1) goto DIE;
--  }
--  else {
--    log_tx(z->name[0],z->type,z->control[0],z->servers[0],0);
--    if (dns_transmit_start(&z->dt,z->servers[0],flagforwardonly,z->name[0],z->type,z->localip) == -1) goto DIE;
--  }
-+  dtype = z->level ? DNS_T_A : z->type;
-+  if (qmerge_start(&z->qm,z->servers[z->level],flagforwardonly,z->name[z->level],dtype,z->localip,z->control[z->level]) == -1) goto DIE;
-   return 0;
- 
- 
-@@ -450,10 +444,10 @@ static int doit(struct query *z,int state)
- 
-   HAVEPACKET:
-   if (++z->loop == 100) goto DIE;
--  buf = z->dt.packet;
--  len = z->dt.packetlen;
-+  buf = z->qm->dt.packet;
-+  len = z->qm->dt.packetlen;
- 
--  whichserver = z->dt.servers + 4 * z->dt.curserver;
-+  whichserver = z->qm->dt.servers + 4 * z->qm->dt.curserver;
-   control = z->control[z->level];
-   d = z->name[z->level];
-   dtype = z->level ? DNS_T_A : z->type;
-@@ -836,7 +830,7 @@ int query_start(struct query *z,char *dn,char type[2],char class[2],char localip
- 
- int query_get(struct query *z,iopause_fd *x,struct taia *stamp)
- {
--  switch(dns_transmit_get(&z->dt,x,stamp)) {
-+  switch(qmerge_get(&z->qm,x,stamp)) {
-     case 1:
-       return doit(z,1);
-     case -1:
-@@ -847,5 +841,5 @@ int query_get(struct query *z,iopause_fd *x,struct taia *stamp)
- 
- void query_io(struct query *z,iopause_fd *x,struct taia *deadline)
- {
--  dns_transmit_io(&z->dt,x,deadline);
-+  qmerge_io(z->qm,x,deadline);
- }
-diff --git a/query.h b/query.h
-index eff68b2..06feab4 100644
---- a/query.h
-+++ b/query.h
-@@ -1,7 +1,7 @@
- #ifndef QUERY_H
- #define QUERY_H
- 
--#include "dns.h"
-+#include "qmerge.h"
- #include "uint32.h"
- 
- #define QUERY_MAXLEVEL 5
-@@ -20,7 +20,7 @@ struct query {
-   char localip[4];
-   char type[2];
-   char class[2];
--  struct dns_transmit dt;
-+  struct qmerge *qm;
- } ;
- 
- extern int query_start(struct query *,char *,char *,char *,char *);
Index: patches/300-bugfix-dnscache-dempsky-poison.patch
===================================================================
--- patches/300-bugfix-dnscache-dempsky-poison.patch	(revision 0)
+++ patches/300-bugfix-dnscache-dempsky-poison.patch	(revision 0)
@@ -0,0 +1,11 @@
+--- a/response.c.orig	2009-02-24 21:04:06.000000000 -0800
++++ b/response.c	2009-02-24 21:04:25.000000000 -0800
+@@ -34,7 +34,7 @@
+         uint16_pack_big(buf,49152 + name_ptr[i]);
+         return response_addbytes(buf,2);
+       }
+-    if (dlen <= 128)
++    if ((dlen <= 128) && (response_len < 16384))
+       if (name_num < NAMES) {
+ 	byte_copy(name[name_num],dlen,d);
+ 	name_ptr[name_num] = response_len;
Index: patches/070-dnscache-dpos-tcp-servfail.patch
===================================================================
--- patches/070-dnscache-dpos-tcp-servfail.patch	(revision 0)
+++ patches/070-dnscache-dpos-tcp-servfail.patch	(revision 0)
@@ -0,0 +1,11 @@
+--- old/dns_transmit.c.orig	2008-01-08 13:58:33.000000000 -0800
++++ new/dns_transmit.c	2008-01-08 13:57:56.000000000 -0800
+@@ -166,6 +166,7 @@
+       taia_uint(&d->deadline,10);
+       taia_add(&d->deadline,&d->deadline,&now);
+       if (socket_connect4(d->s1 - 1,ip,53) == 0) {
++        d->pos = 0;
+         d->tcpstate = 2;
+         return 0;
+       }
+
Index: patches/110-cachestats.patch
===================================================================
--- patches/110-cachestats.patch	(revision 16393)
+++ patches/110-cachestats.patch	(working copy)
@@ -1,89 +0,0 @@
-#
-# This patch to djbdns 1.05 modifies the dnscache program to keep a
-# counter of cache hits and cache misses.
-#
-# Two new fields are added to the ``stats'' output line:
-#  . the fifth number is the number of cache hits
-#  . the sixth number is the number of cache misses
-# e.g.
-#  @400000003fa92ccc317d70f4 stats 3 1201 1 0 21 49
-# indicates 21 hits and 49 misses.
-#
-# James Raftery <james at now.ie>  6 Nov. 2003
-#
---- djbdns-1.05.orig/cache.c	Sun Feb 11 21:11:45 2001
-+++ djbdns-1.05/cache.c	Wed Nov  5 17:21:06 2003
-@@ -7,6 +7,11 @@
- 
- uint64 cache_motion = 0;
- 
-+/* record cache stats */
-+/* James Raftery <james at now.ie> 6 Nov. 2003 */
-+uint64 cache_hit = 0;
-+uint64 cache_miss = 0;
-+
- static char *x = 0;
- static uint32 size;
- static uint32 hsize;
-@@ -112,15 +117,20 @@
-         if (u > size - pos - 20 - keylen) cache_impossible();
-         *datalen = u;
- 
-+        cache_hit++;
-         return x + pos + 20 + keylen;
-       }
-     }
-     nextpos = prevpos ^ get4(pos);
-     prevpos = pos;
-     pos = nextpos;
--    if (++loop > 100) return 0; /* to protect against hash flooding */
-+    if (++loop > 100) { /* to protect against hash flooding */
-+      cache_miss++;
-+      return 0;
-+    }
-   }
- 
-+  cache_miss++;
-   return 0;
- }
- 
---- djbdns-1.05.orig/cache.h	Sun Feb 11 21:11:45 2001
-+++ djbdns-1.05/cache.h	Wed Nov  5 17:13:36 2003
-@@ -5,6 +5,12 @@
- #include "uint64.h"
- 
- extern uint64 cache_motion;
-+
-+/* record cache stats */
-+/* James Raftery <james at now.ie> 6 Nov. 2003 */
-+extern uint64 cache_hit;
-+extern uint64 cache_miss;
-+
- extern int cache_init(unsigned int);
- extern void cache_set(const char *,unsigned int,const char *,unsigned int,uint32);
- extern char *cache_get(const char *,unsigned int,unsigned int *,uint32 *);
---- djbdns-1.05.orig/log.c	Sun Feb 11 21:11:45 2001
-+++ djbdns-1.05/log.c	Wed Nov  5 17:21:12 2003
-@@ -276,6 +276,12 @@
- {
-   extern uint64 numqueries;
-   extern uint64 cache_motion;
-+
-+  /* record cache stats */
-+  /* James Raftery <james at now.ie> 6 Nov. 2003 */
-+  extern uint64 cache_hit;
-+  extern uint64 cache_miss;
-+
-   extern int uactive;
-   extern int tactive;
- 
-@@ -283,6 +289,8 @@
-   number(numqueries); space();
-   number(cache_motion); space();
-   number(uactive); space();
--  number(tactive);
-+  number(tactive); space();
-+  number(cache_hit); space();
-+  number(cache_miss);
-   line();
- }
Index: patches/040-dnscache-less-chatty-log.patch
===================================================================
--- patches/040-dnscache-less-chatty-log.patch	(revision 0)
+++ patches/040-dnscache-less-chatty-log.patch	(revision 0)
@@ -0,0 +1,40 @@
+--- djbdns-1.05/log.h	2005-03-16 13:00:04.779943592 -0700
++++ djbdns-1.05/log.h	2005-03-16 13:00:16.710129928 -0700
+@@ -1,6 +1,8 @@
+ #ifndef LOG_H
+ #define LOG_H
+ 
++#define STATS_DISPLAY_INTERVAL 5
++
+ #include "uint64.h"
+ 
+ extern void log_startup(void);
+--- djbdns-1.05/log.c	2005-03-16 12:57:20.465923120 -0700
++++ djbdns-1.05/log.c	2005-03-16 13:01:36.092062040 -0700
+@@ -7,6 +1,7 @@
+ #include "buffer.h"
+ #include "uint32.h"
+ #include "uint16.h"
++#include "time.h"
+ #include "error.h"
+ #include "byte.h"
+ #include "log.h"
+@@ -274,11 +275,17 @@
+ 
+ void log_stats(void)
+ {
++  static time_t prev = 0;
++  time_t cur = time(NULL);
+   extern uint64 numqueries;
+   extern uint64 cache_motion;
+   extern int uactive;
+   extern int tactive;
+ 
++  if(prev == 0) prev = time(NULL);
++  if(cur - prev < STATS_DISPLAY_INTERVAL) return;
++  prev = cur;
++
+   string("stats ");
+   number(numqueries); space();
+   number(cache_motion); space();
+
Index: patches/060-dnscache-big-udp-packets.patch
===================================================================
--- patches/060-dnscache-big-udp-packets.patch	(revision 0)
+++ patches/060-dnscache-big-udp-packets.patch	(revision 0)
@@ -0,0 +1,12 @@
+--- old/dns_transmit.c.orig	2008-10-10 16:59:03.000000000 -0700
++++ new/dns_transmit.c	2008-10-10 16:59:11.000000000 -0700
+@@ -240,7 +240,7 @@
+
+ int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct taia *when)
+ {
+-  char udpbuf[513];
++  char udpbuf[4097];
+   unsigned char ch;
+   int r;
+   int fd;
+
Index: patches/020-dnsroots-update.patch
===================================================================
--- patches/020-dnsroots-update.patch	(revision 0)
+++ patches/020-dnsroots-update.patch	(revision 0)
@@ -0,0 +1,19 @@
+--- djbdns/dnsroots.global	2001-02-11 22:11:45.000000000 +0100
++++ djbdns.new/dnsroots.global	2009-04-30 20:53:28.000000000 +0200
+@@ -1,5 +1,5 @@
+ 198.41.0.4
+-128.9.0.107
++192.228.79.201
+ 192.33.4.12
+ 128.8.10.90
+ 192.203.230.10
+@@ -7,7 +7,7 @@
+ 192.112.36.4
+ 128.63.2.53
+ 192.36.148.17
+-198.41.0.10
++192.58.128.30
+ 193.0.14.129
+-198.32.64.12
++199.7.83.42
+ 202.12.27.33
Index: patches/260-djbdns-1.05-dnsfilter-replace.patch
===================================================================
--- patches/260-djbdns-1.05-dnsfilter-replace.patch	(revision 16393)
+++ patches/260-djbdns-1.05-dnsfilter-replace.patch	(working copy)
@@ -1,71 +0,0 @@
---- a/dnsfilter.c	Thu Feb 15 21:29:28 2001
-+++ b/dnsfilter.c	Thu Feb 15 21:57:36 2001
-@@ -41,6 +41,7 @@
- iopause_fd *inio;
- int flag0 = 1;
- 
-+int opt_replace = 0;
- iopause_fd *io;
- int iolen;
- 
-@@ -51,12 +52,16 @@
- void errout(int i)
- {
-   int j;
--
--  if (!stralloc_copys(&x[i].middle,":")) nomem();
--  if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
--  for (j = 0;j < x[i].middle.len;++j)
--    if (x[i].middle.s[j] == ' ')
--      x[i].middle.s[j] = '-';
-+ 
-+  if (opt_replace) 
-+    x[i].middle.len=0;
-+  else {
-+    if (!stralloc_copys(&x[i].middle,":")) nomem();
-+    if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
-+    for (j = 0;j < x[i].middle.len;++j)
-+      if (x[i].middle.s[j] == ' ')
-+        x[i].middle.s[j] = '-';
-+  }
- }
- 
- int main(int argc,char **argv)
-@@ -69,7 +74,7 @@
-   int j;
-   int r;
- 
--  while ((opt = getopt(argc,argv,"c:l:")) != opteof)
-+  while ((opt = getopt(argc,argv,"c:l:r")) != opteof)
-     switch(opt) {
-       case 'c':
- 	scan_ulong(optarg,&u);
-@@ -83,8 +88,11 @@
- 	if (u > 1000000) u = 1000000;
- 	xmax = u;
- 	break;
-+      case 'r':
-+	opt_replace = 1;	  
-+	break;
-       default:
--	strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ]");
-+	strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ] [-r]");
-     }
- 
-   x = (struct line *) alloc(xmax * sizeof(struct line));
-@@ -140,8 +148,13 @@
- 	else if (r == 1) {
- 	  if (dns_name_packet(&x[i].middle,x[i].dt.packet,x[i].dt.packetlen) == -1)
- 	    errout(i);
--	  if (x[i].middle.len)
--	    if (!stralloc_cats(&x[i].left,"=")) nomem();
-+	  if (x[i].middle.len) {
-+	    if (opt_replace) {
-+	      if (!stralloc_copys(&x[i].left, "")) nomem();
-+	    } else {
-+	      if (!stralloc_cats(&x[i].left, "=")) nomem();
-+	    }
-+	  }
- 	  x[i].flagactive = 0;
- 	  --numactive;
- 	}
Index: patches/100-crosscompile.patch
===================================================================
--- patches/100-crosscompile.patch	(revision 16393)
+++ patches/100-crosscompile.patch	(working copy)
@@ -1,171 +0,0 @@
-diff -urN djbdns-1.05/Makefile djbdns-1.05.new/Makefile
---- djbdns-1.05/Makefile	2001-02-11 23:11:45.000000000 +0200
-+++ djbdns-1.05.new/Makefile	2007-09-30 15:09:51.000000000 +0300
-@@ -29,10 +29,6 @@
- compile auto-str.c buffer.h exit.h
- 	./compile auto-str.c
- 
--auto_home.c: \
--auto-str conf-home
--	./auto-str auto_home `head -1 conf-home` > auto_home.c
--
- auto_home.o: \
- compile auto_home.c
- 	./compile auto_home.c
-@@ -221,10 +217,6 @@
- uint64.h taia.h dd.h
- 	./compile dd.c
- 
--direntry.h: \
--choose compile trydrent.c direntry.h1 direntry.h2
--	./choose c trydrent direntry.h1 direntry.h2 > direntry.h
--
- dns.a: \
- makelib dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ipq.o dns_mx.o \
- dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o \
-@@ -508,12 +500,6 @@
- 	  *) cat hasdevtcp.h1 ;; \
- 	esac ) > hasdevtcp.h
- 
--hasshsgr.h: \
--choose compile load tryshsgr.c hasshsgr.h1 hasshsgr.h2 chkshsgr \
--warn-shsgr
--	./chkshsgr || ( cat warn-shsgr; exit 1 )
--	./choose clr tryshsgr hasshsgr.h1 hasshsgr.h2 > hasshsgr.h
--
- hier.o: \
- compile hier.c auto_home.h
- 	./compile hier.c
-@@ -534,10 +520,6 @@
- compile instcheck.c strerr.h error.h exit.h
- 	./compile instcheck.c
- 
--iopause.h: \
--choose compile load trypoll.c iopause.h1 iopause.h2
--	./choose clr trypoll iopause.h1 iopause.h2 > iopause.h
--
- iopause.o: \
- compile iopause.c taia.h tai.h uint64.h select.h iopause.h taia.h
- 	./compile iopause.c
-@@ -766,10 +748,6 @@
- compile seek_set.c seek.h
- 	./compile seek_set.c
- 
--select.h: \
--choose compile trysysel.c select.h1 select.h2
--	./choose c trysysel select.h1 select.h2 > select.h
--
- server.o: \
- 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 \
-@@ -1060,10 +1038,6 @@
- compile uint32_unpack.c uint32.h
- 	./compile uint32_unpack.c
- 
--uint64.h: \
--choose compile load tryulong64.c uint64.h1 uint64.h2
--	./choose clr tryulong64 uint64.h1 uint64.h2 > uint64.h
--
- unix.a: \
- 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 \
-diff -urN djbdns-1.05/auto_home.c djbdns-1.05.new/auto_home.c
---- djbdns-1.05/auto_home.c	1970-01-01 03:00:00.000000000 +0300
-+++ djbdns-1.05.new/auto_home.c	2007-09-30 13:32:06.000000000 +0300
-@@ -0,0 +1,3 @@
-+const char auto_home[] = "\
-+\057\165\163\162\
-+";
-diff -urN djbdns-1.05/conf-cc djbdns-1.05.new/conf-cc
---- djbdns-1.05/conf-cc	2007-09-30 14:11:35.000000000 +0300
-+++ djbdns-1.05.new/conf-cc	2007-09-30 15:10:46.000000000 +0300
-@@ -1,3 +1,3 @@
--gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings
-+$TARGET_CC $TARGET_CFLAGS -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -include errno.h
- 
- This will be used to compile .c files.
-diff -urN djbdns-1.05/conf-home djbdns-1.05.new/conf-home
---- djbdns-1.05/conf-home	2001-02-11 23:11:45.000000000 +0200
-+++ djbdns-1.05.new/conf-home	2007-09-30 14:10:46.000000000 +0300
-@@ -1,4 +1,4 @@
--/usr/local
-+/usr
- 
- This is the dnscache home directory. Programs will be installed in
- .../bin.
-diff -urN djbdns-1.05/conf-ld djbdns-1.05.new/conf-ld
---- djbdns-1.05/conf-ld	2001-02-11 23:11:45.000000000 +0200
-+++ djbdns-1.05.new/conf-ld	2007-09-30 15:11:00.000000000 +0300
-@@ -1,3 +1,3 @@
--gcc -s
-+$TARGET_CC -s $TARGET_LDFLAGS
- 
- This will be used to link .o files into an executable.
-diff -urN djbdns-1.05/direntry.h djbdns-1.05.new/direntry.h
---- djbdns-1.05/direntry.h	1970-01-01 03:00:00.000000000 +0300
-+++ djbdns-1.05.new/direntry.h	2007-09-30 13:14:14.000000000 +0300
-@@ -0,0 +1,10 @@
-+#ifndef DIRENTRY_H
-+#define DIRENTRY_H
-+
-+/* sysdep: +dirent */
-+
-+#include <sys/types.h>
-+#include <dirent.h>
-+#define direntry struct dirent
-+
-+#endif
-diff -urN djbdns-1.05/hasshsgr.h djbdns-1.05.new/hasshsgr.h
---- djbdns-1.05/hasshsgr.h	1970-01-01 03:00:00.000000000 +0300
-+++ djbdns-1.05.new/hasshsgr.h	2007-09-30 13:14:14.000000000 +0300
-@@ -0,0 +1 @@
-+/* sysdep: -shortsetgroups */
-diff -urN djbdns-1.05/iopause.h djbdns-1.05.new/iopause.h
---- djbdns-1.05/iopause.h	1970-01-01 03:00:00.000000000 +0300
-+++ djbdns-1.05.new/iopause.h	2007-09-30 13:14:14.000000000 +0300
-@@ -0,0 +1,18 @@
-+#ifndef IOPAUSE_H
-+#define IOPAUSE_H
-+
-+/* sysdep: +poll */
-+#define IOPAUSE_POLL
-+
-+#include <sys/types.h>
-+#include <poll.h>
-+
-+typedef struct pollfd iopause_fd;
-+#define IOPAUSE_READ POLLIN
-+#define IOPAUSE_WRITE POLLOUT
-+
-+#include "taia.h"
-+
-+extern void iopause(iopause_fd *,unsigned int,struct taia *,struct taia *);
-+
-+#endif
-diff -urN djbdns-1.05/select.h djbdns-1.05.new/select.h
---- djbdns-1.05/select.h	1970-01-01 03:00:00.000000000 +0300
-+++ djbdns-1.05.new/select.h	2007-09-30 13:14:14.000000000 +0300
-@@ -0,0 +1,11 @@
-+#ifndef SELECT_H
-+#define SELECT_H
-+
-+/* sysdep: +sysselect */
-+
-+#include <sys/types.h>
-+#include <sys/time.h>
-+#include <sys/select.h>
-+extern int select();
-+
-+#endif
-diff -urN djbdns-1.05/uint64.h djbdns-1.05.new/uint64.h
---- djbdns-1.05/uint64.h	1970-01-01 03:00:00.000000000 +0300
-+++ djbdns-1.05.new/uint64.h	2007-09-30 13:23:48.000000000 +0300
-@@ -0,0 +1,8 @@
-+#ifndef UINT64_H
-+#define UINT64_H
-+
-+/* sysdep: -ulong64 */
-+
-+typedef unsigned long long uint64;
-+
-+#endif
Index: patches/080-dnscache-cache-negatives.patch
===================================================================
--- patches/080-dnscache-cache-negatives.patch	(revision 0)
+++ patches/080-dnscache-cache-negatives.patch	(revision 0)
@@ -0,0 +1,42 @@
+--- djbdns-1.05.old/query.c	2001-02-11 14:11:45.000000000 -0700
++++ djbdns-1.05.new/query.c	2005-03-16 12:48:23.236594392 -0700
+@@ -193,6 +193,7 @@
+   int k;
+   int p;
+   int q;
++  uint32 cachettl;
+
+   errno = error_io;
+   if (state == 1) goto HAVEPACKET;
+@@ -471,6 +472,7 @@
+   rcode = header[3] & 15;
+   if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */
+
++  cachettl = 0;
+   flagout = 0;
+   flagcname = 0;
+   flagreferral = 0;
+@@ -512,6 +514,11 @@
+ 
+     uint16_unpack_big(header + 8,&datalen);
+     pos += datalen;
++
++    if (flagsoa && (pos <= len)) {
++      cachettl = ttlget(buf + pos - 4);
++      if (soattl < cachettl) cachettl = soattl;
++    }
+   }
+   posglue = pos;
+ 
+@@ -689,8 +696,8 @@
+   }
+ 
+   if (rcode == 3) {
+-    log_nxdomain(whichserver,d,soattl);
+-    cachegeneric(DNS_T_ANY,d,"",0,soattl);
++    log_nxdomain(whichserver,d,cachettl);
++    cachegeneric(DNS_T_ANY,d,"",0,cachettl);
+ 
+     NXDOMAIN:
+     if (z->level) goto LOWERLEVEL;
+
Index: patches/030-srv-records-and-axfrget.patch
===================================================================
--- patches/030-srv-records-and-axfrget.patch	(revision 0)
+++ patches/030-srv-records-and-axfrget.patch	(revision 0)
@@ -0,0 +1,138 @@
+From: Michael Handler <handler at sub-rosa.com>
+To: dns at list.cr.yp.to
+Subject: tinydns-data SRV & axfr-get SRV/PTR patches
+Date: Thu, 14 Sep 2000 20:37:50 -0400
+
+Here's a combined patch that:
+
+a) adds a native SRV type to tinydns-data
+
+Sfqdn:ip:x:port:weight:priority:ttl:timestamp
+
+Standard rules for ip, x, ttl, and timestamp apply. Port, weight, and
+priority all range from 0-65535. Weight and priority are optional; they
+default to zero if not provided.
+
+Sconsole.zoinks.example.com:1.2.3.4:rack102-con1:2001:69:7:300:
+
+b) makes axfr-get decompose SRV and PTR records and write them out in
+native format, rather than opaque. Again, this is necessary because if the
+DNAME fields in the records reference the same zone as fqdn, they can have
+compression pointers that are bogus outside the context of that specific
+packet, and which can't be correctly loaded into data.cdb by tinydns-data.
+
+--michael
+
+Laurent G. Bercot <ska-djbdns at skarnet.org> updated it for djbdns-1.05:
+
+diff -rNU3 djbdns-1.05/axfr-get.c djbdns-1.05-srv/axfr-get.c
+--- djbdns-1.05/axfr-get.c	Sun Feb 11 22:11:45 2001
++++ djbdns-1.05-srv/axfr-get.c	Thu Oct 18 14:46:56 2001
+@@ -209,6 +209,26 @@
+     if (!stralloc_cats(&line,".:")) return 0;
+     if (!stralloc_catulong0(&line,dist,0)) return 0;
+   }
++  else if (byte_equal(data,2,DNS_T_SRV)) {
++    uint16 dist, weight, port;
++    if (!stralloc_copys(&line,"S")) return 0;
++    if (!dns_domain_todot_cat(&line,d1)) return 0;
++    if (!stralloc_cats(&line,"::")) return 0;
++    pos = x_copy(buf,len,pos,data,2);
++    uint16_unpack_big(data,&dist);
++    pos = x_copy(buf,len,pos,data,2);
++    uint16_unpack_big(data,&weight);
++    pos = x_copy(buf,len,pos,data,2);
++    uint16_unpack_big(data,&port);
++    x_getname(buf,len,pos,&d1);
++    if (!dns_domain_todot_cat(&line,d1)) return 0;
++    if (!stralloc_cats(&line,".:")) return 0;
++    if (!stralloc_catulong0(&line,dist,0)) return 0;
++    if (!stralloc_cats(&line,":")) return 0;
++    if (!stralloc_catulong0(&line,weight,0)) return 0;
++    if (!stralloc_cats(&line,":")) return 0;
++    if (!stralloc_catulong0(&line,port,0)) return 0;
++  }
+   else if (byte_equal(data,2,DNS_T_A) && (dlen == 4)) {
+     char ipstr[IP4_FMT];
+     if (!stralloc_copys(&line,"+")) return 0;
+@@ -216,6 +236,14 @@
+     if (!stralloc_cats(&line,":")) return 0;
+     x_copy(buf,len,pos,data,4);
+     if (!stralloc_catb(&line,ipstr,ip4_fmt(ipstr,data))) return 0;
++  }
++  else if (byte_equal(data,2,DNS_T_PTR)) {
++    if (!stralloc_copys(&line,"^")) return 0;
++    if (!dns_domain_todot_cat(&line,d1)) return 0;
++    if (!stralloc_cats(&line,":")) return 0;
++    x_getname(buf,len,pos,&d1);
++    if (!dns_domain_todot_cat(&line,d1)) return 0;
++    if (!stralloc_cats(&line,".")) return 0;
+   }
+   else {
+     unsigned char ch;
+diff -rNU3 djbdns-1.05/dns.h djbdns-1.05-srv/dns.h
+--- djbdns-1.05/dns.h	Sun Feb 11 22:11:45 2001
++++ djbdns-1.05-srv/dns.h	Thu Oct 18 14:46:56 2001
+@@ -20,6 +20,7 @@
+ #define DNS_T_SIG "\0\30"
+ #define DNS_T_KEY "\0\31"
+ #define DNS_T_AAAA "\0\34"
++#define DNS_T_SRV "\0\41"
+ #define DNS_T_AXFR "\0\374"
+ #define DNS_T_ANY "\0\377"
+ 
+diff -rNU3 djbdns-1.05/tinydns-data.c djbdns-1.05-srv/tinydns-data.c
+--- djbdns-1.05/tinydns-data.c	Sun Feb 11 22:11:45 2001
++++ djbdns-1.05-srv/tinydns-data.c	Thu Oct 18 14:50:53 2001
+@@ -196,6 +196,7 @@
+   char type[2];
+   char soa[20];
+   char buf[4];
++  char srv[6];
+ 
+   umask(022);
+ 
+@@ -360,6 +361,43 @@
+ 	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,loc);
++	  rr_add(ip,4);
++	  rr_finish(d2);
++	}
++	break;
++	
++      case 'S':
++	if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
++	if (!stralloc_0(&f[6])) nomem();
++	if (!scan_ulong(f[6].s,&ttl)) ttl = TTL_POSITIVE;
++	ttdparse(&f[7],ttd);
++	locparse(&f[8],loc);
++
++	if (!stralloc_0(&f[1])) nomem();
++
++	if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
++	  if (!stralloc_cats(&f[2],".srv.")) nomem();
++	  if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
++	}
++	if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem();
++
++	if (!stralloc_0(&f[4])) nomem();
++	if (!scan_ulong(f[4].s,&u)) u = 0;
++	uint16_pack_big(srv,u);
++	if (!stralloc_0(&f[5])) nomem();
++	if (!scan_ulong(f[5].s,&u)) u = 0;
++	uint16_pack_big(srv + 2,u);
++	if (!stralloc_0(&f[3])) nomem();
++	if (!scan_ulong(f[3].s,&u)) nomem();
++	uint16_pack_big(srv + 4,u);
++
++	rr_start(DNS_T_SRV,ttl,ttd,loc);
++	rr_add(srv,6);
+ 	rr_addname(d2);
+ 	rr_finish(d1);
+ 
Index: patches/260-dnsfilter-replace.patch
===================================================================
--- patches/260-dnsfilter-replace.patch	(revision 0)
+++ patches/260-dnsfilter-replace.patch	(revision 0)
@@ -0,0 +1,71 @@
+--- a/dnsfilter.c	Thu Feb 15 21:29:28 2001
++++ b/dnsfilter.c	Thu Feb 15 21:57:36 2001
+@@ -41,6 +41,7 @@
+ iopause_fd *inio;
+ int flag0 = 1;
+ 
++int opt_replace = 0;
+ iopause_fd *io;
+ int iolen;
+ 
+@@ -51,12 +52,16 @@
+ void errout(int i)
+ {
+   int j;
+-
+-  if (!stralloc_copys(&x[i].middle,":")) nomem();
+-  if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
+-  for (j = 0;j < x[i].middle.len;++j)
+-    if (x[i].middle.s[j] == ' ')
+-      x[i].middle.s[j] = '-';
++ 
++  if (opt_replace) 
++    x[i].middle.len=0;
++  else {
++    if (!stralloc_copys(&x[i].middle,":")) nomem();
++    if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
++    for (j = 0;j < x[i].middle.len;++j)
++      if (x[i].middle.s[j] == ' ')
++        x[i].middle.s[j] = '-';
++  }
+ }
+ 
+ int main(int argc,char **argv)
+@@ -69,7 +74,7 @@
+   int j;
+   int r;
+ 
+-  while ((opt = getopt(argc,argv,"c:l:")) != opteof)
++  while ((opt = getopt(argc,argv,"c:l:r")) != opteof)
+     switch(opt) {
+       case 'c':
+ 	scan_ulong(optarg,&u);
+@@ -83,8 +88,11 @@
+ 	if (u > 1000000) u = 1000000;
+ 	xmax = u;
+ 	break;
++      case 'r':
++	opt_replace = 1;	  
++	break;
+       default:
+-	strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ]");
++	strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ] [-r]");
+     }
+ 
+   x = (struct line *) alloc(xmax * sizeof(struct line));
+@@ -140,8 +148,13 @@
+ 	else if (r == 1) {
+ 	  if (dns_name_packet(&x[i].middle,x[i].dt.packet,x[i].dt.packetlen) == -1)
+ 	    errout(i);
+-	  if (x[i].middle.len)
+-	    if (!stralloc_cats(&x[i].left,"=")) nomem();
++	  if (x[i].middle.len) {
++	    if (opt_replace) {
++	      if (!stralloc_copys(&x[i].left, "")) nomem();
++	    } else {
++	      if (!stralloc_cats(&x[i].left, "=")) nomem();
++	    }
++	  }
+ 	  x[i].flagactive = 0;
+ 	  --numactive;
+ 	}
Index: patches/130-dnscache-multiple-ip.patch
===================================================================
--- patches/130-dnscache-multiple-ip.patch	(revision 16393)
+++ patches/130-dnscache-multiple-ip.patch	(working copy)
@@ -1,301 +0,0 @@
---- djbdns-1.05.orig/dnscache.c.orig	Tue Feb 27 00:32:52 2001
-+++ djbdns-1.05/dnscache.c	Tue Feb 27 00:30:58 2001
-@@ -5,6 +5,7 @@
- #include "strerr.h"
- #include "error.h"
- #include "ip4.h"
-+#include "str.h"
- #include "uint16.h"
- #include "uint64.h"
- #include "socket.h"
-@@ -47,12 +48,20 @@
- 
- 
- static char myipoutgoing[4];
--static char myipincoming[4];
- static char buf[1024];
- uint64 numqueries = 0;
- 
-+struct interf {
-+  char ip[4];
-+  int udp53;
-+  int tcp53;
-+  iopause_fd *udp53io;
-+  iopause_fd *tcp53io;
-+  
-+  struct interf *next;
-+} ;
- 
--static int udp53;
-+struct interf *interhead = 0;
- 
- #define MAXUDP 200
- static struct udpclient {
-@@ -60,6 +69,7 @@
-   struct taia start;
-   uint64 active; /* query number, if active; otherwise 0 */
-   iopause_fd *io;
-+  int fd;
-   char ip[4];
-   uint16 port;
-   char id[2];
-@@ -78,12 +88,12 @@
-   if (!u[j].active) return;
-   response_id(u[j].id);
-   if (response_len > 512) response_tc();
--  socket_send4(udp53,response,response_len,u[j].ip,u[j].port);
-+  socket_send4(u[j].fd,response,response_len,u[j].ip,u[j].port);
-   log_querydone(&u[j].active,response_len);
-   u[j].active = 0; --uactive;
- }
- 
--void u_new(void)
-+void u_new(int fd)
- {
-   int j;
-   int i;
-@@ -108,8 +118,9 @@
- 
-   x = u + j;
-   taia_now(&x->start);
-+  x->fd = fd;
- 
--  len = socket_recv4(udp53,buf,sizeof buf,x->ip,&x->port);
-+  len = socket_recv4(x->fd,buf,sizeof buf,x->ip,&x->port);
-   if (len == -1) return;
-   if (len >= sizeof buf) return;
-   if (x->port < 1024) if (x->port != 53) return;
-@@ -129,8 +140,6 @@
- }
- 
- 
--static int tcp53;
--
- #define MAXTCP 20
- struct tcpclient {
-   struct query q;
-@@ -138,6 +147,7 @@
-   struct taia timeout;
-   uint64 active; /* query number or 1, if active; otherwise 0 */
-   iopause_fd *io;
-+  int fd;
-   char ip[4]; /* send response to this address */
-   uint16 port; /* send response to this port */
-   char id[2];
-@@ -266,7 +276,7 @@
-   x->state = 0;
- }
- 
--void t_new(void)
-+void t_new(int fd)
- {
-   int i;
-   int j;
-@@ -290,8 +300,9 @@
- 
-   x = t + j;
-   taia_now(&x->start);
-+  x->fd = fd;
- 
--  x->tcp = socket_accept4(tcp53,x->ip,&x->port);
-+  x->tcp = socket_accept4(x->fd,x->ip,&x->port);
-   if (x->tcp == -1) return;
-   if (x->port < 1024) if (x->port != 53) { close(x->tcp); return; }
-   if (!okclient(x->ip)) { close(x->tcp); return; }
-@@ -304,19 +315,24 @@
-   log_tcpopen(x->ip,x->port);
- }
- 
-+#define FATAL "dnscache: fatal: "
- 
--iopause_fd io[3 + MAXUDP + MAXTCP];
--iopause_fd *udp53io;
--iopause_fd *tcp53io;
-+iopause_fd *io = 0;
-+int numio;
- 
- static void doit(void)
- {
-   int j;
-   struct taia deadline;
-   struct taia stamp;
-+  struct interf *inter;
-   int iolen;
-   int r;
- 
-+  io = (iopause_fd *) alloc((numio + 1 + MAXUDP + MAXTCP) * sizeof(iopause_fd));
-+  if (!io)
-+    strerr_die2sys(111,FATAL,"unable to alloc io: ");
-+
-   for (;;) {
-     taia_now(&stamp);
-     taia_uint(&deadline,120);
-@@ -324,13 +340,15 @@
- 
-     iolen = 0;
- 
--    udp53io = io + iolen++;
--    udp53io->fd = udp53;
--    udp53io->events = IOPAUSE_READ;
--
--    tcp53io = io + iolen++;
--    tcp53io->fd = tcp53;
--    tcp53io->events = IOPAUSE_READ;
-+    for (inter = interhead; inter != 0; inter = inter->next) {
-+      inter->udp53io = io + iolen++;
-+      inter->udp53io->fd = inter->udp53;
-+      inter->udp53io->events = IOPAUSE_READ;
-+
-+      inter->tcp53io = io + iolen++;
-+      inter->tcp53io->fd = inter->tcp53;
-+      inter->tcp53io->events = IOPAUSE_READ;
-+    }
- 
-     for (j = 0;j < MAXUDP;++j)
-       if (u[j].active) {
-@@ -372,46 +390,82 @@
- 	    t_rw(j);
-       }
- 
--    if (udp53io)
--      if (udp53io->revents)
--	u_new();
--
--    if (tcp53io)
--      if (tcp53io->revents)
--	t_new();
-+    for (inter = interhead; inter != 0; inter = inter->next) {
-+      if (inter->udp53io)
-+        if (inter->udp53io->revents)
-+	  u_new(inter->udp53);
-+
-+      if (inter->tcp53io)
-+        if (inter->tcp53io->revents)
-+	  t_new(inter->tcp53);
-+    }
-   }
- }
-   
--#define FATAL "dnscache: fatal: "
--
- char seed[128];
- 
- int main()
- {
-   char *x;
-+  int len;
-+  int pos;
-+  int oldpos;
-+  char iptmp[4];
-+  char iperr[IP4_FMT];
-+  struct interf *inter;
-+  struct interf *itmp;
-   unsigned long cachesize;
- 
-   x = env_get("IP");
-   if (!x)
-     strerr_die2x(111,FATAL,"$IP not set");
--  if (!ip4_scan(x,myipincoming))
--    strerr_die3x(111,FATAL,"unable to parse IP address ",x);
- 
--  udp53 = socket_udp();
--  if (udp53 == -1)
--    strerr_die2sys(111,FATAL,"unable to create UDP socket: ");
--  if (socket_bind4_reuse(udp53,myipincoming,53) == -1)
--    strerr_die2sys(111,FATAL,"unable to bind UDP socket: ");
--
--  tcp53 = socket_tcp();
--  if (tcp53 == -1)
--    strerr_die2sys(111,FATAL,"unable to create TCP socket: ");
--  if (socket_bind4_reuse(tcp53,myipincoming,53) == -1)
--    strerr_die2sys(111,FATAL,"unable to bind TCP socket: ");
-+  len = str_len(x);
-+  numio = pos = oldpos = 0;
-+  
-+  while (pos < len) {
-+    if (pos) oldpos = pos + 1;
-+    pos = oldpos + str_chr(x + oldpos,'/');
-+    x[pos] = 0;
-+    if (!str_len(x + oldpos)) continue;
-+    
-+    if (!ip4_scan(x + oldpos,iptmp))
-+      strerr_die3x(111,FATAL,"unable to parse IP address ",x + oldpos);
-+      
-+    inter = (struct interf *) alloc(sizeof(struct interf));
-+    
-+    if (interhead == 0) interhead = inter;
-+    else if (interhead->next == 0) interhead->next = inter;
-+    else {
-+      for (itmp = interhead; itmp->next != 0; itmp = itmp->next);
-+      itmp->next = inter;
-+    }
-+    
-+    inter->next = 0;
-+    
-+    inter->udp53 = socket_udp();
-+    if (inter->udp53 == -1)
-+      strerr_die4sys(111,FATAL,"unable to create UDP socket for IP address ",x + oldpos,": ");
-+    if (socket_bind4_reuse(inter->udp53,iptmp,53) == -1)
-+      strerr_die4sys(111,FATAL,"unable to bind UDP socket for IP address ",x + oldpos,": ");
-+      
-+    inter->tcp53 = socket_tcp();
-+    if (inter->tcp53 == -1)
-+      strerr_die4sys(111,FATAL,"unable to create TCP socket for IP address ",x + oldpos,": ");
-+    if (socket_bind4_reuse(inter->tcp53,iptmp,53) == -1)
-+      strerr_die4sys(111,FATAL,"unable to bind TCP socket for IP address ",x + oldpos,": ");
-+      
-+    numio++;
-+    log_listen(iptmp);
-+  }
-+
-+  if (interhead == 0)
-+    strerr_die2x(111,FATAL,"no interfaces to listen on");
- 
-   droproot(FATAL);
- 
--  socket_tryreservein(udp53,131072);
-+  for (inter = interhead; inter != 0; inter = inter->next)
-+    socket_tryreservein(inter->udp53,131072);
- 
-   byte_zero(seed,sizeof seed);
-   read(0,seed,sizeof seed);
-@@ -439,8 +493,11 @@
-   if (!roots_init())
-     strerr_die2sys(111,FATAL,"unable to read servers: ");
- 
--  if (socket_listen(tcp53,20) == -1)
--    strerr_die2sys(111,FATAL,"unable to listen on TCP socket: ");
-+  for (inter = interhead; inter != 0; inter = inter->next)
-+    if (socket_listen(inter->tcp53,20) == -1) {
-+      iperr[ip4_fmt(iperr,inter->ip)] = 0;
-+      strerr_die4sys(111,FATAL,"unable to listen on TCP socket for IP ",iperr,": ");
-+    }
- 
-   log_startup();
-   doit();
---- djbdns-1.05.orig/log.c.orig	Tue Feb 27 00:33:02 2001
-+++ djbdns-1.05/log.c	Tue Feb 27 00:30:58 2001
-@@ -94,6 +94,13 @@
-   line();
- }
- 
-+void log_listen(const char addr[4])
-+{
-+  string("listening on ");
-+  ip(addr);
-+  line();
-+}
-+
- void log_query(uint64 *qnum,const char client[4],unsigned int port,const char id[2],const char *q,const char qtype[2])
- {
-   string("query "); number(*qnum); space();
---- djbdns-1.05.orig/log.h.orig	Tue Feb 27 00:33:09 2001
-+++ djbdns-1.05/log.h	Tue Feb 27 00:30:58 2001
-@@ -4,6 +4,7 @@
- #include "uint64.h"
- 
- extern void log_startup(void);
-+extern void log_listen(const char *);
- 
- extern void log_query(uint64 *,const char *,unsigned int,const char *,const char *,const char *);
- extern void log_querydrop(uint64 *);
Index: patches/280-dnscache-ignoreip2.patch
===================================================================
--- patches/280-dnscache-ignoreip2.patch	(revision 0)
+++ patches/280-dnscache-ignoreip2.patch	(revision 0)
@@ -0,0 +1,119 @@
+This patch change djbdns's dnscache program so that it will ignore the
+IP address given in the ignoreip file.  I wrote this patch because of
+Verisign's oh-so helpful wildcard A record for *.COM and *.NET.
+
+If you have djbdns-1.05-ignoreip.patch installed, back it out like this:
+    cd /usr/local/src/djbdns-1.05
+    patch -R <djbdns-1.05-ignoreip.patch
+
+Install the patch like this:
+    cd /usr/local/src/djbdns-1.05
+    patch <djbdns-1.05-ignoreip2.patch
+    svc -d /service/dnscache
+    make setup check
+    svc -u /service/dnscache
+
+Configure it to ignore Verisign's wildcard record like this:
+    echo 64.94.110.11 >/service/dnscache/root/ignoreip
+    svc -t /service/dnscache
+
+Configure it to ignore all the cretins like this:
+awk '{print $2}' <<EOF >/service/dnscache/root/ignoreip
+         *.ac            194.205.62.122
+         *.cc            206.253.214.102
+         *.com           64.94.110.11
+         *.cx            219.88.106.80
+         *.museum        195.7.77.20
+         *.net           64.94.110.11
+         *.nu            64.55.105.9
+                   and   212.181.91.6
+         *.ph            203.119.4.6
+         *.sh            194.205.62.62
+         *.tm            194.205.62.62
+         *.ws            216.35.187.246
+EOF
+    svc -t /service/dnscache
+
+J.P. Larocque contributes a script which updates root/ignoreip:
+    http://ely.ath.cx/~piranha/software/ignoreip-update/ignoreip-update-0.1
+
+If root/ignoreip is not present, no addresses will be ignored.
+
+--
+--My blog is at angry-economist.russnelson.com  | Free markets express in the
+Crynwr sells support for free software  | PGPok | practical world our belief
+521 Pleasant Valley Rd. | +1 315 268 1925 voice | that there is that of God
+Potsdam, NY 13676-3213  | +1 315 268 9201 FAX   | in all people. -Chris V.
+
+
+diff -u orig/dnscache.c ./dnscache.c
+--- orig/dnscache.c	2001-02-11 16:11:45.000000000 -0500
++++ ./dnscache.c	2003-09-16 23:23:36.000000000 -0400
+@@ -23,6 +23,8 @@
+ #include "okclient.h"
+ #include "droproot.h"
+ 
++stralloc ignoreip = {0};
++
+ static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2])
+ {
+   unsigned int pos;
+@@ -389,6 +391,7 @@
+ int main()
+ {
+   char *x;
++  unsigned int i, j, k;
+   unsigned long cachesize;
+ 
+   x = env_get("IP");
+@@ -431,6 +434,20 @@
+   if (!cache_init(cachesize))
+     strerr_die3x(111,FATAL,"not enough memory for cache of size ",x);
+ 
++  if (openreadclose("ignoreip",&ignoreip,64) < 0) 
++    strerr_die2x(111,FATAL,"trouble reading ignoreip");
++  for(j = k = i = 0; i < ignoreip.len; i++)
++    if (ignoreip.s[i] == '\n')  {
++      ignoreip.s[i] = '\0';
++      if (j + 4 > i)
++        strerr_die3x(111,FATAL,"badly malformed ip4 address ",ignoreip.s+k);
++      if (!ip4_scan(ignoreip.s+k,ignoreip.s+j))
++        strerr_die3x(111,FATAL,"unable to parse address in ignoreip ",ignoreip.s+k);
++      j += 4;
++      k = i + 1;
++    }
++  ignoreip.len = j;
++
+   if (env_get("HIDETTL"))
+     response_hidettl();
+   if (env_get("FORWARDONLY"))
+diff -u orig/query.c ./query.c
+--- orig/query.c	2001-02-11 16:11:45.000000000 -0500
++++ ./query.c	2003-09-16 23:31:41.000000000 -0400
+@@ -13,6 +13,8 @@
+ #include "response.h"
+ #include "query.h"
+ 
++extern stralloc ignoreip;
++
+ static int flagforwardonly = 0;
+ 
+ void query_forwardonly(void)
+@@ -163,6 +165,7 @@
+
+ static int doit(struct query *z,int state)
+ {
++  unsigned int ii;
+   char key[257];
+   char *cached;
+   unsigned int cachedlen;
+@@ -643,6 +646,9 @@
+         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
+         if (byte_equal(header + 8,2,"\0\4")) {
+           pos = dns_packet_copy(buf,len,pos,header,4); if (!pos) goto DIE;
++          if (ignoreip.len)
++	    for(ii = 0; ii < ignoreip.len; ii+= 4)
++	      if (byte_equal(header,4,ignoreip.s+ii)) goto NXDOMAIN;
+           save_data(header,4);
+           log_rr(whichserver,t1,DNS_T_A,header,4,ttl);
+         }

Property changes on: patches/280-dnscache-ignoreip2.patch
___________________________________________________________________
Added: svn:executable
   + *

Index: patches/320-bugfix-dnscache-cache-soa-records.patch
===================================================================
--- patches/320-bugfix-dnscache-cache-soa-records.patch	(revision 0)
+++ patches/320-bugfix-dnscache-cache-soa-records.patch	(revision 0)
@@ -0,0 +1,70 @@
+diff --git a/query.c b/query.c
+index 46cdc00..4574e97 100644
+--- a/query.c
++++ b/query.c
+@@ -319,6 +319,29 @@ static int doit(struct query *z,int state)
+       }
+     }
+ 
++    if (typematch(DNS_T_SOA,dtype)) {
++      byte_copy(key,2,DNS_T_SOA);
++      cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
++      if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
++        log_cachedanswer(d,DNS_T_SOA);
++        if (!rqa(z)) goto DIE;
++        pos = 0;
++        while (pos = dns_packet_copy(cached,cachedlen,pos,misc,20)) {
++          pos = dns_packet_getname(cached,cachedlen,pos,&t2);
++          if (!pos) break;
++          pos = dns_packet_getname(cached,cachedlen,pos,&t3);
++          if (!pos) break;
++          if (!response_rstart(d,DNS_T_SOA,ttl)) goto DIE;
++          if (!response_addname(t2)) goto DIE;
++          if (!response_addname(t3)) goto DIE;
++          if (!response_addbytes(misc,20)) goto DIE;
++          response_rfinish(RESPONSE_ANSWER);
++        }
++        cleanup(z);
++        return 1;
++      }
++    }
++
+     if (typematch(DNS_T_A,dtype)) {
+       byte_copy(key,2,DNS_T_A);
+       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+@@ -351,7 +374,7 @@ static int doit(struct query *z,int state)
+       }
+     }
+ 
+-    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
++    if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_SOA,dtype)) {
+       byte_copy(key,2,dtype);
+       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
+@@ -585,15 +608,24 @@ static int doit(struct query *z,int state)
+     else if (byte_equal(type,2,DNS_T_AXFR))
+       ;
+     else if (byte_equal(type,2,DNS_T_SOA)) {
++      int non_authority = 0;
++      save_start();
+       while (i < j) {
+         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
+         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
+         pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE;
+         pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE;
+-        if (records[i] < posauthority)
++        if (records[i] < posauthority) {
+           log_rrsoa(whichserver,t1,t2,t3,misc,ttl);
++          save_data(misc,20);
++          save_data(t2,dns_domain_length(t2));
++          save_data(t3,dns_domain_length(t3));
++          non_authority++;
++        }
+         ++i;
+       }
++      if (non_authority)
++        save_finish(DNS_T_SOA,t1,ttl);
+     }
+     else if (byte_equal(type,2,DNS_T_CNAME)) {
+       pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE;
+
Index: patches/300-bugfix1-dempsky.patch
===================================================================
--- patches/300-bugfix1-dempsky.patch	(revision 16393)
+++ patches/300-bugfix1-dempsky.patch	(working copy)
@@ -1,11 +0,0 @@
---- a/response.c.orig	2009-02-24 21:04:06.000000000 -0800
-+++ b/response.c	2009-02-24 21:04:25.000000000 -0800
-@@ -34,7 +34,7 @@
-         uint16_pack_big(buf,49152 + name_ptr[i]);
-         return response_addbytes(buf,2);
-       }
--    if (dlen <= 128)
-+    if ((dlen <= 128) && (response_len < 16384))
-       if (name_num < NAMES) {
- 	byte_copy(name[name_num],dlen,d);
- 	name_ptr[name_num] = response_len;
Index: Changelog
===================================================================
--- Changelog	(revision 16393)
+++ Changelog	(working copy)
@@ -1,5 +1,24 @@
 #Changelog for the djbdns port for OpenWRT
 
+5 20090522 jhalfmoon
+enhancement - added patch: dnsroots_updated
+enhancement - added patch: tinydns_one_second
+enhancement - added patch: srv-records-and-axfrget
+enhancement - added patch: dnscache_less_chatty_log
+enhancement - added patch: tinydns_mmap_leak
+enhancement - added patch: dnscache_dpos_tcp_servfail
+enhancement - added patch: dnscache_negative_ttls
+enhancement - added patch: dnscache_sigpipe_fix
+enhancement - added patch: dnscache_big_udp_packets
+enhancement - added patch: dnscache_ignoreip2 (Note: disabled in config by default!)
+enhancement - added HIDETTL config option
+change - Corrected a typo in the axfrdns description in the Makefile.
+change - Cleaned up some lines in the Makefile
+change - dnsroots.global now gets copied from the djbdns source folder instead of from the package/files folder.
+change - The dnscache-multiple-ip patch was removed as it served no purpose
+change - Renamed a few patches to be more consistent with the other patches
+change - Updated the README file to reflect the changes 
+
 4 20090418 jhalfmoon
 bugfix - The dnscache postinst script had a bug that prevented djbdns from being compiled into a firmware image.
 bugfix - The dnscache startup script now uses /dev/urandom instead of /dev/random as a source of randomness. Using /dev/random does not work on 2.6 kernels.
Index: Makefile
===================================================================
--- Makefile	(revision 16393)
+++ Makefile	(working copy)
@@ -13,7 +13,7 @@
 
 PKG_NAME:=djbdns
 PKG_VERSION:=1.05
-PKG_RELEASE:=4
+PKG_RELEASE:=5
 
 PKG_SOURCE:=${PKG_NAME}-${PKG_VERSION}.tar.gz
 PKG_SOURCE_URL:=http://cr.yp.to/djbdns/
@@ -100,7 +100,7 @@
 
 define Package/djbdns-axfrdns/description
 	axfrdns is a DNS zone-transfer server.
-	It reads a zone-transfer request in DNS-over-TINSTALL_DATA format
+	It reads a zone-transfer request in DNS-over-TCP format
        	from its standard input and responds with locally configured
 	information. 
 endef
@@ -138,19 +138,20 @@
 define Package/djbdns-dnscache/install
 	$(INSTALL_DIR) $(1)/usr/bin
 	(cd $(PKG_BUILD_DIR); \
-	$(INSTALL_BIN) dnscache pickdns pickdns-data \
-	$(1)/usr/bin)
-	$(INSTALL_DIR) $(1)/etc
-	$(CP) -r ./files/dnscache $(1)/etc/
+	$(INSTALL_BIN) dnscache pickdns pickdns-data $(1)/usr/bin)
 	$(INSTALL_DIR) $(1)/etc/init.d
 	$(INSTALL_BIN) ./files/dnscache.init $(1)/etc/init.d/dnscache
+	$(CP) -r ./files/dnscache $(1)/etc/
+	$(CP) $(PKG_BUILD_DIR)/dnsroots.global $(1)/etc/dnscache/
+	$(INSTALL_DIR) $(1)/etc/dnscache/ip
+	$(INSTALL_DIR) $(1)/etc/dnscache/servers
+	$(CP) $(PKG_BUILD_DIR)/dnsroots.global $(1)/etc/dnscache/servers/@
 endef
 
 define Package/djbdns-tinydns/install
 	$(INSTALL_DIR) $(1)/usr/bin
 	(cd $(PKG_BUILD_DIR); \
-	$(INSTALL_BIN) tinydns tinydns-data tinydns-edit tinydns-get \
-	$(1)/usr/bin)
+	$(INSTALL_BIN) tinydns tinydns-data tinydns-edit tinydns-get $(1)/usr/bin)
 	$(INSTALL_DIR) $(1)/etc/init.d
 	$(INSTALL_BIN) ./files/tinydns.init $(1)/etc/init.d/tinydns
 	$(CP) -r ./files/tinydns $(1)/etc/
@@ -159,8 +160,7 @@
 define Package/djbdns-axfrdns/install
 	$(INSTALL_DIR) $(1)/usr/bin
 	(cd $(PKG_BUILD_DIR); \
-	$(INSTALL_BIN) axfrdns axfr-get \
-	$(1)/usr/bin)
+	$(INSTALL_BIN) axfrdns axfr-get $(1)/usr/bin)
 	$(INSTALL_DIR) $(1)/etc/init.d
 	$(INSTALL_BIN) ./files/axfrdns.init $(1)/etc/init.d/axfrdns
 	$(CP) -r ./files/axfrdns $(1)/etc/
@@ -169,8 +169,7 @@
 define Package/djbdns-rbldns/install
 	$(INSTALL_DIR) $(1)/usr/bin
 	(cd $(PKG_BUILD_DIR); \
-	$(INSTALL_BIN) rbldns rbldns-data \
-	$(1)/usr/bin)
+	$(INSTALL_BIN) rbldns rbldns-data $(1)/usr/bin)
 	$(INSTALL_DIR) $(1)/etc/init.d
 	$(INSTALL_BIN) ./files/rbldns.init $(1)/etc/init.d/rbldns
 	$(CP) -r ./files/rbldns $(1)/etc/
@@ -179,8 +178,7 @@
 define Package/djbdns-walldns/install
 	$(INSTALL_DIR) $(1)/usr/bin
 	(cd $(PKG_BUILD_DIR); \
-	$(INSTALL_BIN) walldns \
-	$(1)/usr/bin)
+	$(INSTALL_BIN) walldns $(1)/usr/bin)
 	$(INSTALL_DIR) $(1)/etc/init.d
 	$(INSTALL_BIN) ./files/walldns.init $(1)/etc/init.d/walldns
 endef
Index: README
===================================================================
--- README	(revision 16393)
+++ README	(working copy)
@@ -62,9 +62,11 @@
 - Starting the init.d scripts from the command line with the environment variable DEBUG set to 1 will prevent the servers from daemonizing and show the servers's log dumped to stdout / stderr instead of /dev/null. Example: "DEBUG=1 /etc/init.d/dnscache start"
 - By default, all logging is disabled. Each daemon has a seperate option to activate logging. When logging activated the daemon logs to syslog using facility local1.info.
 - Each djbdns server requires an IP address on which to listen on. This port of djbdns allows you to define an interface on which to listen instead of an IP address. The advantage of this is that an interface can get a different IP address assigned, the djbdns stuff will not break. The dnscache server has a patch applied so that it is possible to define multiple interfaces on which to listen, separated by slashes. Example: wan/lan .
-- By default, dnscache acts as a recursive name server. If you wish to operate in forwardonly mode, then you need to set the forwardonly flag to '1'. Then you need to do either one of the following: Put the ip addresses of the name servers you wish to use as resolvers in the UCI config (djbdns.dnscache.resolver) or alternatively you can set the useresolvconf flag which will cause the dns servers assigned by dhcp to be used.
+- By default, dnscache acts as a recursive name server. If you wish to operate in forwardonly mode, then you need to set the forwardonly flag to '1'. Then you need to do either one of the following: Put the ip addresses of the name servers you wish to use as resolvers in the UCI config (djbdns.dnscache.resolver) or alternatively you can set the useresolvconf flag which will cause the dns servers assigned by dhcp to be used. That last option is a so called set-and-forget mode which will work quite well in most home environments.
 - If you want your OpenWRT machine to make use of its own dnscache, then you must make /etc/resolv.conf reflect this. One way of doin this is as follows: uci set network.wan.dns=127.0.0.1 . If you have dnscache listening on some other interface, you would naturally replace 127.0.0.1 by the address of that interface.
 - OpenWRT has several applications that can do DNS serving in one way or another (dnsmasq, Maradns, Bind). Make sure you have none of these apps running when you start running a djbdns name server because having two DNS apps listening on the same address is not something you would usually want. A patch for the dnsmasq configuration script and its config file is included with this package. The patch will allow you to configure dnsmasq to listen only on certain interfaces, instead of on all them as it does by default on OpenWRT. Alternatively, you could completely disable and / or remove dnsmasq, if you do not intend to use any of its functionality (which is serving DNS and DHCP).
+- The ignoreip patch also has a script supplied along with it, with which you can update the ignorelist. The script contains an explanation of why you might want to do this.
+- The ignoreip functionality is disabled by default. If you want to activate it, you need to set the flag 'useignore' flag to '1' in the config. You might also want to check if you are really blocking what you want to block. Be careful with this feature. Think twice before using it.
 
 To apply the dnsmasq patch
 ==========================
@@ -204,65 +206,104 @@
 
 Applied patches
 ===============
-100-crosscompile.patch
+crosscompile.patch
 https://dev.openwrt.org/ticket/2497
 Patch to make djbdns compile correctly for OpenWRT. I understand that the original patch comes from FreeWRT and was adapted for OpenWRT by Alexander Tsvyashchenko.
 
-110-cachestats.patch
+dnsroots-update.patch
+Update the dnsroots.global file to be current.
+
+srv-records-and-axfrget.patch
+http://sol.truespace.ca/Files/djbdns/srv.patch
+Adds native support for srv records (not really necessary) and also patches axfr-get to decompose SRV and PTR records and write them out in native format, rather than opaque. This last thing is needed to fix a possible problem with tinydns-data.
+
+dnscache_less_chatty_log
+http://sol.truespace.ca/Files/djbdns/log.patch
+Makes dnscache log "stat" entries no more than once per 5 seconds.
+
+tinydns_mmap_leak
+http://marc.info/?l=djbdns&m=116399640808774&w=2
+This fixes the following: In the original code if cdb_read encountered an error it returned an error code and the calling function exited without closing the cdb data file resulting in an fd leak, eventually leading to a 'too many files open' error.
+
+dnscache_big_udp_packets
+http://marc.info/?l=djbdns&m=122368590802063&w=2
+Patch to support oversized UDP packets up to 4096 bytes in length, while still correctly truncating responses over 512 bytes when sending them to stub resolvers.
+
+dnscache_dpos_tcp_servfail
+http://marc.info/?l=djbdns&m=119998909915985&w=3
+Fixes broken tcp dns queries in certain situations. For example: A vanilla 1.05 will fail on "dnstxt aol.com aol.com".
+
+dnscache-cache-negatives
+http://sol.truespace.ca/Files/djbdns/nxdomain.patch
+Add support for caching of unsuccessful lookup results.
+
+tinydns_one_second
+http://www.tinydns.org/one-second.patch
+Causes tinydns to keep its mmap() of the data.cdb file open for at most one second, instead of the default one hundred queries. This improves throughput on high traffic machines.
+
+dnscache-cachestats.patch
 http://romana.now.ie/#djbdns-cachestats
 This patch modifies the dnscache program to keep a counter of cache hits and cache misses. Two new fields are added to the stats output line: the fifth number is the number of cache hits; the sixth number is the number of cache misses.
 
-120-compiler-temporary-filename.patch
+compiler-temporary-filename.patch
 http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/#compiler-temporary-filename
 A bit of a nit-picky patch that adjusts the names of generated temorary files to be more 'correct'. A bit silly really.
 
-130-dnscache-multiple-ip.patch
+dnscache-multiple-ip.patch
 http://danp.net/djbdns/patches.html
-When applied, dnscache will accept a /-delimited list of IP address in $IP and bind to each in turn. NOTE: This patch is only really useful on embedded systems with very limited memory. On 'big' systems, ther are other ways to achieve listening on multiple IP adresses. Example: http://www.faqts.com/knowledge_base/view.phtml/aid/9644/fid/699
+When applied, dnscache will accept a /-delimited list of IP address in $IP and bind to each in turn. NOTE: This patch is only really useful on embedded systems with very limited memory. On big systems, ther are other ways to achieve listening on multiple IP adresses. You can read more on that over here: http://www.faqts.com/knowledge_base/view.phtml/aid/9644/fid/699
 
-140-dnsnamex-extra-command.patch
+dnsnamex-extra-command.patch
 http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/#dnsnamex
 Not really a patch, but an extra command. dnsnamex prints all of the domain names that the IP address supplied to it maps to, on a single line.
 
-200-dnscache-cname-handling.patch
+dnscache-cname-handling.patch
 http://homepages.tesco.net/~J.deBoynePollard/FGA/#DNS
 Fixes mis-handling of client-side aliases
 
-210-dnscache-strict-forwardonly.patch
+dnscache-strict-forwardonly.patch
 http://homepages.tesco.net/~J.deBoynePollard/Softwares/djbdns/#dnscache-strict-forwardonly
 This patch modifies the behaviour of dnscache such that "forwardonly" mode is fully enforced.
 
-220-dnscacheip-space-separator.patch
+dnscacheip-space-separator.patch
 http://homepages.tesco.net/~J.deBoynePollard/FGA/djbdns-problems.html#dnscacheip-separator-character
 Patch to change the separator in ${DNSCACHEIP} to the space character
 
-230-tinydns-data-semantic-error.patch
+tinydns-data-semantic-error.patch
 http://homepages.tesco.net/~J.deBoynePollard/FGA/djbdns-problems.html#tinydns-data-semantic-error
 Fixes the fact that stock tinydns-data doesn't handle semantic errors in its input
 
-240-tinydns-alias-chain-truncation.patch
+tinydns-alias-chain-truncation.patch
 http://homepages.tesco.net/~J.deBoynePollard/FGA/djbdns-problems.html#tinydns-alias-chain-truncation
 Fixes truncation of alias chains by tinydns and axfrdns
 
-250-djbdns-1.05-slogging.patch
+dnscache-slogging.patch
 http://www.ohse.de/uwe/patches.html
 Patch to enable statistics logging of queried resource records.
 This patch is merged with the patch server-1.05-nxdomain-logging.patch that logs nxdomain queries.
 http://danp.net/djbdns/
 
-260-djbdns-1.05-dnsfilter-replace.patch
+dnsfilter-replace.patch
 http://www.ohse.de/uwe/patches.html
 This patch adds an option to the dnsfilter program (-r). It's use makes dnsfilter simply replace the IP address by the host name if possible. If the IP address cannot be determined for whatever reason then it will be left alone. -r stands for replace. 
 
-300-bugfix1-dempsky.patch
+dnscache_sigpipe_fix
+http://marc.info/?l=djbdns&m=104804013229536&w=2
+This patch tells dnscache to ignore the SIGPIPE signal.
+
+ignoreip2.patch
+http://tinydns.org/djbdns-1.05-ignoreip2.patch
+This patch change djbdns's dnscache so that it will ignore thex IP addresses given in the ignoreip file. This patch was made to boycott Verisign, amongst others, who decided to start supplying replies to non-existant and wildcard domains. NOTE: This feature is disabled in the config file by default. Be careful with this one.
+
+bugfix-dnscache-dempsky-poison.patch
 http://www.securityfocus.com/archive/1/501294/30/0/threaded
 Patch to fix a potential cache-poisoning attack. This bug only affects domains that serve DNS content using tinydns and axfrdns (only for DNS queries over TCP; clients do not need AXFR permissions) from djbdns 1.05 and allow untrusted users to include arbitrary records.
 
-310-bugfix2-merge-outgoing-requests.patch
+bugfix-dnscache-merge-outgoing-requests.patch
 http://www.your.org/dnscache/
 This patch prevents a class of poisoning attack by combining identical requests from clients into one outgoing query. Without this patch, an attacker can coerce dnscache into launching hundreds of identical queries at once, making a specific type of attack several orders of magnitude easier. 
 
-320-bugfix3-cache-soa-records.patch
+bugfix-dnscache-cache-soa-records.patch
 http://www.your.org/dnscache/
 This patch allows dnscache to store the responses of "SOA" type queries in its cache. SOA responses are the only type of response unconditionally uncached. dnscache uses its internal cache to prevent certain classes of poisoning attack. Attackers may choose to send floods of SOA requests to bypass these protections. 




More information about the openwrt-devel mailing list