23 logmsg(
WHO,111,FATAL,
"out of memory");
27 logmsg(
WHO,100,USAGE,
"dnstrace type name rootip ...");
33static stralloc querystr;
39 if (!stralloc_copys(&
tmp,
""))
nomem();
41 buffer_put(buffer_1,
tmp.s,
tmp.len);
54 char qflags[2] = { 0, 0 };
65 taia_uint(&deadline,120);
66 taia_add(&deadline,&deadline,&stamp);
68 r = iopause(
x,1,&deadline,&stamp);
75 taia_sub(&stamp,&stamp,&
start);
76 taia_uint(&deadline,1);
77 if (taia_less(&deadline,&stamp)) {
78 buffer_put(buffer_1,querystr.s,querystr.len);
79 buffer_puts(buffer_1,
"ALERT|took more than 1 second\n");
91GEN_ALLOC_readyplus(address_alloc,
struct address,s,
len,a,i,n,
x,30,address_alloc_readyplus)
92GEN_ALLOC_append(address_alloc,
struct address,s,
len,a,i,n,
x,30,address_alloc_readyplus,address_alloc_append)
102GEN_ALLOC_readyplus(ns_alloc,
struct ns,s,
len,a,i,n,
x,30,ns_alloc_readyplus)
103GEN_ALLOC_append(ns_alloc,
struct ns,s,
len,a,i,n,
x,30,ns_alloc_readyplus,ns_alloc_append)
113GEN_ALLOC_readyplus(query_alloc,
struct query,s,
len,a,i,n,
x,30,query_alloc_readyplus)
114GEN_ALLOC_append(query_alloc,
struct query,s,
len,a,i,n,
x,30,query_alloc_readyplus,query_alloc_append)
116static query_alloc
query;
126GEN_ALLOC_readyplus(qt_alloc,
struct qt,s,
len,a,i,n,
x,30,qt_alloc_readyplus)
127GEN_ALLOC_append(qt_alloc,
struct qt,s,
len,a,i,n,
x,30,qt_alloc_readyplus,qt_alloc_append)
131void qt_add(
const char *q,
const char type[2],
const char *control,
const char ip[16])
138 for (i = 0; i < qt.len; ++i)
141 if (byte_equal(qt.s[i].type,2,
type))
142 if (byte_equal(qt.s[i].ip,16,
ip))
145 byte_zero((
char *)&
x,
sizeof(
x));
148 byte_copy(
x.type,2,
type);
149 byte_copy(
x.ip,16,
ip);
150 if (!qt_alloc_append(&qt,&
x))
nomem();
159 for (i = 0; i <
query.len; ++i)
164 byte_zero((
char *)&
x,
sizeof(
x));
166 byte_copy(
x.type,2,
type);
169 for (i = 0; i <
ns.len; ++i)
171 for (j = 0; j <
address.len; ++j)
182 buffer_put(buffer_1,querystr.s,querystr.len);
183 buffer_puts(buffer_1,
"NS|");
185 buffer_puts(buffer_1,
"|");
187 buffer_puts(buffer_1,
"\n");
189 for (i = 0; i < ns.len; ++i)
197 byte_zero((
char *)&
x,
sizeof(
x));
200 if (!ns_alloc_append(&ns,&
x))
nomem();
202 for (i = 0; i <
query.len; ++i)
204 for (j = 0; j <
address.len; ++j)
216 scan_dnum(querystr.s,&
type);
217 buffer_put(buffer_1,querystr.s,querystr.len);
218 buffer_puts(buffer_1,
"A/AAAA|");
220 buffer_puts(buffer_1,
"|");
221 if (ip6_isv4mapped(
ip)) {
226 buffer_puts(buffer_1,
"\n");
228 for (i = 0; i <
address.len; ++i)
233 byte_zero((
char *)&
x,
sizeof(
x));
235 byte_copy(
x.ip,16,
ip);
238 for (i = 0; i < ns.len; ++i)
240 for (j = 0; j <
query.len; ++j)
249static char *referral;
252static int typematch(
const char rtype[2],
const char qtype[2])
254 return byte_equal(qtype,2,rtype) || byte_equal(qtype,2,
DNS_T_ANY);
257void parsepacket(
const char *
buf,
unsigned int len,
const char *d,
const char dtype[2],
const char *control)
263 unsigned int posanswers;
279 uint16_unpack_big(header + 6,&numanswers);
280 uint16_unpack_big(header + 8,&numauthority);
281 uint16_unpack_big(header + 10,&numglue);
283 rcode = header[3] & 15;
284 if (rcode && (rcode != 3)) { errno = EPROTO;
goto DIE; }
291 for (j = 0; j < numanswers; ++j) {
295 if (byte_equal(header + 2,2,
DNS_C_IN))
296 if (typematch(header,dtype))
304 uint16_unpack_big(header + 8,&datalen);
307 for (j = 0; j < numauthority; ++j) {
312 else if (typematch(header,
DNS_T_NS)) {
316 uint16_unpack_big(header + 8,&datalen);
320 if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
322 buffer_put(buffer_1,querystr.s,querystr.len);
323 buffer_puts(buffer_1,
"ALERT|lame server; refers to ");
325 buffer_puts(buffer_1,
"\n");
330 for (j = 0;j < numanswers + numauthority + numglue;++j) {
333 uint16_unpack_big(header + 8,&datalen);
335 if (byte_equal(header + 2,2,
DNS_C_IN)) {
340 else if (typematch(header,
DNS_T_A) && datalen == 4) {
342 byte_copy(misc,12,V4mappedprefix);
345 else if (typematch(header,
DNS_T_AAAA) && datalen == 16) {
356 buffer_put(buffer_1,querystr.s,querystr.len);
357 buffer_puts(buffer_1,
"CNAME|");
359 buffer_puts(buffer_1,
"\n");
363 buffer_put(buffer_1,querystr.s,querystr.len);
364 buffer_puts(buffer_1,
"NXDOMAIN\n");
367 if (flagout || flagsoa || !flagreferral) {
369 buffer_put(buffer_1,querystr.s,querystr.len);
370 buffer_puts(buffer_1,
"NODATA\n");
374 for (j = 0; j < numanswers + numauthority + numglue; ++j) {
378 buffer_put(buffer_1,querystr.s,querystr.len);
379 buffer_puts(buffer_1,
"answer|");
380 buffer_put(buffer_1,
tmp.s,
tmp.len);
387 buffer_put(buffer_1,querystr.s,querystr.len);
388 buffer_puts(buffer_1,
"see|");
390 buffer_puts(buffer_1,
"\n");
395 buffer_put(buffer_1,querystr.s,querystr.len);
396 buffer_puts(buffer_1,
"ALERT|unable to parse response packet; ");
397 buffer_puts(buffer_1,
x);
398 buffer_puts(buffer_1,
"\n");
403 static stralloc ipout;
404 static stralloc fqdn;
415 if (!stralloc_copys(&querystr,
"0|.|.|start|"))
nomem();
418 if (!query_alloc_readyplus(&
query,1))
nomem();
419 if (!ns_alloc_readyplus(&ns,1))
nomem();
420 if (!qt_alloc_readyplus(&qt,1))
nomem();
423 if (!*++argv)
usage();
426 if (!*++argv)
usage();
433 if (!stralloc_copys(&udn,*argv))
nomem();
435 for (i = 0; i + 16 <= ipout.len; i += 16)
439 for (i = 0; i < qt.len; ++i) {
441 control = qt.s[i].control;
443 byte_copy(
type,2,qt.s[i].type);
444 byte_copy(
ip,16,qt.s[i].ip);
446 if (!stralloc_copys(&querystr,
""))
nomem();
447 uint16_unpack_big(
type,&u16);
448 if (!stralloc_catulong0(&querystr,u16,0))
nomem();
449 if (!stralloc_cats(&querystr,
"|"))
nomem();
451 if (!stralloc_cats(&querystr,
"|"))
nomem();
453 if (!stralloc_cats(&querystr,
"|"))
nomem();
454 if (ip6_isv4mapped(
ip)) {
458 if (!stralloc_cats(&querystr,
"|"))
nomem();
460 buffer_put(buffer_1,querystr.s,querystr.len);
461 buffer_puts(buffer_1,
"tx\n");
462 buffer_flush(buffer_1);
465 const char *
x = errstr(errno);
466 buffer_put(buffer_1,querystr.s,querystr.len);
467 buffer_puts(buffer_1,
"ALERT|query failed; ");
468 buffer_puts(buffer_1,
x);
469 buffer_puts(buffer_1,
"\n");
475 buffer_put(buffer_1,querystr.s,querystr.len);
476 buffer_puts(buffer_1,
"ALERT|some caches do not handle localhost internally\n");
477 address_add(q,
"\0\0\0\0\0\0\0\0\0\0\0\0\177\0\0\1");
480 buffer_put(buffer_1,querystr.s,querystr.len);
481 buffer_puts(buffer_1,
"ALERT|some caches do not handle localhost internally\n");
482 address_add(q,
"\0\0\0\0\0\0\0\0\0\0\0\0\177\0\0\1");
485 buffer_put(buffer_1,querystr.s,querystr.len);
486 buffer_puts(buffer_1,
"ALERT|some caches do not handle loopback internally\n");
489 if (
dd4(q,
"",
ip) == 4 ||
dd6(q,
"",
ip) == 16) {
490 buffer_put(buffer_1,querystr.s,querystr.len);
491 buffer_puts(buffer_1,
"ALERT|some caches do not handle IP addresses internally\n");
495 buffer_flush(buffer_1);
int dd6(const char *q, const char *base, char ip[16])
int dd4(const char *q, const char *base, char ip[4])
int dns_domain_fromdot(char **out, const char *buf, unsigned int n)
int dns_domain_equal(const char *dn1, const char *dn2)
int dns_domain_copy(char **out, const char *in)
int dns_domain_suffix(const char *big, const char *little)
int dns_domain_todot_cat(stralloc *out, const char *d)
int dns_ip_qualify(stralloc *ipout, stralloc *fqdn, const stralloc *in)
unsigned int dns_packet_getname(const char *buf, unsigned int len, unsigned int pos, char **d)
unsigned int dns_packet_copy(const char *buf, unsigned int len, unsigned int pos, char *out, unsigned int outlen)
unsigned int dns_packet_skipname(const char *buf, unsigned int len, unsigned int pos)
void dns_random_init(const char data[128])
void dns_transmit_io(struct dns_transmit *d, iopause_fd *x, struct taia *deadline)
int dns_transmit_start(struct dns_transmit *d, const char servers[QUERY_MAXIPLEN], char qflags[2], const char *q, const char qtype[2], const char localip[16])
int dns_transmit_get(struct dns_transmit *d, const iopause_fd *x, const struct taia *when)
char servers[QUERY_MAXIPLEN]
int resolve(char *q, char qtype[2], char ip[16])
void query_add(const char *owner, const char type[2])
void address_add(const char *owner, const char ip[16])
void ns_add(const char *owner, const char *server)
void printdomain(const char *d)
void parsepacket(const char *buf, unsigned int len, const char *d, const char dtype[2], const char *control)
GEN_ALLOC_typedef(GEN_ALLOC_readyplus(address_alloc, GEN_ALLOC_readyplus(struct address, GEN_ALLOC_readyplus(s, GEN_ALLOC_readyplus(len, GEN_ALLOC_readyplus(a)
void owner(int uid, int gid)
void start(const char *s)
void d(const char *home, const char *subdir, int uid, int gid, int mode)
int parsetype(char *, char[2])
unsigned int printrecord(stralloc *, const char *, unsigned int, unsigned int, const char *, const char[2])
char * ns[QUERY_MAXLEVEL][QUERY_MAXNS]