/* prettycache.c diet -Os gcc -s -o prettycache prettycache.c -Wall -W -lowfat http://riemann.fmi.uni-sofia.bg/ or in ./djbdns-1.05/ with: ./compile prettycache.c ./load prettycache buffer.a byte.a libtai.a unix.a */ #include #include #include #include #include "tai.h" #include "buffer.h" #include "uint32.h" #include "uint16.h" #include "fmt.h" #define outs(x) buffer_puts(buffer_1,x) #define out(x,y) buffer_put(buffer_1,x,y) int outu(uint32 u) {char tmp[12]; return out(tmp,fmt_ulong(tmp,u));} static uint32 pos; static int flagdot, flagupper, flagtai, flagflat, flagalive; struct tai now; char hex[16] = "0123456789abcdef"; void die(int n, const char *s1, const char *s2, const char *s3) { buffer_flush(buffer_1); 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); } void bad_input() { char tmp[12]; tmp[fmt_ulong(tmp, pos)]=0; die(111,"\n\ntruncated input near to ", tmp, " position"); } void u_octal(unsigned char ch) { char buf[4]; buf[3] = '0' + (ch & 7); ch >>= 3; buf[2] = '0' + (ch & 7); ch >>= 3; buf[1] = '0' + (ch & 7); buf[0] = '\\'; out(buf,4); } int dns_dtodot(const char *d, uint32 len) { char ch, ch2; int total=0; if (!len) return 0; if (!*d) { outs("."); return 1; } for (;len;) { ch = *d++; total++; len--; while (len && ch--) { ch2 = *d++; total++; len--; if (!flagupper) if ((ch2 >= 'A') && (ch2 <= 'Z')) ch2 += 32; if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_') || ((ch2 >= 'A') && (ch2 <= 'Z'))) { out(&ch2,1); } else u_octal((unsigned char)ch2); } if (len && !*d) { if (flagdot) out(".",1); return ++total; } out(".",1); } return -1; } void u_misc(char *s, uint32 len) { char *a=s, *end=a+len; while(a> 4) & 15), 1); out(hex + ((a[0]) & 15), 1); ++a; } } void u_a(char *s, uint32 len) { char *a=s, *end=a+len; while(a+4<=end) { int i=0; for(i=0; i<4; i++) { outu((uint32)(unsigned char)a[i]); if (i<3) outs("."); } a += 4; if (a+4 <= end) outs(" "); } } void u_hex(unsigned char *p) { char x[4]; int i; x[0]=hex[p[0] >> 4]; x[1]=hex[p[0] & 15]; x[2]=hex[p[1] >> 4]; x[3]=hex[p[1] & 15]; for (i=0; i<3 && x[i]=='0';) i++; out(x+i, 4-i); } void u_ip6(unsigned char *ip) { int k, p0,len0, p1,len1, compr; for (k=0, p0=0,len0=0, p1=0, compr=0; k<16; k+=2) { if (ip[k]==0 && ip[k+1]==0) { if (!compr) { compr=1; p1=k; } if (k==14) { k=16; goto last; } } else if (compr) { last: if ((len1 = k-p1) > len0) { len0=len1; p0=p1; } compr=0; } } for (k=0; k<16; k+=2) { if (p0 == k && len0) { out("::", 1 + !p0); k += len0-2; continue; } u_hex(ip + k); if (k<14) outs(":"); } } void u_aaaa(char *s, uint32 len) { char *end = s + len; while (s+18 <= end) { if (flagflat) u_misc(s+2,16); else u_ip6((unsigned char*)s+2); s += 18; if (s+18 <= end) outs(" "); } } void u_txt(char *a, uint32 len) { unsigned int txtlen,i; txtlen=0; for (i = 2;i < len;++i) { char ch = a[i]; if (!txtlen) txtlen = (unsigned char) ch; else { --txtlen; if (ch < 32 || ch > 126) u_octal((unsigned char)ch); else out(&ch,1); } } if (txtlen) bad_input(); } void u_name(char *s, uint32 len) { char *a=s, *end=a+len; unsigned long r; while(a1 && argv[1][0] == '-') { for (p=argv[1]+1; *p; p++) switch (*p) { case 'A': flagalive=1; break; case 'u': flagupper=1; break; case 'd': flagdot=1; break; case 't': flagtai=1; break; case 'f': flagflat=1; break; case 'T': sep="\t"; break; default: goto usage; } argc--; argv++; } if (argc<2) {usage: die(1,"usage: prettycache [-AdftTu] data",0,0);} 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); tai_now(&now); pos = 0; while (pos+16 <= len) { char *a,*b; uint16 u; uint32_unpack(p + pos, &keylen); uint32_unpack(p + pos + 4, &datalen); out = 16 + keylen + datalen; if (pos + out > len) bad_input(); if (keylen < 3 || keylen > 1024) bad_input(); if (datalen > 1000000) bad_input(); if (u_time(p + pos + 8)) goto next; a = p + pos + 16; b = a + keylen; uint16_unpack_big(a, &u); uu=u_misc; switch (u) { case 1: uu=u_a; type="a"; break; case 2: uu=u_name; type="ns"; break; case 5: uu=u_name; type="cname"; break; case 12: uu=u_name; type="ptr"; break; case 15: uu=u_mx; type="mx"; break; case 16: uu=u_txt; type="txt"; break; case 28: uu=u_aaaa; type="aaaa"; break; case 33: type="srv"; break; case 252: type="servfail"; break; case 255: type="nxdomain"; break; default: buf[fmt_ulong(buf,u)]=0; type=buf; break; } outs(type); outs(sep); u_name(a+2, keylen-2); outs(sep); uu(b,datalen); outs("\n"); next: pos += out; } buffer_flush(buffer_1); munmap(p,len); return 0; }