Download | Plain Text | No Line Numbers
- /* 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 <unistd.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <time.h>
- #include <errno.h>
- #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;
-
- 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<argc; i++) {
- if (p[pos + 15 + keylen] == 0 &&
- !case_diffb(hosts[i], keylen-2, p + pos + 18))
- goto skip;
- }
- if (buffer_put(&b, p + pos, out)) goto die;
- }
-
- skip:
- pos += out;
- continue;
-
- die:
- munmap(p,len);
- close (b.fd); unlink(argv[2]);
- die(1, "input/output ", "error", 0);
- }
-
- if (buffer_flush(&b)) goto die;
- if (pos != len) goto die;
- if (fsync(b.fd) || close(b.fd)) goto die;
- munmap(p,len);
-
- if (flagkill)
- if (kill(flagkill,SIGHUP))
- die(111, "unable to kill dnscache: ", "SIGHUP", 0);
- return 0;
- }
-