Download | Plain Text | No Line Numbers


  1. /* prettycache.c
  2.   diet -Os gcc -s -o prettycache prettycache.c -Wall -W -lowfat
  3.   http://riemann.fmi.uni-sofia.bg/
  4.  
  5.   or in ./djbdns-1.05/ with:
  6.   ./compile prettycache.c
  7.   ./load prettycache buffer.a byte.a libtai.a unix.a
  8. */
  9.  
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12. #include <sys/mman.h>
  13. #include <errno.h>
  14. #include "tai.h"
  15. #include "buffer.h"
  16. #include "uint32.h"
  17. #include "uint16.h"
  18. #include "fmt.h"
  19.  
  20. #define outs(x) buffer_puts(buffer_1,x)
  21. #define out(x,y) buffer_put(buffer_1,x,y)
  22. int outu(uint32 u) {char tmp[12]; return out(tmp,fmt_ulong(tmp,u));}
  23.  
  24. static uint32 pos;
  25. static int flagdot, flagupper, flagtai, flagflat, flagalive;
  26. struct tai now;
  27. char hex[16] = "0123456789abcdef";
  28.  
  29. void die(int n, const char *s1, const char *s2, const char *s3) {
  30. buffer_flush(buffer_1);
  31. if (s1) buffer_puts(buffer_2, s1);
  32. if (s2) buffer_puts(buffer_2, s2);
  33. if (s3) buffer_puts(buffer_2, s3);
  34. buffer_puts(buffer_2, "\n");
  35. buffer_flush(buffer_2);
  36. _exit(n);
  37. }
  38.  
  39. void bad_input() {
  40. char tmp[12];
  41. tmp[fmt_ulong(tmp, pos)]=0;
  42. die(111,"\n\ntruncated input near to ", tmp, " position");
  43. }
  44.  
  45. void u_octal(unsigned char ch) {
  46. char buf[4];
  47. buf[3] = '0' + (ch & 7); ch >>= 3;
  48. buf[2] = '0' + (ch & 7); ch >>= 3;
  49. buf[1] = '0' + (ch & 7);
  50. buf[0] = '\\';
  51. out(buf,4);
  52. }
  53.  
  54. int dns_dtodot(const char *d, uint32 len) {
  55. char ch, ch2;
  56. int total=0;
  57.  
  58. if (!len) return 0;
  59. if (!*d) { outs("."); return 1; }
  60.  
  61. for (;len;) {
  62. ch = *d++;
  63. total++;
  64. len--;
  65. while (len && ch--) {
  66. ch2 = *d++;
  67. total++;
  68. len--;
  69. if (!flagupper)
  70. if ((ch2 >= 'A') && (ch2 <= 'Z'))
  71. ch2 += 32;
  72. if (((ch2 >= 'a') && (ch2 <= 'z')) ||
  73. ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_') ||
  74. ((ch2 >= 'A') && (ch2 <= 'Z'))) {
  75. out(&ch2,1);
  76. }
  77. else
  78. u_octal((unsigned char)ch2);
  79. }
  80. if (len && !*d) { if (flagdot) out(".",1); return ++total; }
  81. out(".",1);
  82. }
  83. return -1;
  84. }
  85.  
  86. void u_misc(char *s, uint32 len) {
  87. char *a=s, *end=a+len;
  88. while(a<end) {
  89. out(hex + ((a[0] >> 4) & 15), 1);
  90. out(hex + ((a[0]) & 15), 1);
  91. ++a;
  92. }
  93. }
  94.  
  95. void u_a(char *s, uint32 len) {
  96. char *a=s, *end=a+len;
  97. while(a+4<=end) {
  98. int i=0;
  99. for(i=0; i<4; i++) {
  100. outu((uint32)(unsigned char)a[i]);
  101. if (i<3) outs(".");
  102. }
  103. a += 4;
  104. if (a+4 <= end) outs(" ");
  105. }
  106. }
  107.  
  108. void u_hex(unsigned char *p) {
  109. char x[4];
  110. int i;
  111. x[0]=hex[p[0] >> 4];
  112. x[1]=hex[p[0] & 15];
  113. x[2]=hex[p[1] >> 4];
  114. x[3]=hex[p[1] & 15];
  115. for (i=0; i<3 && x[i]=='0';) i++;
  116. out(x+i, 4-i);
  117. }
  118.  
  119. void u_ip6(unsigned char *ip) {
  120. int k, p0,len0, p1,len1, compr;
  121.  
  122. for (k=0, p0=0,len0=0, p1=0, compr=0; k<16; k+=2) {
  123. if (ip[k]==0 && ip[k+1]==0) {
  124. if (!compr) {
  125. compr=1;
  126. p1=k;
  127. }
  128. if (k==14) { k=16; goto last; }
  129. } else if (compr) {
  130. last:
  131. if ((len1 = k-p1) > len0) {
  132. len0=len1;
  133. p0=p1;
  134. }
  135. compr=0;
  136. }
  137. }
  138.  
  139. for (k=0; k<16; k+=2) {
  140. if (p0 == k && len0) {
  141. out("::", 1 + !p0);
  142. k += len0-2;
  143. continue;
  144. }
  145. u_hex(ip + k);
  146. if (k<14) outs(":");
  147. }
  148. }
  149.  
  150. void u_aaaa(char *s, uint32 len) {
  151. char *end = s + len;
  152. while (s+18 <= end) {
  153. if (flagflat) u_misc(s+2,16);
  154. else u_ip6((unsigned char*)s+2);
  155. s += 18;
  156. if (s+18 <= end) outs(" ");
  157. }
  158. }
  159.  
  160. void u_txt(char *a, uint32 len) {
  161. unsigned int txtlen,i;
  162. txtlen=0;
  163. for (i = 2;i < len;++i) {
  164. char ch = a[i];
  165. if (!txtlen)
  166. txtlen = (unsigned char) ch;
  167. else {
  168. --txtlen;
  169. if (ch < 32 || ch > 126) u_octal((unsigned char)ch);
  170. else out(&ch,1);
  171. }
  172. }
  173. if (txtlen) bad_input();
  174. }
  175.  
  176. void u_name(char *s, uint32 len) {
  177. char *a=s, *end=a+len;
  178. unsigned long r;
  179. while(a<end) {
  180. if ((r = dns_dtodot(a,end-a))<=0) bad_input();
  181. a += r;
  182. if (a<end) outs(" ");
  183. }
  184. }
  185.  
  186. void u_mx(char *s, uint32 len) {
  187. char *a=s, *end=a+len;
  188. unsigned long r;
  189. uint16 u;
  190. while(a+3<end) {
  191. uint16_unpack_big(a, &u);
  192. outu(u);
  193. outs(" ");
  194. if ((r=dns_dtodot(a+2, end-(a+2)))<=0) bad_input();
  195. a += r+2;
  196. if (a+3<end) outs(" ");
  197. }
  198. }
  199.  
  200. int u_time(char *tai) {
  201. struct tai expire;
  202. uint32 exp;
  203.  
  204. tai_unpack(tai, &expire);
  205. if (expire.x <= now.x) {
  206. if (flagalive) return 1;
  207. exp = 0;
  208. } else
  209. exp = (uint32)(expire.x - now.x);
  210.  
  211. if (flagtai) {
  212. outs("@");
  213. u_misc(tai,8);
  214. outs("00000000");
  215. } else {
  216. char sp[] = " ";
  217. int len = fmt_ulong(0, exp);
  218. if (len<6) out(sp, 6-len);
  219. outu((uint32)exp);
  220. }
  221. outs(" ");
  222. return 0;
  223. }
  224.  
  225. int main(int argc, char **argv) {
  226. uint32 len;
  227. uint32 keylen;
  228. uint32 datalen;
  229. uint32 out;
  230. char *p, buf[8];
  231. const char *type, *sep=" ";
  232. int fd;
  233. void (*uu)(char*, uint32);
  234.  
  235. while (argc>1 && argv[1][0] == '-') {
  236. for (p=argv[1]+1; *p; p++)
  237. switch (*p) {
  238. case 'A': flagalive=1; break;
  239. case 'u': flagupper=1; break;
  240. case 'd': flagdot=1; break;
  241. case 't': flagtai=1; break;
  242. case 'f': flagflat=1; break;
  243. case 'T': sep="\t"; break;
  244. default: goto usage;
  245. }
  246. argc--; argv++;
  247. }
  248.  
  249. if (argc<2) {usage: die(1,"usage: prettycache [-AdftTu] data",0,0);}
  250.  
  251. if ((fd=open(argv[1],O_RDONLY)) == -1)
  252. die(21, argv[1], ": open ", "error");
  253. if ((len=lseek(fd,0,SEEK_END)) == (uint32)-1)
  254. die(21, argv[1], ": lseek ", "error");
  255. if ((p=mmap(0,len,PROT_READ,MAP_SHARED,fd,0))==MAP_FAILED)
  256. die(21, "mmap ", "error", 0);
  257. close(fd);
  258.  
  259. tai_now(&now);
  260. pos = 0;
  261.  
  262. while (pos+16 <= len) {
  263. char *a,*b;
  264. uint16 u;
  265.  
  266. uint32_unpack(p + pos, &keylen);
  267. uint32_unpack(p + pos + 4, &datalen);
  268.  
  269. out = 16 + keylen + datalen;
  270. if (pos + out > len) bad_input();
  271. if (keylen < 3 || keylen > 1024) bad_input();
  272. if (datalen > 1000000) bad_input();
  273.  
  274. if (u_time(p + pos + 8)) goto next;
  275. a = p + pos + 16;
  276. b = a + keylen;
  277. uint16_unpack_big(a, &u);
  278. uu=u_misc;
  279.  
  280. switch (u) {
  281. case 1: uu=u_a; type="a"; break;
  282. case 2: uu=u_name; type="ns"; break;
  283. case 5: uu=u_name; type="cname"; break;
  284. case 12: uu=u_name; type="ptr"; break;
  285. case 15: uu=u_mx; type="mx"; break;
  286. case 16: uu=u_txt; type="txt"; break;
  287. case 28: uu=u_aaaa; type="aaaa"; break;
  288. case 33: type="srv"; break;
  289. case 252: type="servfail"; break;
  290. case 255: type="nxdomain"; break;
  291. default: buf[fmt_ulong(buf,u)]=0; type=buf; break;
  292. }
  293.  
  294. outs(type); outs(sep);
  295. u_name(a+2, keylen-2); outs(sep);
  296. uu(b,datalen); outs("\n");
  297. next:
  298. pos += out;
  299. }
  300.  
  301. buffer_flush(buffer_1);
  302. munmap(p,len);
  303. return 0;
  304. }
  305.