diff options
Diffstat (limited to 'main/djbdns/djbdns-1.05-jumbo-josb.patch')
-rw-r--r-- | main/djbdns/djbdns-1.05-jumbo-josb.patch | 1858 |
1 files changed, 1858 insertions, 0 deletions
diff --git a/main/djbdns/djbdns-1.05-jumbo-josb.patch b/main/djbdns/djbdns-1.05-jumbo-josb.patch new file mode 100644 index 0000000000..c1a685aef4 --- /dev/null +++ b/main/djbdns/djbdns-1.05-jumbo-josb.patch @@ -0,0 +1,1858 @@ +Downloaded from: +http://lizzy.dyndns.org/~jos/djbdns-1.05-jumbo-josb.patch + +This patch combines the following patches: +- Claudiu Costin's jumbo-p13.patch + http://www.ro.kde.org/djbdns/mywork/jumbo/jumbo-p13.patch.gz +- Guilherme Balena Versiani's djbdns SRV+NAPTR combined patch + http://mywebpage.netscape.com/guibv/djbdns-1.05-srvnaptr.diff + +diff -ruN djbdns-1.05-dist/CHANGES djbdns-1.05/CHANGES +--- djbdns-1.05-dist/CHANGES 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/CHANGES 2008-08-11 19:33:30.000000000 -0700 +@@ -374,3 +374,5 @@ + ui: servers print starting message. + internal: some respond() declarations. + version: djbdns 1.05. ++20010313 ++ patch: to dump and reload the cache +diff -ruN djbdns-1.05-dist/Makefile djbdns-1.05/Makefile +--- djbdns-1.05-dist/Makefile 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/Makefile 2008-08-11 19:33:30.000000000 -0700 +@@ -4,6 +4,8 @@ + + default: it + ++include Makefile.sig ++ + alloc.a: \ + makelib alloc.o alloc_re.o getln.o getln2.o stralloc_cat.o \ + stralloc_catb.o stralloc_cats.o stralloc_copy.o stralloc_eady.o \ +@@ -149,13 +151,13 @@ + + cache.o: \ + compile cache.c alloc.h byte.h uint32.h exit.h tai.h uint64.h cache.h \ +-uint32.h uint64.h ++uint32.h uint64.h env.h error.h open.h openreadclose.h + ./compile cache.c + + cachetest: \ +-load cachetest.o cache.o libtai.a buffer.a alloc.a unix.a byte.a +- ./load cachetest cache.o libtai.a buffer.a alloc.a unix.a \ +- byte.a ++load cachetest.o cache.o libtai.a buffer.a alloc.a unix.a byte.a env.a ++ ./load cachetest cache.o libtai.a buffer.a unix.a env.a \ ++ alloc.a byte.a dns.a + + cachetest.o: \ + compile cachetest.c buffer.h exit.h cache.h uint32.h uint64.h str.h +@@ -228,11 +230,11 @@ + 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 \ +-dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o ++dns_resolve.o dns_rotateip.o dns_sortip.o dns_transmit.o dns_txt.o + ./makelib dns.a 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 dns_resolve.o \ +- dns_sortip.o dns_transmit.o dns_txt.o ++ dns_rotateip.o dns_sortip.o dns_transmit.o dns_txt.o + + dns_dfd.o: \ + compile dns_dfd.c error.h alloc.h byte.h dns.h stralloc.h gen_alloc.h \ +@@ -301,6 +303,10 @@ + dns.h stralloc.h gen_alloc.h iopause.h taia.h + ./compile dns_resolve.c + ++dns_rotateip.o: \ ++compile dns_rotateip.c byte.h dns.h stralloc.h gen_alloc.h ++ ./compile dns_rotateip.c ++ + dns_sortip.o: \ + compile dns_sortip.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \ + taia.h tai.h uint64.h taia.h +@@ -320,10 +326,10 @@ + dnscache: \ + load dnscache.o droproot.o okclient.o log.o cache.o query.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 ++libtai.a unix.a byte.a sig.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 \ +- env.a alloc.a buffer.a libtai.a unix.a byte.a `cat \ ++ env.a alloc.a buffer.a libtai.a unix.a byte.a sig.a `cat \ + socket.lib` + + dnscache-conf: \ +@@ -626,9 +632,9 @@ + ./compile parsetype.c + + pickdns: \ +-load pickdns.o server.o response.o droproot.o qlog.o prot.o dns.a \ ++load pickdns.o server.o iopause.o response.o droproot.o qlog.o prot.o dns.a \ + env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib +- ./load pickdns server.o response.o droproot.o qlog.o \ ++ ./load pickdns server.o iopause.o response.o droproot.o qlog.o \ + prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \ + byte.a `cat socket.lib` + +@@ -704,9 +710,9 @@ + ./compile random-ip.c + + rbldns: \ +-load rbldns.o server.o response.o dd.o droproot.o qlog.o prot.o dns.a \ ++load rbldns.o server.o iopause.o response.o dd.o droproot.o qlog.o prot.o dns.a \ + env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib +- ./load rbldns server.o response.o dd.o droproot.o qlog.o \ ++ ./load rbldns server.o iopause.o response.o dd.o droproot.o qlog.o \ + prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \ + byte.a `cat socket.lib` + +@@ -774,7 +780,7 @@ + compile server.c byte.h case.h env.h buffer.h strerr.h ip4.h uint16.h \ + ndelay.h socket.h uint16.h droproot.h qlog.h uint16.h response.h \ + uint32.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h uint64.h \ +-taia.h ++taia.h iopause.h alloc.h + ./compile server.c + + setup: \ +@@ -979,10 +985,10 @@ + ./compile timeoutwrite.c + + tinydns: \ +-load tinydns.o server.o droproot.o tdlookup.o response.o qlog.o \ ++load tinydns.o server.o iopause.o droproot.o tdlookup.o response.o qlog.o \ + prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \ + socket.lib +- ./load tinydns server.o droproot.o tdlookup.o response.o \ ++ ./load tinydns server.o iopause.o droproot.o tdlookup.o response.o \ + qlog.o prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \ + unix.a byte.a `cat socket.lib` + +@@ -1084,10 +1090,10 @@ + ./compile utime.c + + walldns: \ +-load walldns.o server.o response.o droproot.o qlog.o prot.o dd.o \ ++load walldns.o server.o iopause.o response.o droproot.o qlog.o prot.o dd.o \ + dns.a env.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib +- ./load walldns server.o response.o droproot.o qlog.o \ +- prot.o dd.o dns.a env.a cdb.a alloc.a buffer.a unix.a \ ++ ./load walldns server.o iopause.o response.o droproot.o qlog.o \ ++ prot.o dd.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a \ + byte.a `cat socket.lib` + + walldns-conf: \ +diff -ruN djbdns-1.05-dist/Makefile.sig djbdns-1.05/Makefile.sig +--- djbdns-1.05-dist/Makefile.sig 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/Makefile.sig 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,27 @@ ++sig.o: \ ++compile sig.c sig.h ++ ./compile sig.c ++ ++sig_block.o: \ ++compile sig_block.c sig.h hassgprm.h ++ ./compile sig_block.c ++ ++sig_catch.o: \ ++compile sig_catch.c sig.h hassgact.h ++ ./compile sig_catch.c ++ ++sig_pause.o: \ ++compile sig_pause.c sig.h hassgprm.h ++ ./compile sig_pause.c ++ ++sig.a: \ ++makelib sig.o sig_block.o sig_catch.o sig_pause.o ++ ./makelib sig.a sig.o sig_block.o sig_catch.o sig_pause.o ++ ++hassgact.h: \ ++choose compile load trysgact.c hassgact.h1 hassgact.h2 ++ ./choose cl trysgact hassgact.h1 hassgact.h2 > hassgact.h ++ ++hassgprm.h: \ ++choose compile load trysgprm.c hassgprm.h1 hassgprm.h2 ++ ./choose cl trysgprm hassgprm.h1 hassgprm.h2 > hassgprm.h +diff -ruN djbdns-1.05-dist/README djbdns-1.05/README +--- djbdns-1.05-dist/README 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/README 2008-08-11 19:33:30.000000000 -0700 +@@ -1,3 +1,9 @@ ++patchlevel fg1 ++20010313 ++by Florent Guillaume <florent.guillaume@mail.com> ++patch home page: http://mapage.noos.fr/efgeor/djbdns/index.html ++Uses parts of Felix von Leitner's djb-0.5.2 package: http://www.fefe.de/djb/ ++ + djbdns 1.05 + 20010211 + Copyright 2001 +diff -ruN djbdns-1.05-dist/SYSDEPS djbdns-1.05/SYSDEPS +--- djbdns-1.05-dist/SYSDEPS 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/SYSDEPS 2008-08-11 19:33:30.000000000 -0700 +@@ -7,4 +7,6 @@ + direntry.h + hasshsgr.h + hasdevtcp.h ++hassgact.h ++hassgprm.h + socket.lib +diff -ruN djbdns-1.05-dist/TARGETS djbdns-1.05/TARGETS +--- djbdns-1.05-dist/TARGETS 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/TARGETS 2008-08-11 19:33:30.000000000 -0700 +@@ -214,3 +214,10 @@ + it + setup + check ++sig.o ++sig.a ++sig_catch.o ++sig_block.o ++hassgact.h ++hassgprm.h ++sig_pause.o +diff -ruN djbdns-1.05-dist/VERSION djbdns-1.05/VERSION +--- djbdns-1.05-dist/VERSION 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/VERSION 2008-08-11 19:33:30.000000000 -0700 +@@ -1 +1 @@ +-djbdns 1.05 ++djbdns 1.05-fg1 +diff -ruN djbdns-1.05-dist/auto_home.c djbdns-1.05/auto_home.c +--- djbdns-1.05-dist/auto_home.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/auto_home.c 2008-08-12 09:17:21.000000000 -0700 +@@ -0,0 +1,3 @@ ++const char auto_home[] = "\ ++\057\165\163\162\057\154\157\143\141\154\ ++"; +diff -ruN djbdns-1.05-dist/axfr-get.c djbdns-1.05/axfr-get.c +--- djbdns-1.05-dist/axfr-get.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/axfr-get.c 2008-08-11 22:49:05.000000000 -0700 +@@ -209,6 +209,57 @@ + if (!stralloc_cats(&line,".:")) return 0; + if (!stralloc_catulong0(&line,dist,0)) return 0; + } ++ else if (byte_equal(data,2,DNS_T_SRV)) { ++ uint16 priority, 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,&priority); ++ 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,port,0)) return 0; ++ if (!stralloc_cats(&line,":")) return 0; ++ if (!stralloc_catulong0(&line,priority,0)) return 0; ++ if (!stralloc_cats(&line,":")) return 0; ++ if (!stralloc_catulong0(&line,weight,0)) return 0; ++ } ++ else if (byte_equal(data,2,DNS_T_NAPTR)) { ++ uint16 order, preference; ++ char flags[255], service[255], regexp[255]; ++ char fs, ss, rs; ++ if (!stralloc_copys(&line,"N")) 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,&order); ++ pos = x_copy(buf,len,pos,data,2); ++ uint16_unpack_big(data,&preference); ++ pos = x_copy(buf,len,pos,&fs,1); ++ pos = x_copy(buf,len,pos,flags,fs); ++ pos = x_copy(buf,len,pos,&ss,1); ++ pos = x_copy(buf,len,pos,service,ss); ++ pos = x_copy(buf,len,pos,&rs,1); ++ pos = x_copy(buf,len,pos,regexp,rs); ++ x_getname(buf,len,pos,&d1); ++ if (!stralloc_catulong0(&line,order,0)) return 0; ++ if (!stralloc_cats(&line,":")) return 0; ++ if (!stralloc_catulong0(&line,preference,0)) return 0; ++ if (!stralloc_cats(&line,":")) return 0; ++ if (!stralloc_catb(&line,flags,fs)) return 0; ++ if (!stralloc_cats(&line,":")) return 0; ++ if (!stralloc_catb(&line,service,ss)) return 0; ++ if (!stralloc_cats(&line,":")) return 0; ++ if (!stralloc_catb(&line,regexp,rs)) return 0; ++ if (!stralloc_cats(&line,":")) return 0; ++ if (!dns_domain_todot_cat(&line,d1)) return 0; ++ if (!stralloc_cats(&line,".")) return 0; ++ } + else if (byte_equal(data,2,DNS_T_A) && (dlen == 4)) { + char ipstr[IP4_FMT]; + if (!stralloc_copys(&line,"+")) return 0; +@@ -217,6 +268,14 @@ + 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; + unsigned char ch2; +diff -ruN djbdns-1.05-dist/cache.c djbdns-1.05/cache.c +--- djbdns-1.05-dist/cache.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/cache.c 2008-08-11 19:33:30.000000000 -0700 +@@ -1,12 +1,23 @@ ++#ifdef DUMPCACHE ++#include <stdio.h> ++#include <unistd.h> ++#include "env.h" ++#include "error.h" ++#include "open.h" ++#include "openreadclose.h" ++#endif + #include "alloc.h" + #include "byte.h" + #include "uint32.h" + #include "exit.h" + #include "tai.h" + #include "cache.h" ++#include "dns.h" ++#include "buffer.h" + + uint64 cache_motion = 0; + ++static char *rrobin; + static char *x = 0; + static uint32 size; + static uint32 hsize; +@@ -87,6 +98,12 @@ + uint32 u; + unsigned int loop; + double d; ++ static int trigger=0; ++ ++ if (!trigger) { ++ rrobin = env_get("ROUNDROBIN"); ++ trigger++; ++ } + + if (!x) return 0; + if (keylen > MAXKEYLEN) return 0; +@@ -111,7 +128,11 @@ + u = get4(pos + 8); + if (u > size - pos - 20 - keylen) cache_impossible(); + *datalen = u; +- ++ if (byte_equal(key,2,DNS_T_A)) { ++ if (rrobin) { ++ dns_rotateip(x + pos + 20 + keylen,u); ++ } ++ } + return x + pos + 20 + keylen; + } + } +@@ -205,3 +226,97 @@ + + return 1; + } ++ ++#ifdef DUMPCACHE ++static int fd; ++ ++static int cache_writeline(const char *buf, unsigned int len) ++{ ++ int w; ++ ++ while (len) { ++ w = write(fd,buf,len); ++ if (w == -1) { ++ if (errno == error_intr) continue; ++ close(fd); ++ return -1; ++ } ++ buf += w; ++ len -= w; ++ } ++ return 0; ++} ++ ++int cache_dump(void) ++{ ++ static char *fn; ++ static char *fntmp; ++ uint32 pos; ++ unsigned int len; ++ ++ fn = env_get("DUMPCACHE"); ++ if (!fn) return 999; ++ fntmp = env_get("DUMPCACHETMP"); ++ if (!fntmp) return 999; ++ fd = open_trunc(fntmp); ++ if (fd == -1) return -1; ++ ++ pos = oldest; ++ while (pos < unused) { ++ len = get4(pos + 4) + get4(pos + 8) + 16; ++ if (cache_writeline(x + pos + 4, len)) return -1; ++ pos += 4 + len; ++ } ++ pos = hsize; ++ while (pos < writer) { ++ len = get4(pos + 4) + get4(pos + 8) + 16; ++ if (cache_writeline(x + pos + 4, len)) return -1; ++ pos += 4 + len; ++ } ++ ++ if (fsync(fd) == -1) return -1; ++ if (close(fd) == -1) return -1; ++ if (rename(fntmp,fn) == -1) return -1; ++ return 0; ++} ++ ++int cache_slurp(const char *fn) ++{ ++ static stralloc buf = {0}; ++ char *p; ++ uint32 pos; ++ unsigned int len; ++ uint32 keylen; ++ uint32 datalen; ++ struct tai now; ++ struct tai expire; ++ int nb; ++ ++ if (openreadclose(fn,&buf,16384) != 1) goto DIE; ++ tai_now(&now); ++ p = buf.s; ++ pos = 0; ++ len = buf.len; ++ nb = 0; ++ while (pos + 16 <= len) { ++ uint32_unpack(p + pos, &keylen); ++ uint32_unpack(p + pos + 4, &datalen); ++ tai_unpack(p + pos + 8, &expire); ++ pos += 16; ++ if (pos + keylen + datalen > len) break; /* missing data */ ++ if (!tai_less(&expire,&now)) { ++ tai_sub(&expire,&expire,&now); ++ cache_set(p + pos, keylen, p + pos + keylen, datalen, (unsigned int)expire.x); ++ } ++ pos += keylen + datalen; ++ nb++; ++ } ++ alloc_free(buf.s); buf.s = 0; ++ return nb; ++ ++ DIE: ++ alloc_free(buf.s); buf.s = 0; ++ if (errno == error_noent) return 0; ++ return -1; ++} ++#endif +diff -ruN djbdns-1.05-dist/cache.h djbdns-1.05/cache.h +--- djbdns-1.05-dist/cache.h 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/cache.h 2008-08-11 19:33:30.000000000 -0700 +@@ -8,5 +8,9 @@ + 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 *); ++#ifdef DUMPCACHE ++extern int cache_dump(void); ++extern int cache_slurp(const char *); ++#endif + + #endif +diff -ruN djbdns-1.05-dist/chkshsgr.c djbdns-1.05/chkshsgr.c +--- djbdns-1.05-dist/chkshsgr.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/chkshsgr.c 2008-08-11 19:33:30.000000000 -0700 +@@ -1,4 +1,6 @@ + #include "exit.h" ++#include <grp.h> ++#include <unistd.h> + + int main() + { +diff -ruN djbdns-1.05-dist/direntry.h djbdns-1.05/direntry.h +--- djbdns-1.05-dist/direntry.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/direntry.h 2008-08-11 22:55:14.000000000 -0700 +@@ -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 -ruN djbdns-1.05-dist/dns.h djbdns-1.05/dns.h +--- djbdns-1.05-dist/dns.h 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/dns.h 2008-08-11 22:49:25.000000000 -0700 +@@ -20,6 +20,8 @@ + #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_NAPTR "\0\43" + #define DNS_T_AXFR "\0\374" + #define DNS_T_ANY "\0\377" + +@@ -43,6 +45,7 @@ + extern unsigned int dns_random(unsigned int); + + extern void dns_sortip(char *,unsigned int); ++extern void dns_rotateip(char *,unsigned int); + + extern void dns_domain_free(char **); + extern int dns_domain_copy(char **,const char *); +diff -ruN djbdns-1.05-dist/dns_rotateip.c djbdns-1.05/dns_rotateip.c +--- djbdns-1.05-dist/dns_rotateip.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/dns_rotateip.c 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,15 @@ ++#include "byte.h" ++ ++void dns_rotateip(char *s, unsigned int n) ++{ ++ unsigned int i; ++ char tmp[4]; ++ ++ i = n >> 2; ++ while (i > 1) { ++ --i; ++ byte_copy(tmp,4,s + (i << 2)); ++ byte_copy(s + (i << 2),4,s); ++ byte_copy(s,4,tmp); ++ } ++} +diff -ruN djbdns-1.05-dist/dnscache-conf.c djbdns-1.05/dnscache-conf.c +--- djbdns-1.05-dist/dnscache-conf.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/dnscache-conf.c 2008-08-11 19:33:30.000000000 -0700 +@@ -32,6 +32,10 @@ + char *user; + char *loguser; + struct passwd *pw; ++#ifdef DUMPCACHE ++int useruid; ++int usergid; ++#endif + const char *myip; + + uint32 seed[32]; +@@ -81,6 +85,14 @@ + myip = argv[4]; + if (!myip) myip = "127.0.0.1"; + ++#ifdef DUMPCACHE ++ pw = getpwnam(user); ++ seed_addtime(); ++ if (!pw) ++ strerr_die3x(111,FATAL,"unknown account ",user); ++ useruid = pw->pw_uid; ++ usergid = pw->pw_gid; ++#endif + pw = getpwnam(loguser); + seed_addtime(); + if (!pw) +@@ -120,6 +132,14 @@ + seed_addtime(); perm(0644); + seed_addtime(); start("env/DATALIMIT"); outs("3000000\n"); finish(); + seed_addtime(); perm(0644); ++#ifdef DUMPCACHE ++ seed_addtime(); start("env/SLURPCACHE"); outs("dump/slurpcache\n"); finish(); ++ seed_addtime(); perm(0644); ++ seed_addtime(); start("env/DUMPCACHE"); outs("dump/dumpcache\n"); finish(); ++ seed_addtime(); perm(0644); ++ seed_addtime(); start("env/DUMPCACHETMP"); outs("dump/dumpcache.tmp\n"); finish(); ++ seed_addtime(); perm(0644); ++#endif + seed_addtime(); start("run"); + outs("#!/bin/sh\nexec 2>&1\nexec <seed\nexec envdir ./env sh -c '\n exec envuidgid "); outs(user); + outs(" softlimit -o250 -d \"$DATALIMIT\" "); +@@ -131,6 +151,11 @@ + seed_addtime(); perm(0755); + seed_addtime(); makedir("root"); + seed_addtime(); perm(02755); ++#ifdef DUMPCACHE ++ seed_addtime(); makedir("root/dump"); ++ seed_addtime(); owner(useruid,usergid); ++ seed_addtime(); perm(02755); ++#endif + seed_addtime(); makedir("root/ip"); + seed_addtime(); perm(02755); + seed_addtime(); start("root/ip/127.0.0.1"); finish(); +diff -ruN djbdns-1.05-dist/dnscache.c djbdns-1.05/dnscache.c +--- djbdns-1.05-dist/dnscache.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/dnscache.c 2008-08-11 19:33:30.000000000 -0700 +@@ -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" +@@ -22,6 +23,7 @@ + #include "log.h" + #include "okclient.h" + #include "droproot.h" ++#include "sig.h" + + static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2]) + { +@@ -47,12 +49,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 +70,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 +89,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 +119,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 +141,6 @@ + } + + +-static int tcp53; +- + #define MAXTCP 20 + struct tcpclient { + struct query q; +@@ -138,6 +148,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 +277,7 @@ + x->state = 0; + } + +-void t_new(void) ++void t_new(int fd) + { + int i; + int j; +@@ -290,8 +301,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 +316,44 @@ + log_tcpopen(x->ip,x->port); + } + ++#ifdef DUMPCACHE ++static void do_dump(void) ++{ ++ int r; ++ r = cache_dump(); ++ if (r < 0) ++ r = errno; ++ log_dump(r); ++} ++#endif ++ ++#define FATAL "dnscache: fatal: " ++ ++iopause_fd *io = 0; ++int numio; ++ ++void hup_me() ++{ ++ if (!roots_init()) ++ strerr_die2sys(111,FATAL,"unable to read servers: "); ++ ++ log_reread(); ++} + +-iopause_fd io[3 + MAXUDP + MAXTCP]; +-iopause_fd *udp53io; +-iopause_fd *tcp53io; + + 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 +361,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 +411,83 @@ + 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; ++ char nxdip[4]; ++ 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); +@@ -430,17 +506,42 @@ + scan_ulong(x,&cachesize); + if (!cache_init(cachesize)) + strerr_die3x(111,FATAL,"not enough memory for cache of size ",x); ++#ifdef DUMPCACHE ++ x = env_get("SLURPCACHE"); ++ if (x) { ++ int nb = cache_slurp(x); ++ if (nb < 0) ++ strerr_die4sys(111,FATAL,"unable to slurp cache ",x," : "); ++ else ++ log_slurp(nb); ++ } ++#endif + + if (env_get("HIDETTL")) + response_hidettl(); + if (env_get("FORWARDONLY")) + query_forwardonly(); + ++ x = env_get("NXDSPECIAL"); ++ if (x) { ++ if (!ip4_scan(x,nxdip)) ++ strerr_die3x(111,FATAL,"unable to parse NXDSPECIAL IP address ",x); ++ query_nxdspecial(nxdip); ++ } ++ + 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,": "); ++ } ++ ++#ifdef DUMPCACHE ++ sig_catch(sig_alarm,do_dump); ++#endif ++ sig_catch(sig_hangup, hup_me); + + log_startup(); + doit(); +diff -ruN djbdns-1.05-dist/dnsfilter.c djbdns-1.05/dnsfilter.c +--- djbdns-1.05-dist/dnsfilter.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/dnsfilter.c 2008-08-11 19:33:30.000000000 -0700 +@@ -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; + } +diff -ruN djbdns-1.05-dist/hasdevtcp.h djbdns-1.05/hasdevtcp.h +--- djbdns-1.05-dist/hasdevtcp.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hasdevtcp.h 2008-08-11 22:55:09.000000000 -0700 +@@ -0,0 +1 @@ ++/* sysdep: -devtcp */ +diff -ruN djbdns-1.05-dist/hassgact.h djbdns-1.05/hassgact.h +--- djbdns-1.05-dist/hassgact.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hassgact.h 2008-08-11 22:55:16.000000000 -0700 +@@ -0,0 +1,2 @@ ++/* sysdep: +sigaction */ ++#define HASSIGACTION 1 +diff -ruN djbdns-1.05-dist/hassgact.h1 djbdns-1.05/hassgact.h1 +--- djbdns-1.05-dist/hassgact.h1 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hassgact.h1 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1 @@ ++/* sysdep: -sigaction */ +diff -ruN djbdns-1.05-dist/hassgact.h2 djbdns-1.05/hassgact.h2 +--- djbdns-1.05-dist/hassgact.h2 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hassgact.h2 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,2 @@ ++/* sysdep: +sigaction */ ++#define HASSIGACTION 1 +diff -ruN djbdns-1.05-dist/hassgprm.h djbdns-1.05/hassgprm.h +--- djbdns-1.05-dist/hassgprm.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hassgprm.h 2008-08-11 22:55:15.000000000 -0700 +@@ -0,0 +1,2 @@ ++/* sysdep: +sigprocmask */ ++#define HASSIGPROCMASK 1 +diff -ruN djbdns-1.05-dist/hassgprm.h1 djbdns-1.05/hassgprm.h1 +--- djbdns-1.05-dist/hassgprm.h1 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hassgprm.h1 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1 @@ ++/* sysdep: -sigprocmask */ +diff -ruN djbdns-1.05-dist/hassgprm.h2 djbdns-1.05/hassgprm.h2 +--- djbdns-1.05-dist/hassgprm.h2 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hassgprm.h2 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,2 @@ ++/* sysdep: +sigprocmask */ ++#define HASSIGPROCMASK 1 +diff -ruN djbdns-1.05-dist/hasshsgr.h djbdns-1.05/hasshsgr.h +--- djbdns-1.05-dist/hasshsgr.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/hasshsgr.h 2008-08-12 09:17:24.000000000 -0700 +@@ -0,0 +1 @@ ++/* sysdep: -shortsetgroups */ +diff -ruN djbdns-1.05-dist/iopause.h djbdns-1.05/iopause.h +--- djbdns-1.05-dist/iopause.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/iopause.h 2008-08-11 22:55:12.000000000 -0700 +@@ -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 -ruN djbdns-1.05-dist/log.c djbdns-1.05/log.c +--- djbdns-1.05-dist/log.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/log.c 2008-08-11 19:33:30.000000000 -0700 +@@ -88,12 +88,39 @@ + } + } + ++void log_reread(void) ++{ ++ string("rereading servers configuration"); ++ line(); ++} ++ + void log_startup(void) + { + string("starting"); + line(); + } + ++void log_listen(const char addr[4]) ++{ ++ string("listening on "); ++ ip(addr); ++ line(); ++} ++ ++#ifdef DUMPCACHE ++void log_slurp(int nb) ++{ ++ string("slurp "); number(nb); ++ line(); ++} ++ ++void log_dump(int err) ++{ ++ string("dump err "); number(err); ++ line(); ++} ++#endif ++ + 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(); +diff -ruN djbdns-1.05-dist/log.h djbdns-1.05/log.h +--- djbdns-1.05-dist/log.h 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/log.h 2008-08-11 19:33:30.000000000 -0700 +@@ -4,6 +4,12 @@ + #include "uint64.h" + + extern void log_startup(void); ++extern void log_listen(const char *); ++#ifdef DUMPCACHE ++extern void log_slurp(int); ++extern void log_dump(int); ++#endif ++extern void log_reread(void); + + extern void log_query(uint64 *,const char *,unsigned int,const char *,const char *,const char *); + extern void log_querydrop(uint64 *); +diff -ruN djbdns-1.05-dist/okclient.c djbdns-1.05/okclient.c +--- djbdns-1.05-dist/okclient.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/okclient.c 2008-08-11 19:33:30.000000000 -0700 +@@ -1,5 +1,6 @@ + #include <sys/types.h> + #include <sys/stat.h> ++#include "env.h" + #include "str.h" + #include "ip4.h" + #include "okclient.h" +@@ -10,6 +11,14 @@ + { + struct stat st; + int i; ++ static int init_done=0; ++ if (!init_done) { ++ if (env_get("OKCLIENT")) { ++ init_done=1; ++ } else ++ init_done=2; ++ } ++ if (init_done==1) return 1; + + fn[0] = 'i'; + fn[1] = 'p'; +diff -ruN djbdns-1.05-dist/parsetype.c djbdns-1.05/parsetype.c +--- djbdns-1.05-dist/parsetype.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/parsetype.c 2008-08-11 22:49:52.000000000 -0700 +@@ -24,6 +24,8 @@ + else if (case_equals(s,"key")) byte_copy(type,2,DNS_T_KEY); + else if (case_equals(s,"aaaa")) byte_copy(type,2,DNS_T_AAAA); + else if (case_equals(s,"axfr")) byte_copy(type,2,DNS_T_AXFR); ++ else if (case_equals(s,"srv")) byte_copy(type,2,DNS_T_SRV); ++ else if (case_equals(s,"naptr")) byte_copy(type,2,DNS_T_NAPTR); + else + return 0; + +diff -ruN djbdns-1.05-dist/printrecord.c djbdns-1.05/printrecord.c +--- djbdns-1.05-dist/printrecord.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/printrecord.c 2008-08-11 23:10:20.000000000 -0700 +@@ -82,6 +82,56 @@ + if (!stralloc_catulong0(out,ch,0)) return 0; + } + } ++ else if (byte_equal(misc,2,DNS_T_SRV)) { ++ if (!stralloc_cats(out," SRV ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0; ++ uint16_unpack_big(misc,&u16); ++ if (!stralloc_catulong0(out,u16,0)) return 0; ++ if (!stralloc_cats(out," ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0; ++ uint16_unpack_big(misc,&u16); ++ if (!stralloc_catulong0(out,u16,0)) return 0; ++ if (!stralloc_cats(out," ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0; ++ uint16_unpack_big(misc,&u16); ++ if (!stralloc_catulong0(out,u16,0)) return 0; ++ if (!stralloc_cats(out," ")) return 0; ++ pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; ++ if (!dns_domain_todot_cat(out,d)) return 0; ++ } ++ else if (byte_equal(misc,2,DNS_T_NAPTR)) { ++ char str[255]; ++ unsigned int oldpos; ++ if (!stralloc_cats(out," NAPTR ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0; ++ uint16_unpack_big(misc,&u16); ++ if (!stralloc_catulong0(out,u16,0)) return 0; ++ if (!stralloc_cats(out," ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0; ++ uint16_unpack_big(misc,&u16); ++ if (!stralloc_catulong0(out,u16,0)) return 0; ++ if (!stralloc_cats(out," ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,&ch,1); if (!pos) return 0; ++ pos = dns_packet_copy(buf,len,pos,str,ch); if (!pos) return 0; ++ if (!stralloc_cats(out,"\"")) return 0; ++ if (!stralloc_catb(out,str,ch)) return 0; ++ if (!stralloc_cats(out,"\" ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,&ch,1); if (!pos) return 0; ++ pos = dns_packet_copy(buf,len,pos,str,ch); if (!pos) return 0; ++ if (!stralloc_cats(out,"\"")) return 0; ++ if (!stralloc_catb(out,str,ch)) return 0; ++ if (!stralloc_cats(out,"\" ")) return 0; ++ pos = dns_packet_copy(buf,len,pos,&ch,1); if (!pos) return 0; ++ pos = dns_packet_copy(buf,len,pos,str,ch); if (!pos) return 0; ++ if (!stralloc_cats(out,"\"")) return 0; ++ if (!stralloc_catb(out,str,ch)) return 0; ++ if (!stralloc_cats(out,"\" ")) return 0; ++ pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; ++ oldpos = out->len; ++ if (!dns_domain_todot_cat(out,d)) return 0; ++ if (out->len == oldpos) ++ if (!stralloc_cats(out,".")) return 0; ++ } + else { + if (!stralloc_cats(out," ")) return 0; + uint16_unpack_big(misc,&u16); +diff -ruN djbdns-1.05-dist/prot.c djbdns-1.05/prot.c +--- djbdns-1.05-dist/prot.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/prot.c 2008-08-11 19:33:30.000000000 -0700 +@@ -1,5 +1,7 @@ + #include "hasshsgr.h" + #include "prot.h" ++#include <grp.h> ++#include <unistd.h> + + int prot_gid(int gid) + { +diff -ruN djbdns-1.05-dist/query.c djbdns-1.05/query.c +--- djbdns-1.05-dist/query.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/query.c 2008-08-11 19:33:30.000000000 -0700 +@@ -20,6 +20,15 @@ + flagforwardonly = 1; + } + ++static int flagnxdspecial = 0; ++static char nxdip[4]; ++ ++void query_nxdspecial(const char ip[4]) ++{ ++ byte_copy(nxdip,4,ip); ++ flagnxdspecial = 1; ++} ++ + static void cachegeneric(const char type[2],const char *d,const char *data,unsigned int datalen,uint32 ttl) + { + unsigned int len; +@@ -246,6 +255,7 @@ + case_lowerb(key + 2,dlen); + cached = cache_get(key,dlen + 2,&cachedlen,&ttl); + if (cached) { ++ soattl = rcode = 0; + log_cachednxdomain(d); + goto NXDOMAIN; + } +@@ -695,7 +705,12 @@ + NXDOMAIN: + if (z->level) goto LOWERLEVEL; + if (!rqa(z)) goto DIE; +- response_nxdomain(); ++ if (flagnxdspecial && typematch(DNS_T_A,dtype)) { ++ if (!response_rstart(d,DNS_T_A,rcode == 3 ? soattl : ttl)) goto DIE; ++ if (!response_addbytes(nxdip,4)) goto DIE; ++ response_rfinish(RESPONSE_ANSWER); ++ } else ++ response_nxdomain(); + cleanup(z); + return 1; + } +diff -ruN djbdns-1.05-dist/query.h djbdns-1.05/query.h +--- djbdns-1.05-dist/query.h 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/query.h 2008-08-11 19:33:30.000000000 -0700 +@@ -28,5 +28,6 @@ + extern int query_get(struct query *,iopause_fd *,struct taia *); + + extern void query_forwardonly(void); ++extern void query_nxdspecial(const char *); + + #endif +diff -ruN djbdns-1.05-dist/seek_set.c djbdns-1.05/seek_set.c +--- djbdns-1.05-dist/seek_set.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/seek_set.c 2008-08-11 19:33:30.000000000 -0700 +@@ -1,4 +1,5 @@ + #include <sys/types.h> ++#include <unistd.h> + #include "seek.h" + + #define SET 0 /* sigh */ +diff -ruN djbdns-1.05-dist/select.h djbdns-1.05/select.h +--- djbdns-1.05-dist/select.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/select.h 2008-08-11 22:55:14.000000000 -0700 +@@ -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 -ruN djbdns-1.05-dist/server.c djbdns-1.05/server.c +--- djbdns-1.05-dist/server.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/server.c 2008-08-11 19:33:30.000000000 -0700 +@@ -11,6 +11,8 @@ + #include "qlog.h" + #include "response.h" + #include "dns.h" ++#include "alloc.h" ++#include "iopause.h" + + extern char *fatal; + extern char *starting; +@@ -25,6 +27,44 @@ + + static char *q; + ++ ++static void hex(unsigned char c) ++{ ++ buffer_put(buffer_2,"0123456789abcdef" + (c >> 4),1); ++ buffer_put(buffer_2,"0123456789abcdef" + (c & 15),1); ++} ++ ++static void put_ip(const char i[4]) ++{ ++ hex(i[0]); ++ hex(i[1]); ++ hex(i[2]); ++ hex(i[3]); ++} ++ ++static void string(const char *s) ++{ ++ buffer_puts(buffer_2,s); ++} ++ ++static void line(void) ++{ ++ string("\n"); ++ buffer_flush(buffer_2); ++} ++ ++void log_listen(const char addr[4]) ++{ ++ string("listening on "); ++ put_ip(addr); ++ line(); ++} ++ ++void nomem() ++{ ++ strerr_die2x(111,fatal,"out of memory"); ++} ++ + static int doit(void) + { + unsigned int pos; +@@ -51,6 +91,13 @@ + response[3] &= ~128; + if (!(header[2] & 1)) response[2] &= ~1; + ++ if ((header[2] & 126) == 0x24) /* NOTIFY + AA */ ++ if (byte_equal(qtype,2,DNS_T_SOA)) { ++ response[2] |= 0x20; /* NOTIFY */ ++ qlog(ip,port,header,q,qtype," N "); ++ return 1; ++ } ++ + if (header[2] & 126) goto NOTIMP; + if (byte_equal(qtype,2,DNS_T_AXFR)) goto NOTIMP; + +@@ -59,7 +106,12 @@ + qlog(ip,port,header,q,qtype," - "); + return 0; + } +- qlog(ip,port,header,q,qtype," + "); ++ ++ if ((response[2] & 4) && (response[3] & 3)) ++ qlog(ip,port,header,q,qtype," X "); ++ else ++ qlog(ip,port,header,q,qtype," + "); ++ + return 1; + + NOTIMP: +@@ -82,35 +134,75 @@ + int main() + { + char *x; +- int udp53; ++ int *udp53; ++ unsigned int off; ++ unsigned int cnt; ++ iopause_fd *iop; + + x = env_get("IP"); + if (!x) + strerr_die2x(111,fatal,"$IP not set"); +- if (!ip4_scan(x,ip)) +- 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,ip,53) == -1) +- strerr_die2sys(111,fatal,"unable to bind UDP socket: "); ++ off=0; ++ cnt=0; ++ while (x[off]) { ++ unsigned int l; ++ char dummy[4]; ++ l=ip4_scan(x+off,dummy); ++ if (!l) ++ strerr_die3x(111,fatal,"unable to parse IP address ",x+off); ++ cnt++; ++ if (!x[off+l]) break; ++ if (x[off+l]!='/') ++ strerr_die3x(111,fatal,"unable to parse IP address ",x+off); ++ off+=l+1; ++ } ++ udp53=(int *) alloc(sizeof(int) *cnt); ++ if (!udp53) nomem(); ++ iop=(iopause_fd *) alloc(sizeof(*iop) * cnt); ++ if (!iop) nomem(); ++ ++ off=0; ++ cnt=0; ++ while (x[off]) { ++ unsigned int l; ++ l=ip4_scan(x+off,ip); ++ udp53[cnt] = socket_udp(); ++ if (udp53[cnt] == -1) ++ strerr_die2sys(111,fatal,"unable to create UDP socket: "); ++ if (socket_bind4_reuse(udp53[cnt],ip,53) == -1) ++ strerr_die2sys(111,fatal,"unable to bind UDP socket: "); ++ ndelay_off(udp53[cnt]); ++ socket_tryreservein(udp53[cnt],65536); ++ iop[cnt].fd=udp53[cnt]; ++ iop[cnt].events=IOPAUSE_READ; ++ log_listen(ip); ++ cnt++; ++ if (!x[off+l]) break; ++ off+=l+1; ++ } + + droproot(fatal); + + initialize(); +- +- ndelay_off(udp53); +- socket_tryreservein(udp53,65536); + + buffer_putsflush(buffer_2,starting); +- ++ + for (;;) { +- len = socket_recv4(udp53,buf,sizeof buf,ip,&port); +- if (len < 0) continue; +- if (!doit()) continue; +- if (response_len > 512) response_tc(); +- socket_send4(udp53,response,response_len,ip,port); +- /* may block for buffer space; if it fails, too bad */ ++ struct taia stamp; ++ struct taia deadline; ++ unsigned int i; ++ taia_now(&stamp); ++ taia_uint(&deadline,300); ++ taia_add(&deadline,&deadline,&stamp); ++ iopause(iop,cnt,&deadline,&stamp); ++ for (i=0;i<cnt;i++) ++ if (iop[i].revents) { ++ len = socket_recv4(udp53[i],buf,sizeof buf,ip,&port); ++ if (len < 0) continue; ++ if (!doit()) continue; ++ if (response_len > 512) response_tc(); ++ socket_send4(udp53[i],response,response_len,ip,port); ++ /* may block for buffer space; if it fails, too bad */ ++ } + } + } +diff -ruN djbdns-1.05-dist/sig.c djbdns-1.05/sig.c +--- djbdns-1.05-dist/sig.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/sig.c 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,12 @@ ++#include <signal.h> ++#include "sig.h" ++ ++int sig_alarm = SIGALRM; ++int sig_child = SIGCHLD; ++int sig_cont = SIGCONT; ++int sig_hangup = SIGHUP; ++int sig_pipe = SIGPIPE; ++int sig_term = SIGTERM; ++ ++void (*sig_defaulthandler)() = SIG_DFL; ++void (*sig_ignorehandler)() = SIG_IGN; +diff -ruN djbdns-1.05-dist/sig.h djbdns-1.05/sig.h +--- djbdns-1.05-dist/sig.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/sig.h 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,25 @@ ++#ifndef SIG_H ++#define SIG_H ++ ++extern int sig_alarm; ++extern int sig_child; ++extern int sig_cont; ++extern int sig_hangup; ++extern int sig_pipe; ++extern int sig_term; ++ ++extern void (*sig_defaulthandler)(); ++extern void (*sig_ignorehandler)(); ++ ++extern void sig_catch(int,void (*)()); ++#define sig_ignore(s) (sig_catch((s),sig_ignorehandler)) ++#define sig_uncatch(s) (sig_catch((s),sig_defaulthandler)) ++ ++extern void sig_block(int); ++extern void sig_unblock(int); ++extern void sig_blocknone(void); ++extern void sig_pause(void); ++ ++extern void sig_dfl(int); ++ ++#endif +diff -ruN djbdns-1.05-dist/sig_block.c djbdns-1.05/sig_block.c +--- djbdns-1.05-dist/sig_block.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/sig_block.c 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,38 @@ ++#include <signal.h> ++#include "sig.h" ++#include "hassgprm.h" ++ ++void sig_block(int sig) ++{ ++#ifdef HASSIGPROCMASK ++ sigset_t ss; ++ sigemptyset(&ss); ++ sigaddset(&ss,sig); ++ sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); ++#else ++ sigblock(1 << (sig - 1)); ++#endif ++} ++ ++void sig_unblock(int sig) ++{ ++#ifdef HASSIGPROCMASK ++ sigset_t ss; ++ sigemptyset(&ss); ++ sigaddset(&ss,sig); ++ sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); ++#else ++ sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1))); ++#endif ++} ++ ++void sig_blocknone(void) ++{ ++#ifdef HASSIGPROCMASK ++ sigset_t ss; ++ sigemptyset(&ss); ++ sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); ++#else ++ sigsetmask(0); ++#endif ++} +diff -ruN djbdns-1.05-dist/sig_catch.c djbdns-1.05/sig_catch.c +--- djbdns-1.05-dist/sig_catch.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/sig_catch.c 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,16 @@ ++#include <signal.h> ++#include "sig.h" ++#include "hassgact.h" ++ ++void sig_catch(int sig,void (*f)()) ++{ ++#ifdef HASSIGACTION ++ struct sigaction sa; ++ sa.sa_handler = f; ++ sa.sa_flags = 0; ++ sigemptyset(&sa.sa_mask); ++ sigaction(sig,&sa,(struct sigaction *) 0); ++#else ++ signal(sig,f); /* won't work under System V, even nowadays---dorks */ ++#endif ++} +diff -ruN djbdns-1.05-dist/sig_pause.c djbdns-1.05/sig_pause.c +--- djbdns-1.05-dist/sig_pause.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/sig_pause.c 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,14 @@ ++#include <signal.h> ++#include "sig.h" ++#include "hassgprm.h" ++ ++void sig_pause(void) ++{ ++#ifdef HASSIGPROCMASK ++ sigset_t ss; ++ sigemptyset(&ss); ++ sigsuspend(&ss); ++#else ++ sigpause(0); ++#endif ++} +diff -ruN djbdns-1.05-dist/tinydns-data.c djbdns-1.05/tinydns-data.c +--- djbdns-1.05-dist/tinydns-data.c 2008-08-11 19:32:53.000000000 -0700 ++++ djbdns-1.05/tinydns-data.c 2008-08-11 22:56:09.000000000 -0700 +@@ -159,11 +159,7 @@ + die_datatmp(); + } + +-buffer b; +-char bspace[1024]; +- + static stralloc line; +-int match = 1; + unsigned long linenum = 0; + + #define NUMFIELDS 15 +@@ -171,6 +167,8 @@ + + static char *d1; + static char *d2; ++static char *contact; ++ + char dptr[DNS_NAME4_DOMAIN]; + + char strnum[FMT_ULONG]; +@@ -181,7 +179,7 @@ + strerr_die4x(111,FATAL,"unable to parse data line ",strnum,why); + } + +-int main() ++int load(const char *fname) + { + int fddata; + int i; +@@ -196,20 +194,20 @@ + char type[2]; + char soa[20]; + char buf[4]; ++ char naptr[4]; ++ char srv[6]; ++ int match; ++ buffer b; ++ char bspace[1024]; + +- umask(022); +- +- fddata = open_read("data"); ++ fddata = open_read(fname); + if (fddata == -1) +- strerr_die2sys(111,FATAL,"unable to open data: "); ++ strerr_die4sys(111,FATAL,"unable to open ",fname,": "); + defaultsoa_init(fddata); + + buffer_init(&b,buffer_unixread,fddata,bspace,sizeof bspace); + +- fdcdb = open_trunc("data.tmp"); +- if (fdcdb == -1) die_datatmp(); +- if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp(); +- ++ match = 1; + while (match) { + ++linenum; + if (getln(&b,&line,&match,'\n') == -1) +@@ -247,6 +245,11 @@ + die_datatmp(); + break; + ++ case 'D': ++ if (!dns_domain_fromdot(&contact,f[0].s,f[0].len)) nomem(); ++ if (f[0].len == 0) contact = NULL; ++ break; ++ + case 'Z': + if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); + +@@ -298,8 +301,13 @@ + if (line.s[0] == '.') { + rr_start(DNS_T_SOA,ttl ? TTL_NEGATIVE : 0,ttd,loc); + rr_addname(d2); +- rr_add("\12hostmaster",11); +- rr_addname(d1); ++ if (!contact) { ++ rr_add("\12hostmaster",11); ++ rr_addname(d1); ++ } else { ++ rr_addname(contact); ++ } ++ + rr_add(defaultsoa,20); + rr_finish(d1); + } +@@ -369,6 +377,43 @@ + 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); ++ ++ if (ip4_scan(f[1].s,ip)) { ++ rr_start(DNS_T_A,ttl,ttd,loc); ++ rr_add(ip,4); ++ rr_finish(d2); ++ } ++ break; + + case '^': case 'C': + if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); +@@ -441,10 +486,61 @@ + rr_finish(d1); + break; + ++ case 'N': ++ if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); ++ if (!dns_domain_fromdot(&d2,f[6].s,f[6].len)) nomem(); ++ if (!stralloc_0(&f[7])) nomem(); ++ if (!scan_ulong(f[7].s,&ttl)) ttl = TTL_POSITIVE; ++ ttdparse(&f[8],ttd); ++ locparse(&f[9],loc); ++ ++ if (!stralloc_0(&f[1])) nomem(); ++ if (!scan_ulong(f[1].s,&u)) u = 0; ++ uint16_pack_big(naptr,u); ++ if (!stralloc_0(&f[2])) nomem(); ++ if (!scan_ulong(f[2].s,&u)) u = 0; ++ uint16_pack_big(naptr + 2,u); ++ ++ txtparse(&f[3]); if (f[3].len > 255) ++ syntaxerror(": it is not allowed more than 255 chars in a label"); ++ txtparse(&f[4]); if (f[4].len > 255) ++ syntaxerror(": it is not allowed more than 255 chars in a label"); ++ txtparse(&f[5]); if (f[5].len > 255) ++ syntaxerror(": it is not allowed more than 255 chars in a label"); ++ ++ rr_start(DNS_T_NAPTR,ttl,ttd,loc); ++ rr_add(naptr,4); ++ ++ ch = f[3].len; rr_add(&ch,1); ++ rr_add(f[3].s, f[3].len); ++ ch = f[4].len; rr_add(&ch,1); ++ rr_add(f[4].s, f[4].len); ++ ch = f[5].len; rr_add(&ch,1); ++ rr_add(f[5].s, f[5].len); ++ ++ rr_addname(d2); ++ rr_finish(d1); ++ break; ++ + default: + syntaxerror(": unrecognized leading character"); + } + } ++ close(fddata); ++} ++ ++int main(int argc, char **argv) ++{ ++ umask(022); ++ fdcdb = open_trunc("data.tmp"); ++ if (fdcdb == -1) die_datatmp(); ++ if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp(); ++ ++ if (argc == 1) ++ load("data"); ++ while(--argc) { ++ load(argv[argc]); ++ } + + if (cdb_make_finish(&cdb) == -1) die_datatmp(); + if (fsync(fdcdb) == -1) die_datatmp(); +diff -ruN djbdns-1.05-dist/trysgact.c djbdns-1.05/trysgact.c +--- djbdns-1.05-dist/trysgact.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/trysgact.c 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,10 @@ ++#include <signal.h> ++ ++main() ++{ ++ struct sigaction sa; ++ sa.sa_handler = 0; ++ sa.sa_flags = 0; ++ sigemptyset(&sa.sa_mask); ++ sigaction(0,&sa,(struct sigaction *) 0); ++} +diff -ruN djbdns-1.05-dist/trysgprm.c djbdns-1.05/trysgprm.c +--- djbdns-1.05-dist/trysgprm.c 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/trysgprm.c 2008-08-11 19:33:30.000000000 -0700 +@@ -0,0 +1,10 @@ ++#include <signal.h> ++ ++main() ++{ ++ sigset_t ss; ++ ++ sigemptyset(&ss); ++ sigaddset(&ss,SIGCHLD); ++ sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); ++} +diff -ruN djbdns-1.05-dist/uint32.h djbdns-1.05/uint32.h +--- djbdns-1.05-dist/uint32.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/uint32.h 2008-08-11 22:55:10.000000000 -0700 +@@ -0,0 +1,11 @@ ++#ifndef UINT32_H ++#define UINT32_H ++ ++typedef unsigned long uint32; ++ ++extern void uint32_pack(char *,uint32); ++extern void uint32_pack_big(char *,uint32); ++extern void uint32_unpack(const char *,uint32 *); ++extern void uint32_unpack_big(const char *,uint32 *); ++ ++#endif +diff -ruN djbdns-1.05-dist/uint64.h djbdns-1.05/uint64.h +--- djbdns-1.05-dist/uint64.h 1969-12-31 16:00:00.000000000 -0800 ++++ djbdns-1.05/uint64.h 2008-08-11 22:55:10.000000000 -0700 +@@ -0,0 +1,8 @@ ++#ifndef UINT64_H ++#define UINT64_H ++ ++/* sysdep: -ulong64 */ ++ ++typedef unsigned long long uint64; ++ ++#endif |