1 #include "uint16_unpack_big.h"
2 #include "uint32_unpack_big.h"
3 #include "e.h"
4 #include "byte.h"
5 #include "dns.h"
6 #include "printrecord.h"
7 #include "iptostr.h"
8 
9 static unsigned char *d = 0;
10 
printrecord_cat(stralloc * out,const unsigned char * buf,long long len,long long pos,const unsigned char * q,const unsigned char qtype[2])11 long long printrecord_cat(stralloc *out,const unsigned char *buf,long long  len,long long pos,const unsigned char *q,const unsigned char qtype[2])
12 {
13   const unsigned char *x;
14   unsigned char misc[20];
15   crypto_uint16 datalen;
16   crypto_uint16 u16;
17   crypto_uint32 u32;
18   long long  newpos;
19   long long i;
20   unsigned char ch;
21   long long txtlen;
22 
23   pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
24   pos = dns_packet_copy(buf,len,pos,misc,10); if (!pos) return 0;
25   datalen = uint16_unpack_big(misc + 8);
26   newpos = pos + datalen;
27 
28   if (q) {
29     if (!dns_domain_equal(d,q))
30       return newpos;
31     if (!byte_isequal(qtype,2,misc) && !byte_isequal(qtype,2,DNS_T_ANY))
32       return newpos;
33   }
34 
35   if (!dns_domain_todot_cat(out,d)) return 0;
36   if (!stralloc_cats(out," ")) return 0;
37   u32 = uint32_unpack_big(misc + 4);
38   if (!stralloc_catnum(out,u32)) return 0;
39 
40   if (!byte_isequal(misc + 2,2,DNS_C_IN)) {
41     if (!stralloc_cats(out," weird class\n")) return 0;
42     return newpos;
43   }
44 
45   x = 0;
46   if (byte_isequal(misc,2,DNS_T_NS)) x = (unsigned char *)" NS ";
47   if (byte_isequal(misc,2,DNS_T_PTR)) x = (unsigned char *)" PTR ";
48   if (byte_isequal(misc,2,DNS_T_CNAME)) x = (unsigned char *)" CNAME ";
49   if (x) {
50     pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
51     if (!stralloc_cats(out,x)) return 0;
52     if (!dns_domain_todot_cat(out,d)) return 0;
53   }
54   else if (byte_isequal(misc,2,DNS_T_MX)) {
55     if (!stralloc_cats(out," MX ")) return 0;
56     pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0;
57     pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
58     u16 = uint16_unpack_big(misc);
59     if (!stralloc_catnum(out,u16)) return 0;
60     if (!stralloc_cats(out," ")) return 0;
61     if (!dns_domain_todot_cat(out,d)) return 0;
62   }
63   else if (byte_isequal(misc,2,DNS_T_SOA)) {
64     if (!stralloc_cats(out," SOA ")) return 0;
65     pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
66     if (!dns_domain_todot_cat(out,d)) return 0;
67     if (!stralloc_cats(out," ")) return 0;
68     pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
69     if (!dns_domain_todot_cat(out,d)) return 0;
70     pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) return 0;
71     for (i = 0;i < 5;++i) {
72       if (!stralloc_cats(out," ")) return 0;
73       u32 = uint32_unpack_big(misc + 4 * i);
74       if (!stralloc_catnum(out,u32)) return 0;
75     }
76   }
77   else if (byte_isequal(misc,2,DNS_T_AAAA)) {
78     if (datalen != 16) { errno = EPROTO; return 0; }
79     if (!stralloc_cats(out," AAAA ")) return 0;
80     pos = dns_packet_copy(buf,len,pos,misc,16); if (!pos) return 0;
81     if (!stralloc_cats(out,iptostr(0, misc))) return 0;
82   }
83   else if (byte_isequal(misc,2,DNS_T_TXT)) {
84     if (pos + datalen > len) return -1;
85     if (!stralloc_cats(out," TXT ")) return 0;
86     txtlen = 0;
87     for (i = 0;i < datalen;++i) {
88       ch = buf[pos + i];
89       if (!txtlen)
90         txtlen = ch;
91       else {
92         --txtlen;
93         if (ch < 32 || ch > 126) {
94           misc[3] = '0' + (7 & ch); ch >>= 3;
95           misc[2] = '0' + (7 & ch); ch >>= 3;
96           misc[1] = '0' + (7 & ch);
97           misc[0] = '\\';
98           if (!stralloc_catb(out,misc,4)) return 0;
99         }
100         else {
101           if (!stralloc_append(out,&ch)) return -1;
102         }
103       }
104     }
105     pos += datalen;
106   }
107   else if (byte_isequal(misc,2,DNS_T_SRV)) {
108     if (!stralloc_cats(out," SRV ")) return 0;
109     pos = dns_packet_copy(buf,len,pos,misc,6); if (!pos) return 0;
110     u16 = uint16_unpack_big(misc);
111     if (!stralloc_catnum(out,u16)) return 0;
112     if (!stralloc_cats(out," ")) return 0;
113     u16 = uint16_unpack_big(misc + 2);
114     if (!stralloc_catnum(out,u16)) return 0;
115     if (!stralloc_cats(out," ")) return 0;
116     u16 = uint16_unpack_big(misc + 4);
117     if (!stralloc_catnum(out,u16)) return 0;
118     if (!stralloc_cats(out," ")) return 0;
119     pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0;
120     if (!dns_domain_todot_cat(out,d)) return 0;
121   }
122   else if (byte_isequal(misc,2,DNS_T_A)) {
123     if (datalen != 4) { errno = EPROTO; return 0; }
124     if (!stralloc_cats(out," A ")) return 0;
125     pos = dns_packet_copy(buf,len,pos,misc,4); if (!pos) return 0;
126     for (i = 0;i < 4;++i) {
127       ch = misc[i];
128       if (i) if (!stralloc_cats(out,".")) return 0;
129       if (!stralloc_catnum(out,ch)) return 0;
130     }
131   }
132   else {
133     if (!stralloc_cats(out," ")) return 0;
134     u16 = uint16_unpack_big(misc);
135     if (!stralloc_catnum(out,u16)) return 0;
136     if (!stralloc_cats(out," ")) return 0;
137     while (datalen--) {
138       pos = dns_packet_copy(buf,len,pos,misc,1); if (!pos) return 0;
139       if ((misc[0] >= 33) && (misc[0] <= 126) && (misc[0] != '\\')) {
140         if (!stralloc_catb(out,misc,1)) return 0;
141       }
142       else {
143         ch = misc[0];
144         misc[3] = '0' + (7 & ch); ch >>= 3;
145         misc[2] = '0' + (7 & ch); ch >>= 3;
146         misc[1] = '0' + (7 & ch);
147         misc[0] = '\\';
148         if (!stralloc_catb(out,misc,4)) return 0;
149       }
150     }
151   }
152 
153   if (!stralloc_cats(out,"\n")) return 0;
154   if (pos != newpos) { errno = EPROTO; return 0; }
155   return newpos;
156 }
157 
printrecord(stralloc * out,const unsigned char * buf,long long len,long long pos,const unsigned char * q,const unsigned char qtype[2])158 long long printrecord(stralloc *out,const unsigned char *buf,long long len,long long pos,const unsigned char *q,const unsigned char qtype[2])
159 {
160   if (!stralloc_copys(out,"")) return 0;
161   return printrecord_cat(out,buf,len,pos,q,qtype);
162 }
163