djbdnscurve6 45
djbdnscurve6
Loading...
Searching...
No Matches
axfr-get.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "uint_t.h"
3#include "stralloc.h"
4#include "logmsg.h"
5#include "getln.h"
6#include "buffer.h"
7#include "exit.h"
8#include "open.h"
9#include "scan.h"
10#include "byte.h"
11#include "str.h"
12#include "ip.h"
13#include "timeout.h"
14#include "dns.h"
15
16#define WHO "axfr-get"
17
18int rename(const char *,const char *); // keep compiler silent
19
20void die_usage(void)
21{
22 logmsg(WHO,100,USAGE,"axfr-get zone fn fn.tmp");
23}
24void die_generate(void)
25{
26 logmsg(WHO,111,FATAL,"unable to generate AXFR query");
27}
28void die_parse(void)
29{
30 logmsg(WHO,111,FATAL,"unable to parse AXFR results");
31}
32unsigned int x_copy(char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen)
33{
34 pos = dns_packet_copy(buf,len,pos,out,outlen);
35 if (!pos) die_parse();
36 return pos;
37}
38unsigned int x_getname(char *buf,unsigned int len,unsigned int pos,char **out)
39{
40 pos = dns_packet_getname(buf,len,pos,out);
41 if (!pos) die_parse();
42 return pos;
43}
44unsigned int x_skipname(char *buf,unsigned int len,unsigned int pos)
45{
46 pos = dns_packet_skipname(buf,len,pos);
47 if (!pos) die_parse();
48 return pos;
49}
50
51static char *zone;
52unsigned int zonelen;
53char *fn;
54char *fntmp;
55
56void die_netread(void)
57{
58 logmsg(WHO,111,FATAL,"unable to read from network");
59}
60void die_netwrite(void)
61{
62 logmsg(WHO,111,FATAL,"unable to write to network");
63}
64void die_read(void)
65{
66 logmsg(WHO,111,FATAL,B("unable to read: ",fn));
67}
68void die_write(void)
69{
70 logmsg(WHO,111,FATAL,B("unable to write: ",fntmp));
71}
72
73ssize_t saferead(int fd,char *buf,unsigned int len)
74{
75 int r;
76 r = timeoutread(60,fd,buf,len);
77 if (r == 0) { errno = EPROTO; die_parse(); }
78 if (r <= 0) die_netread();
79 return r;
80}
81ssize_t safewrite(int fd,char *buf,unsigned int len)
82{
83 int r;
84 r = timeoutwrite(60,fd,buf,len);
85 if (r <= 0) die_netwrite();
86 return r;
87}
88char netreadspace[1024];
89buffer netread = BUFFER_INIT(saferead,6,netreadspace,sizeof(netreadspace));
90char netwritespace[1024];
91buffer netwrite = BUFFER_INIT(safewrite,7,netwritespace,sizeof(netwritespace));
92
93void netget(char *buf,unsigned int len)
94{
95 int r;
96
97 while (len > 0) {
98 r = buffer_get(&netread,buf,len);
99 buf += r; len -= r;
100 }
101}
102
103int fd;
104buffer b;
105char bspace[1024];
106
107void put(char *buf,unsigned int len)
108{
109 if (buffer_put(&b,buf,len) == -1) die_write();
110}
111
112int printable(char ch)
113{
114 if (ch == '.') return 1;
115 if ((ch >= 'a') && (ch <= 'z')) return 1;
116 if ((ch >= '0') && (ch <= '9')) return 1;
117 if ((ch >= 'A') && (ch <= 'Z')) return 1;
118 if (ch == '-') return 1;
119 return 0;
120}
121
122static char *d1;
123static char *d2;
124static char *d3;
125
126stralloc line;
128
130
131unsigned int doit(char *buf,unsigned int len,unsigned int pos)
132{
133 char data[20];
134 uint32 ttl;
135 uint16 dlen;
136 uint16 typenum;
137 uint32 u32;
138 int i;
139
140 pos = x_getname(buf,len,pos,&d1);
141 pos = x_copy(buf,len,pos,data,10);
142 uint16_unpack_big(data,&typenum);
143 uint32_unpack_big(data + 4,&ttl);
144 uint16_unpack_big(data + 8,&dlen);
145 if (len - pos < dlen) { errno = EPROTO; return 0; }
146 len = pos + dlen;
147
148 if (!dns_domain_suffix(d1,zone)) return len;
149 if (byte_diff(data + 2,2,DNS_C_IN)) return len;
150
151 if (byte_equal(data,2,DNS_T_SOA)) {
152 if (++numsoa >= 2) return len;
153 pos = x_getname(buf,len,pos,&d2);
154 pos = x_getname(buf,len,pos,&d3);
155 x_copy(buf,len,pos,data,20);
156 uint32_unpack_big(data,&u32);
157 if (!stralloc_copys(&line,"#")) return 0;
158 if (!stralloc_catulong0(&line,u32,0)) return 0;
159 if (!stralloc_cats(&line," auto axfr-get\n")) return 0;
160 if (!stralloc_cats(&line,"Z")) return 0;
161 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
162 if (!stralloc_cats(&line,"|")) return 0;
163 if (dns_domain_todot_cat(&line,d2) <= 0) return 0;
164 if (!stralloc_cats(&line,".|")) return 0;
165 if (dns_domain_todot_cat(&line,d3) <= 0) return 0;
166 if (!stralloc_cats(&line,".")) return 0;
167 for (i = 0; i < 5; ++i) {
168 uint32_unpack_big(data + 4 * i,&u32);
169 if (!stralloc_cats(&line,"|")) return 0;
170 if (!stralloc_catulong0(&line,u32,0)) return 0;
171 }
172 }
173 else if (byte_equal(data,2,DNS_T_NS)) {
174 if (!stralloc_copys(&line,"&")) return 0;
175 if (byte_equal(d1,2,"\1*")) { errno = EPROTO; return 0; }
176 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
177 if (!stralloc_cats(&line,"||")) return 0;
178 x_getname(buf,len,pos,&d1);
179 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
180 if (!stralloc_cats(&line,".")) return 0;
181 }
182 else if (byte_equal(data,2,DNS_T_CNAME)) {
183 if (!stralloc_copys(&line,"C")) return 0;
184 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
185 if (!stralloc_cats(&line,"|")) return 0;
186 x_getname(buf,len,pos,&d1);
187 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
188 if (!stralloc_cats(&line,".")) return 0;
189 }
190 else if (byte_equal(data,2,DNS_T_PTR)) {
191 if (!stralloc_copys(&line,"^")) return 0;
192 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
193 if (!stralloc_cats(&line,"|")) return 0;
194 x_getname(buf,len,pos,&d1);
195 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
196 if (!stralloc_cats(&line,".")) return 0;
197 }
198 else if (byte_equal(data,2,DNS_T_MX)) {
199 uint16 dist;
200 if (!stralloc_copys(&line,"@")) return 0;
201 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
202 if (!stralloc_cats(&line,"||")) return 0;
203 pos = x_copy(buf,len,pos,data,2);
204 uint16_unpack_big(data,&dist);
205 x_getname(buf,len,pos,&d1);
206 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
207 if (!stralloc_cats(&line,".|")) return 0;
208 if (!stralloc_catulong0(&line,dist,0)) return 0;
209 }
210 else if (byte_equal(data,2,DNS_T_A) && (dlen == 4)) {
211 char ipstr[IP4_FMT];
212 if (!stralloc_copys(&line,"+")) return 0;
213 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
214 if (!stralloc_cats(&line,"|")) return 0;
215 x_copy(buf,len,pos,data,4);
216 if (!stralloc_catb(&line,ipstr,ip4_fmt(ipstr,data))) return 0;
217 }
218 else if (byte_equal(data,2,DNS_T_AAAA)) {
219 char ipstr[IP6_FMT];
220 if (!stralloc_copys(&line,":")) return 0;
221 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
222 if (!stralloc_cats(&line,"|")) return 0;
223 x_copy(buf,len,pos,data,16);
224 if (!stralloc_catb(&line,ipstr,ip6_fmt(ipstr,data))) return 0;
225 }
226 else {
227 unsigned char ch;
228 unsigned char ch2;
229 if (!stralloc_copys(&line,"|")) return 0;
230 if (dns_domain_todot_cat(&line,d1) <= 0) return 0;
231 if (!stralloc_cats(&line,"|")) return 0;
232 if (!stralloc_catulong0(&line,typenum,0)) return 0;
233 if (!stralloc_cats(&line,"|")) return 0;
234 for (i = 0; i < dlen; ++i) {
235 pos = x_copy(buf,len,pos,data,1);
236 ch = data[0];
237 if (printable(ch)) {
238 if (!stralloc_catb(&line,&ch,1)) return 0;
239 }
240 else {
241 if (!stralloc_cats(&line,"\\")) return 0;
242 ch2 = '0' + ((ch >> 6) & 7);
243 if (!stralloc_catb(&line,&ch2,1)) return 0;
244 ch2 = '0' + ((ch >> 3) & 7);
245 if (!stralloc_catb(&line,&ch2,1)) return 0;
246 ch2 = '0' + (ch & 7);
247 if (!stralloc_catb(&line,&ch2,1)) return 0;
248 }
249 }
250 }
251 if (!stralloc_cats(&line,"|")) return 0;
252 if (!stralloc_catulong0(&line,ttl,0)) return 0;
253 if (!stralloc_cats(&line,"\n")) return 0;
254 put(line.s,line.len);
255
256 return len;
257}
258
259stralloc packet;
260
261int main(int argc,char **argv)
262{
263 char out[20];
264 unsigned long u;
265 uint16 dlen;
266 unsigned int pos;
267 uint32 oldserial = 0;
268 uint32 newserial = 0;
269 uint16 numqueries;
270 uint16 numanswers;
271
272 if (!*argv) die_usage();
273
274 if (!*++argv) die_usage();
275 if (dns_domain_fromdot(&zone,*argv,str_len(*argv)) <= 0) die_generate();
277
278 if (!*++argv) die_usage();
279 fn = *argv;
280 if (!*++argv) die_usage();
281 fntmp = *argv;
282
283 fd = open_read(fn);
284 if (fd == -1) {
285 if (errno != ENOENT) die_read();
286 }
287 else {
288 buffer_init(&b,buffer_unixread,fd,bspace,sizeof(bspace));
289 if (getln(&b,&line,&match,'\n') == -1) die_read();
290 if (!stralloc_0(&line)) die_read();
291 if (line.s[0] == '#') {
292 scan_ulong(line.s + 1,&u);
293 oldserial = u;
294 }
295 close(fd);
296 }
297
298 if (!stralloc_copyb(&packet,"\0\0\0\0\0\1\0\0\0\0\0\0",12)) die_generate();
299 if (!stralloc_catb(&packet,zone,zonelen)) die_generate();
300 if (!stralloc_catb(&packet,DNS_T_SOA DNS_C_IN,4)) die_generate();
301 uint16_pack_big(out,packet.len);
302 buffer_put(&netwrite,out,2);
303 buffer_put(&netwrite,packet.s,packet.len);
304 buffer_flush(&netwrite);
305
306 netget(out,2);
307 uint16_unpack_big(out,&dlen);
308 if (!stralloc_ready(&packet,dlen)) die_parse();
309 netget(packet.s,dlen);
310 packet.len = dlen;
311
312 pos = x_copy(packet.s,packet.len,0,out,12);
313 uint16_unpack_big(out + 4,&numqueries);
314 uint16_unpack_big(out + 6,&numanswers);
315
316 while (numqueries) {
317 --numqueries;
318 pos = x_skipname(packet.s,packet.len,pos);
319 pos += 4;
320 }
321
322 if (!numanswers) { errno = EPROTO; die_parse(); }
323 pos = x_getname(packet.s,packet.len,pos,&d1);
324 if (!dns_domain_equal(zone,d1)) { errno = EPROTO; die_parse(); }
325 pos = x_copy(packet.s,packet.len,pos,out,10);
326 if (byte_diff(out,4,DNS_T_SOA DNS_C_IN)) { errno = EPROTO; die_parse(); }
327 pos = x_skipname(packet.s,packet.len,pos);
328 pos = x_skipname(packet.s,packet.len,pos);
329 pos = x_copy(packet.s,packet.len,pos,out,4);
330
331 uint32_unpack_big(out,&newserial);
332
333
334 if (oldserial && newserial) /* allow 0 for very recently modified zones */
335 if (oldserial == newserial) /* allow serial numbers to move backwards */
336 _exit(0);
337
338
339 fd = open_trunc(fntmp);
340 if (fd == -1) die_write();
341 buffer_init(&b,buffer_unixwrite,fd,bspace,sizeof(bspace));
342
343 if (!stralloc_copyb(&packet,"\0\0\0\0\0\1\0\0\0\0\0\0",12)) die_generate();
344 if (!stralloc_catb(&packet,zone,zonelen)) die_generate();
345 if (!stralloc_catb(&packet,DNS_T_AXFR DNS_C_IN,4)) die_generate();
346 uint16_pack_big(out,packet.len);
347 buffer_put(&netwrite,out,2);
348 buffer_put(&netwrite,packet.s,packet.len);
349 buffer_flush(&netwrite);
350
351 numsoa = 0;
352 while (numsoa < 2) {
353 netget(out,2);
354 uint16_unpack_big(out,&dlen);
355 if (!stralloc_ready(&packet,dlen)) die_parse();
356 netget(packet.s,dlen);
357 packet.len = dlen;
358
359 pos = x_copy(packet.s,packet.len,0,out,12);
360 uint16_unpack_big(out + 4,&numqueries);
361
362 while (numqueries) {
363 --numqueries;
364 pos = x_skipname(packet.s,packet.len,pos);
365 pos += 4;
366 }
367 while (pos < packet.len) {
368 pos = doit(packet.s,packet.len,pos);
369 if (!pos) die_parse();
370 }
371 }
372
373 if (buffer_flush(&b) == -1) die_write();
374 if (fsync(fd) == -1) die_write();
375 if (close(fd) == -1) die_write(); /* NFS dorks */
376 if (rename(fntmp,fn) == -1)
377 logmsg(WHO,111,FATAL,B("unable to move ",fntmp," to: ",fn));
378 _exit(0);
379}
void die_write(void)
Definition: axfr-get.c:68
char * fntmp
Definition: axfr-get.c:54
char bspace[1024]
Definition: axfr-get.c:105
void die_usage(void)
Definition: axfr-get.c:20
int printable(char ch)
Definition: axfr-get.c:112
void put(char *buf, unsigned int len)
Definition: axfr-get.c:107
unsigned int x_getname(char *buf, unsigned int len, unsigned int pos, char **out)
Definition: axfr-get.c:38
int rename(const char *, const char *)
char netwritespace[1024]
Definition: axfr-get.c:90
void die_netwrite(void)
Definition: axfr-get.c:60
unsigned int x_skipname(char *buf, unsigned int len, unsigned int pos)
Definition: axfr-get.c:44
void die_netread(void)
Definition: axfr-get.c:56
buffer b
Definition: axfr-get.c:104
unsigned int x_copy(char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
Definition: axfr-get.c:32
void die_read(void)
Definition: axfr-get.c:64
stralloc packet
Definition: axfr-get.c:259
int fd
Definition: axfr-get.c:103
ssize_t saferead(int fd, char *buf, unsigned int len)
Definition: axfr-get.c:73
void die_parse(void)
Definition: axfr-get.c:28
unsigned int zonelen
Definition: axfr-get.c:52
ssize_t safewrite(int fd, char *buf, unsigned int len)
Definition: axfr-get.c:81
void netget(char *buf, unsigned int len)
Definition: axfr-get.c:93
stralloc line
Definition: axfr-get.c:126
void die_generate(void)
Definition: axfr-get.c:24
char * fn
Definition: axfr-get.c:53
unsigned int doit(char *buf, unsigned int len, unsigned int pos)
Definition: axfr-get.c:131
buffer netread
Definition: axfr-get.c:89
int match
Definition: axfr-get.c:127
char netreadspace[1024]
Definition: axfr-get.c:88
buffer netwrite
Definition: axfr-get.c:91
#define WHO
Definition: axfr-get.c:16
int numsoa
Definition: axfr-get.c:129
char data[32767]
Definition: axfrdns.c:130
uint16 len
Definition: axfrdns.c:319
char buf[MSGSIZE]
Definition: axfrdns.c:318
int main()
Definition: axfrdns.c:323
uint32 dlen
Definition: axfrdns.c:131
#define DNS_T_A
Definition: dns.h:56
#define DNS_T_AXFR
Definition: dns.h:84
#define DNS_C_IN
Definition: dns.h:53
#define DNS_T_PTR
Definition: dns.h:60
#define DNS_T_SOA
Definition: dns.h:59
#define DNS_T_NS
Definition: dns.h:57
#define DNS_T_CNAME
Definition: dns.h:58
#define DNS_T_AAAA
Definition: dns.h:67
#define DNS_T_MX
Definition: dns.h:62
int dns_domain_fromdot(char **out, const char *buf, unsigned int n)
Definition: dns_dfd.c:6
int dns_domain_equal(const char *dn1, const char *dn2)
Definition: dns_domain.c:39
unsigned int dns_domain_length(const char *dn)
Definition: dns_domain.c:6
int dns_domain_suffix(const char *big, const char *little)
Definition: dns_domain.c:50
int dns_domain_todot_cat(stralloc *out, const char *d)
Definition: dns_dtda.c:11
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
Definition: dns_packet.c:35
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
Definition: dns_packet.c:8
unsigned int dns_packet_skipname(const char *buf, unsigned int len, unsigned int pos)
Definition: dns_packet.c:18
uint64 numqueries
Definition: dnscache.c:68
char ipstr[IP6_FMT]
Definition: dnstrace.c:31
void out(const char *s, unsigned int len)
Definition: generic-conf.c:54
uint32 u32
Definition: siphash.c:25
Definition: dnsfilter.c:23
unsigned long u
Definition: utime.c:10