10
#include "timeoutread.h"
11
#include "timeoutwrite.h"
25
extern int respond(char *,char *,char *);
27
#define FATAL "axfrdns: fatal: "
31
strerr_die2x(111,FATAL,"out of memory");
35
strerr_die2x(111,FATAL,"truncated request");
39
strerr_die2sys(111,FATAL,"unable to write to network: ");
43
strerr_die2sys(111,FATAL,"unable to read from network: ");
47
strerr_die2x(111,FATAL,"unable to locate information in data.cdb");
51
strerr_die2sys(111,FATAL,"unable to read data.cdb: ");
55
strerr_die3x(111,FATAL,"unable to read data.cdb: ","format error");
58
int safewrite(int fd,char *buf,unsigned int len)
62
w = timeoutwrite(60,fd,buf,len);
63
if (w <= 0) die_netwrite();
67
char netwritespace[1024];
68
buffer netwrite = BUFFER_INIT(safewrite,1,netwritespace,sizeof netwritespace);
70
void print(char *buf,unsigned int len)
73
uint16_pack_big(tcpheader,len);
74
buffer_put(&netwrite,tcpheader,2);
75
buffer_put(&netwrite,buf,len);
76
buffer_flush(&netwrite);
82
void axfrcheck(char *q)
91
if (!axfr[i] || (axfr[i] == '/')) {
93
if (!dns_domain_fromdot(&axfrok,axfr + j,i - j)) nomem();
94
if (dns_domain_equal(q,axfrok)) return;
102
strerr_die2x(111,FATAL,"disallowed zone transfer request");
106
unsigned int zonelen;
111
char bcdbspace[1024];
113
void get(char *buf,unsigned int len)
118
r = buffer_get(&bcdb,buf,len);
119
if (r < 0) die_cdbread();
120
if (!r) die_cdbformat();
135
void copy(char *buf,unsigned int len)
137
dpos = dns_packet_copy(data,dlen,dpos,buf,len);
138
if (!dpos) die_cdbread();
141
void doname(stralloc *sa)
144
dpos = dns_packet_getname(data,dlen,dpos,&d);
145
if (!dpos) die_cdbread();
146
if (!stralloc_catb(sa,d,dns_domain_length(d))) nomem();
149
int build(stralloc *sa,char *q,int flagsoa,char id[2])
151
unsigned int rdatapos;
161
if (flagsoa) if (byte_diff(type,2,DNS_T_SOA)) return 0;
162
if (!flagsoa) if (byte_equal(type,2,DNS_T_SOA)) return 0;
164
if (!stralloc_copyb(sa,id,2)) nomem();
165
if (!stralloc_catb(sa,"\204\000\0\0\0\1\0\0\0\0",10)) nomem();
167
if ((misc[0] == '=' + 1) || (misc[0] == '*' + 1)) {
170
if (byte_diff(recordloc,2,clientloc)) return 0;
172
if (misc[0] == '*') {
173
if (flagsoa) return 0;
174
if (!stralloc_catb(sa,"\1*",2)) nomem();
176
if (!stralloc_catb(sa,q,dns_domain_length(q))) nomem();
177
if (!stralloc_catb(sa,type,2)) nomem();
181
if (byte_diff(ttd,8,"\0\0\0\0\0\0\0\0")) {
182
tai_unpack(ttd,&cutoff);
183
if (byte_equal(ttl,4,"\0\0\0\0")) {
184
if (tai_less(&cutoff,&now)) return 0;
185
uint32_pack_big(ttl,2);
188
if (!tai_less(&cutoff,&now)) return 0;
191
if (!stralloc_catb(sa,DNS_C_IN,2)) nomem();
192
if (!stralloc_catb(sa,ttl,4)) nomem();
193
if (!stralloc_catb(sa,"\0\0",2)) nomem();
196
if (byte_equal(type,2,DNS_T_SOA)) {
200
if (!stralloc_catb(sa,misc,20)) nomem();
202
else if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_PTR) || byte_equal(type,2,DNS_T_CNAME)) {
205
else if (byte_equal(type,2,DNS_T_MX)) {
207
if (!stralloc_catb(sa,misc,2)) nomem();
211
if (!stralloc_catb(sa,data + dpos,dlen - dpos)) nomem();
213
if (sa->len > 65535) die_cdbformat();
214
uint16_pack_big(sa->s + rdatapos - 2,sa->len - rdatapos);
221
static stralloc message;
223
void doaxfr(char id[2])
237
byte_zero(clientloc,2);
240
byte_copy(key + 2,4,ip);
241
r = cdb_find(&c,key,6);
242
if (!r) r = cdb_find(&c,key,5);
243
if (!r) r = cdb_find(&c,key,4);
244
if (!r) r = cdb_find(&c,key,3);
245
if (!r) r = cdb_find(&c,key,2);
246
if (r == -1) die_cdbread();
247
if (r && (cdb_datalen(&c) == 2))
248
if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) die_cdbread();
252
r = cdb_findnext(&c,zone,zonelen);
253
if (r == -1) die_cdbread();
254
if (!r) die_outside();
255
dlen = cdb_datalen(&c);
256
if (dlen > sizeof data) die_cdbformat();
257
if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) die_cdbformat();
258
if (build(&soa,zone,1,id)) break;
262
print(soa.s,soa.len);
265
buffer_init(&bcdb,buffer_unixread,fdcdb,bcdbspace,sizeof bcdbspace);
268
get(num,4); pos += 4;
269
uint32_unpack(num,&eod);
270
while (pos < 2048) { get(num,4); pos += 4; }
273
if (eod - pos < 8) die_cdbformat();
274
get(num,4); pos += 4;
275
uint32_unpack(num,&klen);
276
get(num,4); pos += 4;
277
uint32_unpack(num,&dlen);
278
if (eod - pos < klen) die_cdbformat();
280
if (eod - pos < dlen) die_cdbformat();
283
if (klen > sizeof key) die_cdbformat();
285
if (dlen > sizeof data) die_cdbformat();
288
if ((klen > 1) && (key[0] == 0)) continue; /* location */
289
if (klen < 1) die_cdbformat();
290
if (dns_packet_getname(key,klen,0,&q) != klen) die_cdbformat();
291
if (!dns_domain_suffix(q,zone)) continue;
292
if (!build(&message,q,0,id)) continue;
293
print(message.s,message.len);
296
print(soa.s,soa.len);
299
void netread(char *buf,unsigned int len)
304
r = timeoutread(60,0,buf,len);
305
if (r == 0) _exit(0);
306
if (r < 0) die_netread();
315
static char seed[128];
326
dns_random_init(seed);
328
axfr = env_get("AXFR");
330
x = env_get("TCPREMOTEIP");
331
if (x && ip4_scan(x,ip))
336
x = env_get("TCPREMOTEPORT");
341
netread(tcpheader,2);
342
uint16_unpack_big(tcpheader,&len);
343
if (len > 512) strerr_die2x(111,FATAL,"excessively large request");
346
pos = dns_packet_copy(buf,len,0,header,12); if (!pos) die_truncated();
347
if (header[2] & 254) strerr_die2x(111,FATAL,"bogus query");
348
if (header[4] || (header[5] != 1)) strerr_die2x(111,FATAL,"bogus query");
350
pos = dns_packet_getname(buf,len,pos,&zone); if (!pos) die_truncated();
351
zonelen = dns_domain_length(zone);
352
pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) die_truncated();
353
pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) die_truncated();
355
if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY))
356
strerr_die2x(111,FATAL,"bogus query: bad class");
358
qlog(ip,port,header,zone,qtype," ");
360
if (byte_equal(qtype,2,DNS_T_AXFR)) {
361
case_lowerb(zone,zonelen);
362
fdcdb = open_read("data.cdb");
363
if (fdcdb == -1) die_cdbread();
368
if (!response_query(zone,qtype,qclass)) nomem();
370
case_lowerb(zone,zonelen);
373
if (!(header[2] & 1)) response[2] &= ~1;
374
if (!respond(zone,qtype,ip)) die_outside();
375
print(response,response_len);