19 #define WHO "dnstrace"
23 logmsg(
WHO,111,FATAL,
"out of memory");
27 logmsg(
WHO,100,USAGE,
"dnstrace type name rootip ...");
30 static 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");
88 GEN_ALLOC_append(address_alloc,
struct address,s,
len,a,i,n,
x,30,address_alloc_readyplus,address_alloc_append)
99 GEN_ALLOC_append(ns_alloc,
struct ns,s,
len,a,i,n,
x,30,ns_alloc_readyplus,ns_alloc_append)
110 GEN_ALLOC_append(query_alloc,
struct query,s,
len,a,i,n,
x,30,query_alloc_readyplus,query_alloc_append)
112 static query_alloc
query;
123 GEN_ALLOC_append(qt_alloc,
struct qt,s,
len,a,i,n,
x,30,qt_alloc_readyplus,qt_alloc_append)
127 void 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)
172 void ns_add(
const char *owner,
const char *server)
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)
245 static char *referral;
248 static int typematch(
const char rtype[2],
const char qtype[2])
250 return byte_equal(qtype,2,rtype) || byte_equal(qtype,2,
DNS_T_ANY);
253 void 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])
void dns_transmit_io(struct dns_transmit *, iopause_fd *, struct taia *)
unsigned int dns_packet_copy(const char *, unsigned int, unsigned int, char *, unsigned int)
int dns_domain_equal(const char *, const char *)
int dns_domain_fromdot(char **, const char *, unsigned int)
int dns_domain_todot_cat(stralloc *, const char *)
int dns_ip_qualify(stralloc *, stralloc *, const stralloc *)
int dns_domain_copy(char **, const char *)
int dns_domain_suffix(const char *, const char *)
unsigned int dns_packet_skipname(const char *, unsigned int, unsigned int)
int dns_transmit_start(struct dns_transmit *, const char *, int, const char *, const char *, const char *)
unsigned int dns_packet_getname(const char *, unsigned int, unsigned int, char **)
void dns_random_init(const char *)
int dns_transmit_get(struct dns_transmit *, const iopause_fd *, const struct taia *)
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])
int main(int argc, char **argv)
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)
#define GEN_ALLOC_append(ta, type, field, len, a, i, n, x, base, ta_rplus, ta_append)
#define GEN_ALLOC_readyplus(ta, type, field, len, a, i, n, x, base, ta_rplus)
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 *s, char type[2])
unsigned int printrecord(stralloc *out, const char *buf, unsigned int len, unsigned int pos, const char *q, const char qtype[2])
char * ns[QUERY_MAXLEVEL][QUERY_MAXNS]