diff -urN djbdns-1.05/Makefile djbdns-1.05_new/Makefile --- djbdns-1.05/Makefile Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/Makefile Sun Sep 14 18:07:13 2008 @@ -152,9 +152,14 @@ uint32.h uint64.h ./compile cache.c +cache_djb.o: \ +compile cache_djb.c alloc.h byte.h uint32.h exit.h tai.h uint64.h cache.h \ +uint32.h uint64.h + ./compile cache_djb.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 \ +load cachetest.o cache_djb.o libtai.a buffer.a alloc.a unix.a byte.a + ./load cachetest cache_djb.o libtai.a buffer.a alloc.a unix.a \ byte.a cachetest.o: \ diff -urN djbdns-1.05/README.dumpcache djbdns-1.05_new/README.dumpcache --- djbdns-1.05/README.dumpcache Thu Jan 1 02:00:00 1970 +++ djbdns-1.05_new/README.dumpcache Tue Sep 9 14:57:40 2008 @@ -0,0 +1,23 @@ +dnscache-conf sets variables: + DUMPCACHE=14400:dump/data + SLURPCACHE=dump/data +The number 14400 is the dump interval. Set it between 3600 and 43200. + +Understands signals: + SIGTERM dump cache and exit + SIGALARM dump cache + SIGHUP reload cache + +Filtering like multilog. To use filtering edit run file. Example: +... +exec envdir ./env envuidgid dnscache softlimit -o250 -d 3000000 \ + /usr/local/bin/dnscache '-*' '+stats *' '+slurp *' '+dump *' '+tcp *' + +You can comment line 32 of log.c to remove prefix "dns: ". + +dnscache ignores SIGPIPE. + +I will put documention on: +http://riemann.fmi.uni-sofia.bg/docs/djbdns-dumpcache.html + +Enjoy, Nikola diff -urN djbdns-1.05/TARGETS djbdns-1.05_new/TARGETS --- djbdns-1.05/TARGETS Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/TARGETS Sun Sep 14 18:12:47 2008 @@ -86,6 +86,7 @@ okclient.o log.o cache.o +cache_djb.o query.o response.o dd.o diff -urN djbdns-1.05/cache.c djbdns-1.05_new/cache.c --- djbdns-1.05/cache.c Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/cache.c Tue Sep 9 14:57:40 2008 @@ -1,3 +1,16 @@ +#ifdef DUMPCACHE +#include +#include +#include +#include +#include +#include +#include "str.h" +#include "open.h" +#include "buffer.h" +#include "scan.h" +#include "log.h" +#endif #include "alloc.h" #include "byte.h" #include "uint32.h" @@ -137,6 +150,7 @@ if (datalen > MAXDATALEN) return; if (!ttl) return; + if (cache_get(key, keylen, &entrylen, &pos)) return; if (ttl > 604800) ttl = 604800; entrylen = keylen + datalen + 20; @@ -183,25 +197,137 @@ int cache_init(unsigned int cachesize) { +#ifdef DUMPCACHE + char *y=x; + uint32 old_size=size; +#else if (x) { alloc_free(x); x = 0; } +#endif if (cachesize > 1000000000) cachesize = 1000000000; if (cachesize < 100) cachesize = 100; size = cachesize; - hsize = 4; - while (hsize <= (size >> 5)) hsize <<= 1; - +#ifdef DUMPCACHE + x = realloc(x,size); + if (!x) { x = y; size = old_size; } + log_cachesize(size); +#else x = alloc(size); +#endif if (!x) return 0; byte_zero(x,size); + hsize = 4; + while (hsize <= (size >> 5)) hsize <<= 1; + writer = hsize; oldest = size; unused = size; return 1; } + +#ifdef DUMPCACHE +int cache_dump(char *fn) +{ + uint32 pos; + uint32 len, last; + int r=-1; + char *tmp; + buffer b = BUFFER_INIT((int (*)(int, char*, unsigned int))write, + -1, 0, 8000); + len=str_len(fn); + tmp = alloc(8032+len); + if (tmp == 0) return -1; + byte_copy(tmp,len,fn); + byte_copy(tmp+len,5,".tmp"); + if ((b.fd = open_trunc(tmp)) == -1) goto ready; + b.x = tmp + len + 16; + + for (r=0, pos=oldest, last=unused; r<2; pos=hsize, last=writer, r++) + while (pos < last) { + len = get4(pos + 4) + get4(pos + 8) + 16; + if (buffer_put(&b, x + pos + 4, len)) goto close_fd; + pos += 4 + len; + } + + r = 0; + if (buffer_flush(&b) || fsync(b.fd) || close(b.fd) || rename(tmp,fn)) { + close_fd: + r = errno; + close(b.fd); + unlink(tmp); + errno = r; + r = -1; + } + ready: + alloc_free(tmp); + return r; +} + +int cache_slurp(char *fn, int reinit) +{ + char *map, *data; + uint32 pos; + uint32 keylen; + uint32 datalen; + uint32 len; + struct tai now, expire; + int fd; + unsigned long a=200, b=32768; + + if ((fd = open_read(fn)) == -1) return -1; + len = lseek(fd,0,SEEK_END); + + if (reinit) { + static unsigned int cachesize; + if (!cachesize) cachesize = size; + if ((pos=str_len(fn)) + 48 < size) { + int r; + data = x + 32; + byte_copy(data,pos,fn); + byte_copy(data+pos,8,".blowup"); + r=readlink(data,x,24); + if (r > 0) { + x[r] = 0; + if ((r = scan_ulong(x,&a)) && x[r] == ':') + scan_ulong(x+r+1,&b); + } + } + + pos = ((a*(len/100) + b) & ~4095) - 40; + if (pos > cachesize) pos = cachesize; + /* next is impossible, since cache is already init */ + if (!cache_init(pos)) cache_impossible(); + cache_motion = 0; + } + + map=mmap(0,len,PROT_READ,MAP_SHARED,fd,0); + close(fd); + if (map==MAP_FAILED) return -1; + + tai_now(&now); + pos = 0; + a = 0; + while (pos + 16 <= len) { + data = map + pos; + uint32_unpack(data, &keylen); + uint32_unpack(data + 4, &datalen); + tai_unpack(data + 8, &expire); + pos += 16 + keylen + datalen; + data += 16; + if (pos > len) break; /* missing data */ + if (expire.x > now.x) { + cache_set(data, keylen, data + keylen, datalen, + (uint32)(expire.x - now.x)); + a++; + } + } + munmap(map,len); + return a; +} +#endif diff -urN djbdns-1.05/cache.h djbdns-1.05_new/cache.h --- djbdns-1.05/cache.h Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/cache.h Tue Sep 9 14:57:40 2008 @@ -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(char *); +extern int cache_slurp(char *, int); +#endif #endif diff -urN djbdns-1.05/cache_djb.c djbdns-1.05_new/cache_djb.c --- djbdns-1.05/cache_djb.c Thu Jan 1 02:00:00 1970 +++ djbdns-1.05_new/cache_djb.c Sun Sep 14 18:02:31 2008 @@ -0,0 +1,4 @@ +#ifdef DUMPCACHE +#undef DUMPCACHE +#endif +#include "cache.c" diff -urN djbdns-1.05/conf-cc djbdns-1.05_new/conf-cc --- djbdns-1.05/conf-cc Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/conf-cc Sun Sep 14 18:14:05 2008 @@ -1,3 +1,3 @@ -gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings +gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -DDUMPCACHE This will be used to compile .c files. diff -urN djbdns-1.05/dnscache-conf.c djbdns-1.05_new/dnscache-conf.c --- djbdns-1.05/dnscache-conf.c Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/dnscache-conf.c Tue Sep 9 14:57:40 2008 @@ -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,12 @@ 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/data\n"); finish(); + seed_addtime(); perm(0644); + seed_addtime(); start("env/DUMPCACHE"); outs("14400:dump/data\n"); finish(); + seed_addtime(); perm(0644); +#endif seed_addtime(); start("run"); outs("#!/bin/sh\nexec 2>&1\nexec +char **ARGV; +void sig_catch(int sig, void (*f)()) { + struct sigaction sa; + sa.sa_handler = f; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(sig,&sa,(struct sigaction *) 0); +} +#ifdef DUMPCACHE +static unsigned long dumptime, flagsignal; +static char *slurpcache, *dumpcache; +static struct tai nextdump; +void got_signal(int sig) { flagsignal=sig; } +#endif static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2]) { @@ -115,6 +130,12 @@ if (x->port < 1024) if (x->port != 53) return; if (!okclient(x->ip)) return; +#ifdef DUMPCACHE + if (dumptime && nextdump.x < x->start.sec.x) { + flagsignal=9999; + nextdump.x = x->start.sec.x + (uint64)dumptime; + } +#endif if (!packetquery(buf,len,&q,qtype,qclass,x->id)) return; x->active = ++numqueries; ++uactive; @@ -379,6 +400,18 @@ if (tcp53io) if (tcp53io->revents) t_new(); +#ifdef DUMPCACHE + if (flagsignal && flagsignal != SIGHUP) { /* SIGTERM SIGALRM 9999 */ + r=cache_dump(dumpcache); + log_dump(r); + if (flagsignal == SIGTERM) _exit(0); + if (flagsignal == SIGALRM) flagsignal = 0; + else if (!r && slurpcache) flagsignal = SIGHUP; /* 9999 */ + } + if (flagsignal == SIGHUP) + log_slurp(cache_slurp(slurpcache, 1)); + flagsignal=0; +#endif } } @@ -386,11 +419,13 @@ char seed[128]; -int main() +int main(int argc, char **argv) { char *x; unsigned long cachesize; + sig_catch(SIGPIPE, SIG_IGN); + ARGV = argv+1; (void)argc; x = env_get("IP"); if (!x) strerr_die2x(111,FATAL,"$IP not set"); @@ -443,5 +478,22 @@ strerr_die2sys(111,FATAL,"unable to listen on TCP socket: "); log_startup(); +#ifdef DUMPCACHE + if ((slurpcache=env_get("SLURPCACHE"))) { + log_slurp(cache_slurp(slurpcache, 0)); + sig_catch(SIGHUP, got_signal); + } + if ((x=env_get("DUMPCACHE"))) { + int k=scan_ulong(x, &dumptime); + if (dumptime) + if (x[k]=':' && x[k+1]) { + dumpcache = x+k+1; + tai_now(&nextdump); + nextdump.x += (uint64)dumptime; + sig_catch(SIGTERM, got_signal); + sig_catch(SIGALRM, got_signal); + } else dumptime = 0; + } +#endif doit(); } diff -urN djbdns-1.05/log.c djbdns-1.05_new/log.c --- djbdns-1.05/log.c Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/log.c Tue Sep 9 14:57:40 2008 @@ -4,6 +4,67 @@ #include "error.h" #include "byte.h" #include "log.h" +#include "str.h" + +int match(const char *pattern,const char *buf,unsigned int len) { + char ch; + for (;;) { + ch = *pattern++; + if (!ch) return !len; + if (ch == '*') { + ch = *pattern; + if (!ch) return 1; + for (;;) { + if (!len) return 0; + if (*buf == ch) break; + ++buf; --len; + } + continue; + } + if (!len) return 0; + if (*buf != ch) return 0; + ++buf; --len; + } +} + +extern char **ARGV; +static int ok; +#define LOG_PREFIX "dns: " + +static void buffer_check() { + unsigned int len= buffer_2->p; + char **p=ARGV, *x= buffer_2->x; + +#ifdef LOG_PREFIX + if (len>=5) {len -= 5; x += 5;} +#endif + ok = 1; + for (; *p; p++) { + if (**p=='+' && ok!= 1 && match(*p+1,x,len)) ok= 1; + if (**p=='-' && ok!=-1 && match(*p+1,x,len)) ok=-1; + } + if (ok==-1) buffer_2->p=0; +} + +/* ok==0 no prefix; ok==-2 has prefix; ok==-1 no print; ok==1 print */ +static void out_put(const char *s, unsigned long n) { + switch (ok) { + case 0: ok=-2; +#ifdef LOG_PREFIX + buffer_puts(buffer_2, LOG_PREFIX); +#endif + case -2: + if (n > buffer_2->n - buffer_2->p) { /* no free space */ + buffer_check(); + if (ok==-1) break; + } + case 1: buffer_put(buffer_2,s,n); + } +} + +static void out_puts(const char *s) {out_put(s,str_len(s));} +#define buffer_put(a,b,c) out_put(b,c) +#define buffer_puts(a,b) out_puts(b) /* work around gcc 2.95.2 bug */ #define number(x) ( (u64 = (x)), u64_print() ) @@ -37,7 +98,9 @@ static void line(void) { string("\n"); + if (ok!=1 && ok!=-1) buffer_check(); buffer_flush(buffer_2); + ok = 0; } static void space(void) @@ -93,6 +156,32 @@ string("starting"); line(); } + + +#ifdef DUMPCACHE +void log_slurp(int nb) +{ + string("slurp "); + if (nb<0) { string("err "); string(error_str(errno)); } + else number(nb); + line(); +} + +void log_dump(int e) +{ + string("dump "); + if (e) { string("err "); string(error_str(errno)); } + else string("ok"); + line(); +} + +void log_cachesize(unsigned int e) +{ + string("cachesize "); + number(e); + 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]) { diff -urN djbdns-1.05/log.h djbdns-1.05_new/log.h --- djbdns-1.05/log.h Sun Feb 11 23:11:45 2001 +++ djbdns-1.05_new/log.h Tue Sep 9 14:57:40 2008 @@ -33,4 +33,9 @@ extern void log_stats(void); +#ifdef DUMPCACHE +extern void log_slurp(int); +extern void log_dump(int); +extern void log_cachesize(unsigned int); +#endif #endif