Download | Plain Text | Line Numbers


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 <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#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 <seed\nexec envdir ./env sh -c '\n  exec envuidgid "); outs(user);
   outs(" softlimit -o250 -d \"$DATALIMIT\" ");
@@ -131,6 +149,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 -urN djbdns-1.05/dnscache.c djbdns-1.05_new/dnscache.c
--- djbdns-1.05/dnscache.c	Sun Feb 11 23:11:45 2001
+++ djbdns-1.05_new/dnscache.c	Tue Sep  9 14:57:40 2008
@@ -22,6 +22,21 @@
 #include "log.h"
 #include "okclient.h"
 #include "droproot.h"
+#include <signal.h>
+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