/* dnscache-compact.c diet -Os gcc -s -o dnscache-compact dnscache-compact.c -Wall -W -lowfat http://riemann.fmi.uni-sofia.bg/ or in ./djbdns-1.05/ with: ./compile dnscache-compact.c ./load dnscache-compact buffer.a byte.a libtai.a unix.a dns.a alloc.a I recommend using the second method (Nikola Vladov). */ #include #include #include #include #include #include #include #include #include #include "str.h" #include "case.h" #include "tai.h" #include "buffer.h" #include "uint32.h" #include "dns.h" #include "scan.h" void die(int n, const char *s1, const char *s2, const char *s3) { if (s1) buffer_puts(buffer_2, s1); if (s2) buffer_puts(buffer_2, s2); if (s3) buffer_puts(buffer_2, s3); buffer_puts(buffer_2, "\n"); buffer_flush(buffer_2); _exit(n); } char **convert_hosts(int argc, char **argv) { char **hh,**h,**a,*q; if (!(hh = malloc((argc+1) * sizeof (char *)))) die(111, "malloc ", "error", 0); for(q=0,h=hh,a=argv; *a; a++) if (dns_domain_fromdot(&q, *a, str_len(*a))) {*h++=q; q=0;} return hh; } void dumpandwait(unsigned long pid, char *fn) { struct stat st; time_t mtime=0; struct timespec ts = {0, 100000000}; /* 0.1s */ int i; if (!stat(fn, &st)) mtime = st.st_mtime; if (kill(pid,SIGALRM)) die(111, "unable to kill dnscache: ", "SIGALRM", 0); for (i=0; i<60; i++) { /* 6-7 sec */ if (!stat(fn, &st)) if (mtime != st.st_mtime) return; nanosleep(&ts, 0); } die(111, "timeout waiting for dnscache to dump", 0,0); } int main(int argc, char **argv) { unsigned long flagkill = 0; uint32 pos, len; uint32 keylen; uint32 datalen; uint32 out; struct tai now; struct tai expire; char buf[8192]; char *p,**hosts=0; int fd,i; buffer b= BUFFER_INIT((int (*)(int, const char *, unsigned int))write, -1 , buf, sizeof buf); if (argc>1 && argv[1][0] == '-') { if (!scan_ulong(argv[1]+1, &flagkill) || flagkill <= 1) die(111, "bad pid: ", argv[1]+1, 0); argc--; argv++; } if (argc<4) die(1,"usage: dnscache-compact [-pid] data new.tmp " "new [key1] [key2] ...",0,0); if (flagkill) dumpandwait(flagkill, argv[1]); if ((fd=open(argv[1],O_RDONLY)) == -1) die(21, argv[1], ": open ", "error"); if ((len=lseek(fd,0,SEEK_END)) == (uint32)-1) die(21, argv[1], ": lseek ", "error"); if ((p=mmap(0,len,PROT_READ,MAP_SHARED,fd,0))==MAP_FAILED) die(21, "mmap ", "error", 0); close(fd); if ((b.fd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC, 0644))==-1) die(22, argv[2], ": open ", "error"); argc -= 4; if (argc) hosts = convert_hosts(argc, argv+4); tai_now(&now); pos = 0; while (pos+16 <= len) { uint32_unpack(p + pos, &keylen); uint32_unpack(p + pos + 4, &datalen); tai_unpack(p + pos + 8, &expire); out = 16 + keylen + datalen; if (pos + out > len) goto die; if (!tai_less(&expire,&now)) { for (i=0; i