23 logmsg(
WHO,111,FATAL,
"out of memory");
27 logmsg(
WHO,100,USAGE,
"dnstrace type name rootip ...");
30static stralloc querystr;
36 if (!stralloc_copys(&
tmp,
""))
nomem();
38 buffer_put(buffer_1,
tmp.s,
tmp.len);
61 taia_uint(&deadline,120);
62 taia_add(&deadline,&deadline,&stamp);
64 r = iopause(
x,1,&deadline,&stamp);
71 taia_sub(&stamp,&stamp,&
start);
72 taia_uint(&deadline,1);
73 if (taia_less(&deadline,&stamp)) {
74 buffer_put(buffer_1,querystr.s,querystr.len);
75 buffer_puts(buffer_1,
"ALERT|took more than 1 second\n");
87GEN_ALLOC_readyplus(address_alloc,
struct address,s,
len,a,i,n,
x,30,address_alloc_readyplus)
88GEN_ALLOC_append(address_alloc,
struct address,s,
len,a,i,n,
x,30,address_alloc_readyplus,address_alloc_append)
98GEN_ALLOC_readyplus(ns_alloc,
struct ns,s,
len,a,i,n,
x,30,ns_alloc_readyplus)
99GEN_ALLOC_append(ns_alloc,
struct ns,s,
len,a,i,n,
x,30,ns_alloc_readyplus,ns_alloc_append)
109GEN_ALLOC_readyplus(query_alloc,
struct query,s,
len,a,i,n,
x,30,query_alloc_readyplus)
110GEN_ALLOC_append(query_alloc,
struct query,s,
len,a,i,n,
x,30,query_alloc_readyplus,query_alloc_append)
112static query_alloc
query;
122GEN_ALLOC_readyplus(qt_alloc,
struct qt,s,
len,a,i,n,
x,30,qt_alloc_readyplus)
123GEN_ALLOC_append(qt_alloc,
struct qt,s,
len,a,i,n,
x,30,qt_alloc_readyplus,qt_alloc_append)
127void qt_add(
const char *q,
const char type[2],
const char *control,
const char ip[16])
134 for (i = 0; i < qt.len; ++i)
137 if (byte_equal(qt.s[i].type,2,
type))
138 if (byte_equal(qt.s[i].ip,16,
ip))
141 byte_zero(&
x,
sizeof(
x));
144 byte_copy(
x.type,2,
type);
145 byte_copy(
x.ip,16,
ip);
146 if (!qt_alloc_append(&qt,&
x))
nomem();
155 for (i = 0; i <
query.len; ++i)
160 byte_zero(&
x,
sizeof(
x));
162 byte_copy(
x.type,2,
type);
165 for (i = 0; i <
ns.len; ++i)
167 for (j = 0; j <
address.len; ++j)
178 buffer_put(buffer_1,querystr.s,querystr.len);
179 buffer_puts(buffer_1,
"NS|");
181 buffer_puts(buffer_1,
"|");
183 buffer_puts(buffer_1,
"\n");
185 for (i = 0; i < ns.len; ++i)
193 byte_zero(&
x,
sizeof(
x));
196 if (!ns_alloc_append(&ns,&
x))
nomem();
198 for (i = 0; i <
query.len; ++i)
200 for (j = 0; j <
address.len; ++j)
212 scan_uint(querystr.s,&
type);
213 buffer_put(buffer_1,querystr.s,querystr.len);
214 buffer_puts(buffer_1,
"A/AAAA|");
216 buffer_puts(buffer_1,
"|");
217 if (ip6_isv4mapped(
ip)) {
222 buffer_puts(buffer_1,
"\n");
224 for (i = 0; i <
address.len; ++i)
229 byte_zero(&
x,
sizeof(
x));
231 byte_copy(
x.ip,16,
ip);
234 for (i = 0; i < ns.len; ++i)
236 for (j = 0; j <
query.len; ++j)
245static char *referral;
248static int typematch(
const char rtype[2],
const char qtype[2])
250 return byte_equal(qtype,2,rtype) || byte_equal(qtype,2,
DNS_T_ANY);
253void parsepacket(
const char *
buf,
unsigned int len,
const char *d,
const char dtype[2],
const char *control)
259 unsigned int posanswers;
275 uint16_unpack_big(header + 6,&numanswers);
276 uint16_unpack_big(header + 8,&numauthority);
277 uint16_unpack_big(header + 10,&numglue);
279 rcode = header[3] & 15;
280 if (rcode && (rcode != 3)) { errno = EPROTO;
goto DIE; }
287 for (j = 0; j < numanswers; ++j) {
291 if (byte_equal(header + 2,2,
DNS_C_IN))
292 if (typematch(header,dtype))
300 uint16_unpack_big(header + 8,&datalen);
303 for (j = 0; j < numauthority; ++j) {
308 else if (typematch(header,
DNS_T_NS)) {
312 uint16_unpack_big(header + 8,&datalen);
316 if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
318 buffer_put(buffer_1,querystr.s,querystr.len);
319 buffer_puts(buffer_1,
"ALERT|lame server; refers to ");
321 buffer_puts(buffer_1,
"\n");
326 for (j = 0;j < numanswers + numauthority + numglue;++j) {
329 uint16_unpack_big(header + 8,&datalen);
331 if (byte_equal(header + 2,2,
DNS_C_IN)) {
336 else if (typematch(header,
DNS_T_A) && datalen == 4) {
338 byte_copy(misc,12,V4mappedprefix);
341 else if (typematch(header,
DNS_T_AAAA) && datalen == 16) {
352 buffer_put(buffer_1,querystr.s,querystr.len);
353 buffer_puts(buffer_1,
"CNAME|");
355 buffer_puts(buffer_1,
"\n");
359 buffer_put(buffer_1,querystr.s,querystr.len);
360 buffer_puts(buffer_1,
"NXDOMAIN\n");
363 if (flagout || flagsoa || !flagreferral) {
365 buffer_put(buffer_1,querystr.s,querystr.len);
366 buffer_puts(buffer_1,
"NODATA\n");
370 for (j = 0; j < numanswers + numauthority + numglue; ++j) {
374 buffer_put(buffer_1,querystr.s,querystr.len);
375 buffer_puts(buffer_1,
"answer|");
376 buffer_put(buffer_1,
tmp.s,
tmp.len);
383 buffer_put(buffer_1,querystr.s,querystr.len);
384 buffer_puts(buffer_1,
"see|");
386 buffer_puts(buffer_1,
"\n");
391 buffer_put(buffer_1,querystr.s,querystr.len);
392 buffer_puts(buffer_1,
"ALERT|unable to parse response packet; ");
393 buffer_puts(buffer_1,
x);
394 buffer_puts(buffer_1,
"\n");
399 static stralloc ipout;
400 static stralloc fqdn;
411 if (!stralloc_copys(&querystr,
"0|.|.|start|"))
nomem();
414 if (!query_alloc_readyplus(&
query,1))
nomem();
415 if (!ns_alloc_readyplus(&ns,1))
nomem();
416 if (!qt_alloc_readyplus(&qt,1))
nomem();
419 if (!*++argv)
usage();
422 if (!*++argv)
usage();
429 if (!stralloc_copys(&udn,*argv))
nomem();
431 for (i = 0; i + 16 <= ipout.len; i += 16)
435 for (i = 0; i < qt.len; ++i) {
437 control = qt.s[i].control;
439 byte_copy(
type,2,qt.s[i].type);
440 byte_copy(
ip,16,qt.s[i].ip);
442 if (!stralloc_copys(&querystr,
""))
nomem();
443 uint16_unpack_big(
type,&u16);
444 if (!stralloc_catulong0(&querystr,u16,0))
nomem();
445 if (!stralloc_cats(&querystr,
"|"))
nomem();
447 if (!stralloc_cats(&querystr,
"|"))
nomem();
449 if (!stralloc_cats(&querystr,
"|"))
nomem();
450 if (ip6_isv4mapped(
ip)) {
454 if (!stralloc_cats(&querystr,
"|"))
nomem();
456 buffer_put(buffer_1,querystr.s,querystr.len);
457 buffer_puts(buffer_1,
"tx\n");
458 buffer_flush(buffer_1);
461 const char *
x = errstr(errno);
462 buffer_put(buffer_1,querystr.s,querystr.len);
463 buffer_puts(buffer_1,
"ALERT|query failed; ");
464 buffer_puts(buffer_1,
x);
465 buffer_puts(buffer_1,
"\n");
471 buffer_put(buffer_1,querystr.s,querystr.len);
472 buffer_puts(buffer_1,
"ALERT|some caches do not handle localhost internally\n");
476 buffer_put(buffer_1,querystr.s,querystr.len);
477 buffer_puts(buffer_1,
"ALERT|some caches do not handle localhost internally\n");
481 buffer_put(buffer_1,querystr.s,querystr.len);
482 buffer_puts(buffer_1,
"ALERT|some caches do not handle loopback internally\n");
483 address_add(q,
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001");
485 if (
dd4(q,
"",
ip) == 4 ||
dd6(q,
"",
ip) == 16) {
486 buffer_put(buffer_1,querystr.s,querystr.len);
487 buffer_puts(buffer_1,
"ALERT|some caches do not handle IP addresses internally\n");
491 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], int flagrecursive, 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 *)
unsigned int printrecord(stralloc *, const char *, unsigned int, unsigned int, const char *, const char *)
char * ns[QUERY_MAXLEVEL][QUERY_MAXNS]