Download | Plain Text | No Line Numbers


  1. /* dnscache-compact.c
  2.   diet -Os gcc -s -o dnscache-compact dnscache-compact.c -Wall -W -lowfat
  3.   http://riemann.fmi.uni-sofia.bg/
  4.  
  5.   or in ./djbdns-1.05/ with:
  6.   ./compile dnscache-compact.c
  7.   ./load dnscache-compact buffer.a byte.a libtai.a unix.a dns.a alloc.a
  8.  
  9.   I recommend using the second method (Nikola Vladov).
  10. */
  11.  
  12. #include <unistd.h>
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #include <stdlib.h>
  16. #include <sys/mman.h>
  17. #include <sys/stat.h>
  18. #include <signal.h>
  19. #include <time.h>
  20. #include <errno.h>
  21. #include "str.h"
  22. #include "case.h"
  23. #include "tai.h"
  24. #include "buffer.h"
  25. #include "uint32.h"
  26. #include "dns.h"
  27. #include "scan.h"
  28.  
  29. void die(int n, const char *s1, const char *s2, const char *s3) {
  30. if (s1) buffer_puts(buffer_2, s1);
  31. if (s2) buffer_puts(buffer_2, s2);
  32. if (s3) buffer_puts(buffer_2, s3);
  33. buffer_puts(buffer_2, "\n");
  34. buffer_flush(buffer_2);
  35. _exit(n);
  36. }
  37.  
  38. char **convert_hosts(int argc, char **argv) {
  39. char **hh,**h,**a,*q;
  40.  
  41. if (!(hh = malloc((argc+1) * sizeof (char *))))
  42. die(111, "malloc ", "error", 0);
  43.  
  44. for(q=0,h=hh,a=argv; *a; a++)
  45. if (dns_domain_fromdot(&q, *a, str_len(*a)))
  46. {*h++=q; q=0;}
  47.  
  48. return hh;
  49. }
  50.  
  51. void dumpandwait(unsigned long pid, char *fn) {
  52. struct stat st;
  53. time_t mtime=0;
  54. struct timespec ts = {0, 100000000}; /* 0.1s */
  55. int i;
  56.  
  57. if (!stat(fn, &st)) mtime = st.st_mtime;
  58. if (kill(pid,SIGALRM))
  59. die(111, "unable to kill dnscache: ", "SIGALRM", 0);
  60.  
  61. for (i=0; i<60; i++) { /* 6-7 sec */
  62. if (!stat(fn, &st))
  63. if (mtime != st.st_mtime) return;
  64. nanosleep(&ts, 0);
  65. }
  66. die(111, "timeout waiting for dnscache to dump", 0,0);
  67. }
  68.  
  69. int main(int argc, char **argv) {
  70. unsigned long flagkill = 0;
  71. uint32 pos, len;
  72. uint32 keylen;
  73. uint32 datalen;
  74. uint32 out;
  75. struct tai now;
  76. struct tai expire;
  77. char buf[8192];
  78. char *p,**hosts=0;
  79. int fd,i;
  80. buffer b= BUFFER_INIT((int (*)(int, const char *, unsigned int))write,
  81. -1 , buf, sizeof buf);
  82.  
  83. if (argc>1 && argv[1][0] == '-') {
  84. if (!scan_ulong(argv[1]+1, &flagkill) || flagkill <= 1)
  85. die(111, "bad pid: ", argv[1]+1, 0);
  86. argc--; argv++;
  87. }
  88. if (argc<4)
  89. die(1,"usage: dnscache-compact [-pid] data new.tmp "
  90. "new [key1] [key2] ...",0,0);
  91.  
  92. if (flagkill) dumpandwait(flagkill, argv[1]);
  93.  
  94. if ((fd=open(argv[1],O_RDONLY)) == -1)
  95. die(21, argv[1], ": open ", "error");
  96. if ((len=lseek(fd,0,SEEK_END)) == (uint32)-1)
  97. die(21, argv[1], ": lseek ", "error");
  98. if ((p=mmap(0,len,PROT_READ,MAP_SHARED,fd,0))==MAP_FAILED)
  99. die(21, "mmap ", "error", 0);
  100. close(fd);
  101.  
  102. if ((b.fd=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC, 0644))==-1)
  103. die(22, argv[2], ": open ", "error");
  104.  
  105. argc -= 4;
  106. if (argc) hosts = convert_hosts(argc, argv+4);
  107. tai_now(&now);
  108. pos = 0;
  109.  
  110. while (pos+16 <= len) {
  111. uint32_unpack(p + pos, &keylen);
  112. uint32_unpack(p + pos + 4, &datalen);
  113. tai_unpack(p + pos + 8, &expire);
  114.  
  115. out = 16 + keylen + datalen;
  116. if (pos + out > len) goto die;
  117.  
  118. if (!tai_less(&expire,&now)) {
  119. for (i=0; i<argc; i++) {
  120. if (p[pos + 15 + keylen] == 0 &&
  121. !case_diffb(hosts[i], keylen-2, p + pos + 18))
  122. goto skip;
  123. }
  124. if (buffer_put(&b, p + pos, out)) goto die;
  125. }
  126.  
  127. skip:
  128. pos += out;
  129. continue;
  130.  
  131. die:
  132. munmap(p,len);
  133. close (b.fd); unlink(argv[2]);
  134. die(1, "input/output ", "error", 0);
  135. }
  136.  
  137. if (buffer_flush(&b)) goto die;
  138. if (pos != len) goto die;
  139. if (fsync(b.fd) || close(b.fd)) goto die;
  140. munmap(p,len);
  141. if (rename(argv[2],argv[3])) goto die;
  142.  
  143. if (flagkill)
  144. if (kill(flagkill,SIGHUP))
  145. die(111, "unable to kill dnscache: ", "SIGHUP", 0);
  146. return 0;
  147. }
  148.