xref: /openbsd-src/lib/libc/asr/asr_debug.c (revision beabf0626f373e6ad006167ab8b5eb7203d3b5e4)
1*beabf062Seric /*	$OpenBSD: asr_debug.c,v 1.3 2012/04/25 20:28:25 eric Exp $	*/
2b44da627Seric /*
3b44da627Seric  * Copyright (c) 2010-2012 Eric Faurot <eric@openbsd.org>
4b44da627Seric  *
5b44da627Seric  * Permission to use, copy, modify, and distribute this software for any
6b44da627Seric  * purpose with or without fee is hereby granted, provided that the above
7b44da627Seric  * copyright notice and this permission notice appear in all copies.
8b44da627Seric  *
9b44da627Seric  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10b44da627Seric  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11b44da627Seric  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12b44da627Seric  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13b44da627Seric  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14b44da627Seric  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15b44da627Seric  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16b44da627Seric  */
17b44da627Seric #include <sys/types.h>
18b44da627Seric #include <sys/socket.h>
19b44da627Seric 
20b44da627Seric #include <netinet/in.h>
21b44da627Seric #include <arpa/inet.h>
22b44da627Seric #include <arpa/nameser.h>
23b44da627Seric 
24b44da627Seric #include <inttypes.h>
25b44da627Seric #include <resolv.h>
26b44da627Seric #include <string.h>
27b44da627Seric #include <stdarg.h>
28b44da627Seric 
29b44da627Seric #include "asr.h"
30b44da627Seric #include "asr_private.h"
31b44da627Seric 
32*beabf062Seric char *print_addr(const struct sockaddr *, char *, size_t);
33*beabf062Seric 
34b44da627Seric static void asr_vdebug(const char *, va_list);
35b44da627Seric 
36b44da627Seric static char *print_dname(const char *, char *, size_t);
37b44da627Seric static char *print_host(const struct sockaddr *, char *, size_t);
38b44da627Seric 
39b44da627Seric static const char *typetostr(uint16_t);
40b44da627Seric static const char *classtostr(uint16_t);
41b44da627Seric static const char *rcodetostr(uint16_t);
42b44da627Seric 
43b44da627Seric static const char *inet6_ntoa(struct in6_addr);
44b44da627Seric 
45b44da627Seric 
46b44da627Seric #define OPCODE_SHIFT	11
47b44da627Seric #define Z_SHIFT		 4
48b44da627Seric 
49b44da627Seric struct keyval {
50b44da627Seric 	const char	*key;
51b44da627Seric 	uint16_t	 value;
52b44da627Seric };
53b44da627Seric 
54b44da627Seric static struct keyval kv_class[] = {
55b44da627Seric 	{ "IN",	C_IN },
56b44da627Seric 	{ "CHAOS", C_CHAOS },
57b44da627Seric 	{ "HS", C_HS },
58b44da627Seric 	{ "ANY", C_ANY },
59b44da627Seric 	{ NULL, 	0 },
60b44da627Seric };
61b44da627Seric 
62b44da627Seric static struct keyval kv_type[] = {
63b44da627Seric 	{ "A",		T_A	},
64b44da627Seric 	{ "NS",		T_NS	},
65b44da627Seric 	{ "MD",		T_MD	},
66b44da627Seric 	{ "MF",		T_MF	},
67b44da627Seric 	{ "CNAME",	T_CNAME	},
68b44da627Seric 	{ "SOA",	T_SOA	},
69b44da627Seric 	{ "MB",		T_MB	},
70b44da627Seric 	{ "MG",		T_MG	},
71b44da627Seric 	{ "MR",		T_MR	},
72b44da627Seric 	{ "NULL",	T_NULL	},
73b44da627Seric 	{ "WKS",	T_WKS	},
74b44da627Seric 	{ "PTR",	T_PTR	},
75b44da627Seric 	{ "HINFO",	T_HINFO	},
76b44da627Seric 	{ "MINFO",	T_MINFO	},
77b44da627Seric 	{ "MX",		T_MX	},
78b44da627Seric 	{ "TXT",	T_TXT	},
79b44da627Seric 
80b44da627Seric 	{ "AAAA",	T_AAAA	},
81b44da627Seric 
82b44da627Seric 	{ "AXFR",	T_AXFR	},
83b44da627Seric 	{ "MAILB",	T_MAILB	},
84b44da627Seric 	{ "MAILA",	T_MAILA	},
85b44da627Seric 	{ "ANY",	T_ANY	},
86b44da627Seric 	{ NULL, 	0 },
87b44da627Seric };
88b44da627Seric 
89b44da627Seric static struct keyval kv_rcode[] = {
90b44da627Seric 	{ "NOERROR",	NOERROR	},
91b44da627Seric 	{ "FORMERR",	FORMERR },
92b44da627Seric 	{ "SERVFAIL",	SERVFAIL },
93b44da627Seric 	{ "NXDOMAIN",	NXDOMAIN },
94b44da627Seric 	{ "NOTIMP",	NOTIMP },
95b44da627Seric 	{ "REFUSED",	REFUSED },
96b44da627Seric 	{ NULL, 	0 },
97b44da627Seric };
98b44da627Seric 
99b44da627Seric static const char *
100b44da627Seric typetostr(uint16_t v)
101b44da627Seric {
102b44da627Seric 	static char	 buf[16];
103b44da627Seric 	size_t		 i;
104b44da627Seric 
105b44da627Seric 	for(i = 0; kv_type[i].key; i++)
106b44da627Seric 		if (kv_type[i].value == v)
107b44da627Seric 			return (kv_type[i].key);
108b44da627Seric 
109b44da627Seric 	snprintf(buf, sizeof buf, "%"PRIu16"?", v);
110b44da627Seric 
111b44da627Seric 	return (buf);
112b44da627Seric }
113b44da627Seric 
114b44da627Seric static const char *
115b44da627Seric classtostr(uint16_t v)
116b44da627Seric {
117b44da627Seric 	static char	 buf[16];
118b44da627Seric 	size_t		 i;
119b44da627Seric 
120b44da627Seric 	for(i = 0; kv_class[i].key; i++)
121b44da627Seric 		if (kv_class[i].value == v)
122b44da627Seric 			return (kv_class[i].key);
123b44da627Seric 
124b44da627Seric 	snprintf(buf, sizeof buf, "%"PRIu16"?", v);
125b44da627Seric 
126b44da627Seric 	return (buf);
127b44da627Seric }
128b44da627Seric 
129b44da627Seric static const char *
130b44da627Seric rcodetostr(uint16_t v)
131b44da627Seric {
132b44da627Seric 	static char      buf[16];
133b44da627Seric 	size_t           i;
134b44da627Seric 
135b44da627Seric 	for(i = 0; kv_rcode[i].key; i++)
136b44da627Seric 		if (kv_rcode[i].value == v)
137b44da627Seric 			return (kv_rcode[i].key);
138b44da627Seric 
139b44da627Seric 	snprintf(buf, sizeof buf, "%"PRIu16"?", v);
140b44da627Seric 
141b44da627Seric 	return (buf);
142b44da627Seric }
143b44da627Seric 
144b44da627Seric static const char *
145b44da627Seric inet6_ntoa(struct in6_addr a)
146b44da627Seric {
147b44da627Seric 	static char buf[256];
148b44da627Seric 	struct sockaddr_in6	si;
149b44da627Seric 
150b44da627Seric 	si.sin6_len = sizeof(si);
151b44da627Seric 	si.sin6_family = PF_INET6;
152b44da627Seric 	si.sin6_addr = a;
153b44da627Seric 
154b44da627Seric 	return print_host((struct sockaddr*)&si, buf, sizeof buf);
155b44da627Seric }
156b44da627Seric 
157b44da627Seric static char*
158b44da627Seric print_rr(struct rr *rr, char *buf, size_t max)
159b44da627Seric {
160b44da627Seric 	char	*res;
161b44da627Seric 	char	 tmp[256];
162b44da627Seric 	char	 tmp2[256];
163b44da627Seric 	int	 r;
164b44da627Seric 
165b44da627Seric 	res = buf;
166b44da627Seric 
167b44da627Seric 	r = snprintf(buf, max, "%s %u %s %s ",
168b44da627Seric 	    print_dname(rr->rr_dname, tmp, sizeof tmp),
169b44da627Seric 	    rr->rr_ttl,
170b44da627Seric 	    classtostr(rr->rr_class),
171b44da627Seric 	    typetostr(rr->rr_type));
172b44da627Seric 	if (r == -1) {
173b44da627Seric 		buf[0] = '\0';
174b44da627Seric 		return buf;
175b44da627Seric 	}
176b44da627Seric 
177b44da627Seric 	if ((size_t)r >= max)
178b44da627Seric 		return buf;
179b44da627Seric 
180b44da627Seric 	max -= r;
181b44da627Seric 	buf += r;
182b44da627Seric 
183b44da627Seric 	switch(rr->rr_type) {
184b44da627Seric 	case T_CNAME:
185b44da627Seric 		print_dname(rr->rr.cname.cname, buf, max);
186b44da627Seric 		break;
187b44da627Seric 	case T_MX:
188b44da627Seric 		snprintf(buf, max, "%"PRIu32" %s",
189b44da627Seric 		    rr->rr.mx.preference,
190b44da627Seric 		    print_dname(rr->rr.mx.exchange, tmp, sizeof tmp));
191b44da627Seric 		break;
192b44da627Seric 	case T_NS:
193b44da627Seric 		print_dname(rr->rr.ns.nsname, buf, max);
194b44da627Seric 		break;
195b44da627Seric 	case T_PTR:
196b44da627Seric 		print_dname(rr->rr.ptr.ptrname, buf, max);
197b44da627Seric 		break;
198b44da627Seric 	case T_SOA:
199*beabf062Seric 		snprintf(buf, max, "%s %s %" PRIu32 " %" PRIu32 " %" PRIu32
200*beabf062Seric 		    " %" PRIu32 " %" PRIu32,
201b44da627Seric 		    print_dname(rr->rr.soa.rname, tmp, sizeof tmp),
202b44da627Seric 		    print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2),
203b44da627Seric 		    rr->rr.soa.serial,
204b44da627Seric 		    rr->rr.soa.refresh,
205b44da627Seric 		    rr->rr.soa.retry,
206b44da627Seric 		    rr->rr.soa.expire,
207b44da627Seric 		    rr->rr.soa.minimum);
208b44da627Seric 		break;
209b44da627Seric 	case T_A:
210b44da627Seric 		if (rr->rr_class != C_IN)
211b44da627Seric 			goto other;
212b44da627Seric 		snprintf(buf, max, "%s", inet_ntoa(rr->rr.in_a.addr));
213b44da627Seric 		break;
214b44da627Seric 	case T_AAAA:
215b44da627Seric 		if (rr->rr_class != C_IN)
216b44da627Seric 			goto other;
217b44da627Seric 		snprintf(buf, max, "%s", inet6_ntoa(rr->rr.in_aaaa.addr6));
218b44da627Seric 		break;
219b44da627Seric 	default:
220b44da627Seric 	other:
221b44da627Seric 		snprintf(buf, max, "(rdlen=%"PRIu16 ")", rr->rr.other.rdlen);
222b44da627Seric 		break;
223b44da627Seric 	}
224b44da627Seric 
225b44da627Seric 	return (res);
226b44da627Seric }
227b44da627Seric 
228b44da627Seric static char*
229b44da627Seric print_query(struct query *q, char *buf, size_t max)
230b44da627Seric {
231b44da627Seric 	char b[256];
232b44da627Seric 
233b44da627Seric 	snprintf(buf, max, "%s	%s %s",
234b44da627Seric 	    print_dname(q->q_dname, b, sizeof b),
235b44da627Seric 	    classtostr(q->q_class), typetostr(q->q_type));
236b44da627Seric 
237b44da627Seric 	return (buf);
238b44da627Seric }
239b44da627Seric 
240b44da627Seric static char*
241b44da627Seric print_dname(const char *_dname, char *buf, size_t max)
242b44da627Seric {
243b44da627Seric 	return asr_strdname(_dname, buf, max);
244b44da627Seric }
245b44da627Seric 
246b44da627Seric static char*
247b44da627Seric print_header(struct header *h, char *buf, size_t max, int noid)
248b44da627Seric {
249b44da627Seric 	snprintf(buf, max,
250b44da627Seric 	"id:0x%04x %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i",
251b44da627Seric 	    noid ? 0 : ((int)h->id),
252b44da627Seric 	    (h->flags & QR_MASK) ? "QR":"  ",
253b44da627Seric 	    (int)(OPCODE(h->flags) >> OPCODE_SHIFT),
254b44da627Seric 	    (h->flags & AA_MASK) ? "AA":"  ",
255b44da627Seric 	    (h->flags & TC_MASK) ? "TC":"  ",
256b44da627Seric 	    (h->flags & RD_MASK) ? "RD":"  ",
257b44da627Seric 	    (h->flags & RA_MASK) ? "RA":"  ",
258b44da627Seric 	    ((h->flags & Z_MASK) >> Z_SHIFT),
259b44da627Seric 	    rcodetostr(RCODE(h->flags)),
260b44da627Seric 	    h->qdcount, h->ancount, h->nscount, h->arcount);
261b44da627Seric 
262b44da627Seric 	return buf;
263b44da627Seric }
264b44da627Seric 
265b44da627Seric static char *
266b44da627Seric print_host(const struct sockaddr *sa, char *buf, size_t len)
267b44da627Seric {
26868cad45cSeric 	switch (sa->sa_family) {
26968cad45cSeric 	case AF_INET:
270*beabf062Seric 		inet_ntop(AF_INET, &((const struct sockaddr_in*)sa)->sin_addr,
271*beabf062Seric 		    buf, len);
27268cad45cSeric 		break;
27368cad45cSeric 	case AF_INET6:
274*beabf062Seric 		inet_ntop(AF_INET6,
275*beabf062Seric 		    &((const struct sockaddr_in6*)sa)->sin6_addr, buf, len);
27668cad45cSeric 		break;
27768cad45cSeric 	default:
278b44da627Seric 		buf[0] = '\0';
279b44da627Seric 	}
280b44da627Seric 	return (buf);
281b44da627Seric }
282b44da627Seric 
283b44da627Seric char *
284b44da627Seric print_addr(const struct sockaddr *sa, char *buf, size_t len)
285b44da627Seric {
286b44da627Seric 	char	h[256];
287b44da627Seric 
288b44da627Seric 	print_host(sa, h, sizeof h);
289b44da627Seric 
290b44da627Seric 	switch (sa->sa_family) {
291b44da627Seric 	case AF_INET:
292b44da627Seric 		snprintf(buf, len, "%s:%i", h,
293*beabf062Seric 		    ntohs(((const struct sockaddr_in*)(sa))->sin_port));
294b44da627Seric 		break;
295b44da627Seric 	case AF_INET6:
296b44da627Seric 		snprintf(buf, len, "[%s]:%i", h,
297*beabf062Seric 		    ntohs(((const struct sockaddr_in6*)(sa))->sin6_port));
298b44da627Seric 		break;
299b44da627Seric 	default:
300b44da627Seric 		snprintf(buf, len, "?");
301b44da627Seric 		break;
302b44da627Seric 	}
303b44da627Seric 
304b44da627Seric 	return (buf);
305b44da627Seric }
306b44da627Seric 
307b44da627Seric struct kv { int code; const char *name; };
308b44da627Seric 
309b44da627Seric static const char*	kvlookup(struct kv *, int);
310b44da627Seric 
311b44da627Seric int	 asr_debug = 0;
312b44da627Seric 
313b44da627Seric void
314b44da627Seric asr_dump(struct asr *a)
315b44da627Seric {
316b44da627Seric 	char		 buf[256];
317b44da627Seric 	int		 i;
318b44da627Seric 	struct asr_ctx	*ac;
319b44da627Seric 	unsigned int	 options;
320b44da627Seric 
321b44da627Seric 	ac = a->a_ctx;
322b44da627Seric 
323b44da627Seric 	asr_printf("--------- ASR CONFIG ---------------\n");
324b44da627Seric 	if (a->a_path)
325b44da627Seric 		asr_printf("CONF FILE \"%s\"\n", a->a_path);
326b44da627Seric 	else
327b44da627Seric 		asr_printf("STATIC CONF\n");
328b44da627Seric 	asr_printf("DOMAIN \"%s\"\n", ac->ac_domain);
329b44da627Seric 	asr_printf("SEARCH\n");
330b44da627Seric 	for(i = 0; i < ac->ac_domcount; i++)
331b44da627Seric 		asr_printf("   \"%s\"\n", ac->ac_dom[i]);
332b44da627Seric 	asr_printf("OPTIONS\n");
333b44da627Seric 	asr_printf(" options:");
334b44da627Seric 	options = ac->ac_options;
335b44da627Seric 	if (options & RES_INIT) {
336b44da627Seric 		asr_printf(" INIT"); options &= ~RES_INIT;
337b44da627Seric 	}
338b44da627Seric 	if (options & RES_DEBUG) {
339b44da627Seric 		asr_printf(" DEBUG"); options &= ~RES_DEBUG;
340b44da627Seric 	}
341b44da627Seric 	if (options & RES_USEVC) {
342b44da627Seric 		asr_printf(" USEVC"); options &= ~RES_USEVC;
343b44da627Seric 	}
344b44da627Seric 	if (options & RES_IGNTC) {
345b44da627Seric 		asr_printf(" IGNTC"); options &= ~RES_IGNTC;
346b44da627Seric 	}
347b44da627Seric 	if (options & RES_RECURSE) {
348b44da627Seric 		asr_printf(" RECURSE"); options &= ~RES_RECURSE;
349b44da627Seric 	}
350b44da627Seric 	if (options & RES_DEFNAMES) {
351b44da627Seric 		asr_printf(" DEFNAMES"); options &= ~RES_DEFNAMES;
352b44da627Seric 	}
353b44da627Seric 	if (options & RES_STAYOPEN) {
354b44da627Seric 		asr_printf(" STAYOPEN"); options &= ~RES_STAYOPEN;
355b44da627Seric 	}
356b44da627Seric 	if (options & RES_DNSRCH) {
357b44da627Seric 		asr_printf(" DNSRCH"); options &= ~RES_DNSRCH;
358b44da627Seric 	}
359b44da627Seric 	if (options & RES_NOALIASES) {
360b44da627Seric 		asr_printf(" NOALIASES"); options &= ~RES_NOALIASES;
361b44da627Seric 	}
362b44da627Seric 	if (options & RES_USE_EDNS0) {
363b44da627Seric 		asr_printf(" USE_EDNS0"); options &= ~RES_USE_EDNS0;
364b44da627Seric 	}
365b44da627Seric 	if (options & RES_USE_DNSSEC) {
366b44da627Seric 		asr_printf(" USE_DNSSEC"); options &= ~RES_USE_DNSSEC;
367b44da627Seric 	}
368b44da627Seric 	if (options)
369b44da627Seric 		asr_printf("0x%08x\n", options);
370b44da627Seric 	asr_printf("\n", ac->ac_options);
371b44da627Seric 
372b44da627Seric 	asr_printf(" ndots: %i\n", ac->ac_ndots);
373b44da627Seric 	asr_printf(" family:");
374b44da627Seric 	for(i = 0; ac->ac_family[i] != -1; i++)
375*beabf062Seric 		asr_printf(" %s", (ac->ac_family[i] == AF_INET) ?
376*beabf062Seric 		    "inet" : "inet6");
377b44da627Seric 	asr_printf("\n");
378b44da627Seric 	asr_printf("NAMESERVERS timeout=%i retry=%i\n",
379b44da627Seric 		   ac->ac_nstimeout,
380b44da627Seric 		   ac->ac_nsretries);
381b44da627Seric 	for(i = 0; i < ac->ac_nscount; i++)
382*beabf062Seric 		asr_printf("	%s\n", print_addr(ac->ac_ns[i], buf,
383*beabf062Seric 		    sizeof buf));
384b44da627Seric 	asr_printf("HOSTFILE %s\n", ac->ac_hostfile);
385b44da627Seric 	asr_printf("LOOKUP");
386b44da627Seric 	for(i = 0; i < ac->ac_dbcount; i++) {
387b44da627Seric 		switch (ac->ac_db[i]) {
388b44da627Seric 		case ASR_DB_FILE:
389b44da627Seric 			asr_printf(" file");
390b44da627Seric 			break;
391b44da627Seric 		case ASR_DB_DNS:
392b44da627Seric 			asr_printf(" dns");
393b44da627Seric 			break;
394b44da627Seric 		case ASR_DB_YP:
395b44da627Seric 			asr_printf(" yp");
396b44da627Seric 			break;
397b44da627Seric 		default:
398b44da627Seric 			asr_printf(" ?%i", ac->ac_db[i]);
399b44da627Seric 		}
400b44da627Seric 	}
401b44da627Seric 	asr_printf("\n------------------------------------\n");
402b44da627Seric }
403b44da627Seric 
404b44da627Seric static const char *
405b44da627Seric kvlookup(struct kv *kv, int code)
406b44da627Seric {
407b44da627Seric 	while (kv->name) {
408b44da627Seric 		if (kv->code == code)
409b44da627Seric 			return (kv->name);
410b44da627Seric 		kv++;
411b44da627Seric 	}
412b44da627Seric 	return "???";
413b44da627Seric }
414b44da627Seric 
415b44da627Seric struct kv kv_query_type[] = {
416b44da627Seric 	{ ASR_SEND,		"ASR_SEND"		},
417b44da627Seric 	{ ASR_SEARCH,		"ASR_SEARCH"		},
418b44da627Seric 	{ ASR_GETRRSETBYNAME,	"ASR_GETRRSETBYNAME"	},
419b44da627Seric 	{ ASR_GETHOSTBYNAME,	"ASR_GETHOSTBYNAME"	},
420b44da627Seric 	{ ASR_GETHOSTBYADDR,	"ASR_GETHOSTBYADDR"	},
421b44da627Seric 	{ ASR_GETNETBYNAME,	"ASR_GETNETBYNAME"	},
422b44da627Seric 	{ ASR_GETNETBYADDR,	"ASR_GETNETBYADDR"	},
423b44da627Seric 	{ ASR_GETADDRINFO,	"ASR_GETADDRINFO"	},
424b44da627Seric 	{ ASR_GETNAMEINFO,	"ASR_GETNAMEINFO"	},
425b44da627Seric 	{ ASR_HOSTADDR,		"ASR_HOSTADDR"		},
426b44da627Seric 	{ 0, NULL }
427b44da627Seric };
428b44da627Seric 
429b44da627Seric struct kv kv_db_type[] = {
430b44da627Seric 	{ ASR_DB_FILE,			"ASR_DB_FILE"			},
431b44da627Seric 	{ ASR_DB_DNS,			"ASR_DB_DNS"			},
432b44da627Seric 	{ ASR_DB_YP,			"ASR_DB_YP"			},
433b44da627Seric 	{ 0, NULL }
434b44da627Seric };
435b44da627Seric 
436b44da627Seric struct kv kv_state[] = {
437b44da627Seric 	{ ASR_STATE_INIT,		"ASR_STATE_INIT"		},
438b44da627Seric 	{ ASR_STATE_SEARCH_DOMAIN,	"ASR_STATE_SEARCH_DOMAIN"	},
439b44da627Seric 	{ ASR_STATE_LOOKUP_DOMAIN,	"ASR_STATE_LOOKUP_DOMAIN"	},
440b44da627Seric 	{ ASR_STATE_NEXT_DOMAIN,	"ASR_STATE_NEXT_DOMAIN"		},
441b44da627Seric 	{ ASR_STATE_NEXT_DB,		"ASR_STATE_NEXT_DB"		},
442b44da627Seric 	{ ASR_STATE_SAME_DB,		"ASR_STATE_SAME_DB"		},
443b44da627Seric 	{ ASR_STATE_NEXT_FAMILY,	"ASR_STATE_NEXT_FAMILY"		},
444b44da627Seric 	{ ASR_STATE_LOOKUP_FAMILY,	"ASR_STATE_LOOKUP_FAMILY"	},
445b44da627Seric 	{ ASR_STATE_NEXT_NS,		"ASR_STATE_NEXT_NS"		},
446b44da627Seric 	{ ASR_STATE_READ_RR,		"ASR_STATE_READ_RR"		},
447b44da627Seric 	{ ASR_STATE_READ_FILE,		"ASR_STATE_READ_FILE"		},
448b44da627Seric 	{ ASR_STATE_UDP_SEND,		"ASR_STATE_UDP_SEND"		},
449b44da627Seric 	{ ASR_STATE_UDP_RECV,		"ASR_STATE_UDP_RECV"		},
450b44da627Seric 	{ ASR_STATE_TCP_WRITE,		"ASR_STATE_TCP_WRITE"		},
451b44da627Seric 	{ ASR_STATE_TCP_READ,		"ASR_STATE_TCP_READ"		},
452b44da627Seric 	{ ASR_STATE_PACKET,		"ASR_STATE_PACKET"		},
453b44da627Seric 	{ ASR_STATE_SUBQUERY,		"ASR_STATE_SUBQUERY"		},
454b44da627Seric 	{ ASR_STATE_NOT_FOUND,		"ASR_STATE_NOT_FOUND",		},
455b44da627Seric 	{ ASR_STATE_HALT,		"ASR_STATE_HALT"		},
456b44da627Seric 	{ 0, NULL }
457b44da627Seric };
458b44da627Seric 
459b44da627Seric struct kv kv_transition[] = {
460b44da627Seric 	{ ASYNC_COND,			"ASYNC_COND"			},
461b44da627Seric 	{ ASYNC_YIELD,			"ASYNC_YIELD"			},
462b44da627Seric 	{ ASYNC_DONE,			"ASYNC_DONE"			},
463b44da627Seric         { 0, NULL }
464b44da627Seric };
465b44da627Seric 
466b44da627Seric const char *
467b44da627Seric asr_querystr(int type)
468b44da627Seric {
469b44da627Seric 	return kvlookup(kv_query_type, type);
470b44da627Seric }
471b44da627Seric 
472b44da627Seric const char *
473b44da627Seric asr_transitionstr(int type)
474b44da627Seric {
475b44da627Seric 	return kvlookup(kv_transition, type);
476b44da627Seric }
477b44da627Seric 
478b44da627Seric void
479b44da627Seric asr_dump_async(struct async *as)
480b44da627Seric {
481b44da627Seric 	asr_printf("%s fd=%i timeout=%i"
482b44da627Seric 		"   dom_idx=%i db_idx=%i ns_idx=%i ns_cycles=%i\n",
483b44da627Seric 		kvlookup(kv_state, as->as_state),
484b44da627Seric 		as->as_fd,
485b44da627Seric 		as->as_timeout,
486b44da627Seric 
487b44da627Seric 		as->as_dom_idx,
488b44da627Seric 		as->as_db_idx,
489b44da627Seric 		as->as_ns_idx,
490b44da627Seric 		as->as_ns_cycles);
491b44da627Seric }
492b44da627Seric 
493b44da627Seric void
494b44da627Seric asr_dump_packet(FILE *f, const void *data, size_t len, int noid)
495b44da627Seric {
496b44da627Seric 	char		buf[1024];
497b44da627Seric 	struct packed	p;
498b44da627Seric 	struct header	h;
499b44da627Seric 	struct query	q;
500b44da627Seric 	struct rr	rr;
501b44da627Seric 	int		i, an, ns, ar, n;
502b44da627Seric 
503b44da627Seric 	if (f == NULL)
504b44da627Seric 		return;
505b44da627Seric 
506b44da627Seric 	packed_init(&p, (char *)data, len);
507b44da627Seric 
508b44da627Seric 	if (unpack_header(&p, &h) == -1) {
509b44da627Seric 		fprintf(f, ";; BAD PACKET: %s\n", p.err);
510b44da627Seric 		return;
511b44da627Seric 	}
512b44da627Seric 
513b44da627Seric 	fprintf(f, ";; HEADER %s\n", print_header(&h, buf, sizeof buf, noid));
514b44da627Seric 
515b44da627Seric 	if (h.qdcount)
516b44da627Seric 		fprintf(f, ";; QUERY SECTION:\n");
517b44da627Seric 	for (i = 0; i < h.qdcount; i++) {
518b44da627Seric 		if (unpack_query(&p, &q) == -1)
519b44da627Seric 			goto error;
520b44da627Seric 		fprintf(f, "%s\n", print_query(&q, buf, sizeof buf));
521b44da627Seric 	}
522b44da627Seric 
523b44da627Seric 	an = 0;
524b44da627Seric 	ns = an + h.ancount;
525b44da627Seric 	ar = ns + h.nscount;
526b44da627Seric 	n = ar + h.arcount;
527b44da627Seric 
528b44da627Seric 	for (i = 0; i < n; i++) {
529b44da627Seric 		if (i == an)
530b44da627Seric 			fprintf(f, "\n;; ANSWER SECTION:\n");
531b44da627Seric 		if (i == ns)
532b44da627Seric 			fprintf(f, "\n;; AUTHORITY SECTION:\n");
533b44da627Seric 		if (i == ar)
534b44da627Seric 			fprintf(f, "\n;; ADDITIONAL SECTION:\n");
535b44da627Seric 
536b44da627Seric 		if (unpack_rr(&p, &rr) == -1)
537b44da627Seric 			goto error;
538b44da627Seric 		fprintf(f, "%s\n", print_rr(&rr, buf, sizeof buf));
539b44da627Seric 	}
540b44da627Seric 
541b44da627Seric 	if (p.offset != len)
542b44da627Seric 		fprintf(f, ";; REMAINING GARBAGE %zu\n", len - p.offset);
543b44da627Seric 
544b44da627Seric     error:
545b44da627Seric 	if (p.err)
546b44da627Seric 		fprintf(f, ";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len,
547b44da627Seric 		    p.err);
548b44da627Seric 
549b44da627Seric 	return;
550b44da627Seric }
551b44da627Seric 
552b44da627Seric static void
553b44da627Seric asr_vdebug(const char *fmt, va_list ap)
554b44da627Seric {
555b44da627Seric 	if (asr_debug)
556b44da627Seric 		vfprintf(stderr, fmt, ap);
557b44da627Seric }
558b44da627Seric 
559b44da627Seric void
560b44da627Seric asr_printf(const char *fmt, ...)
561b44da627Seric {
562b44da627Seric 	va_list ap;
563b44da627Seric 
564b44da627Seric 	va_start(ap, fmt);
565b44da627Seric 	asr_vdebug(fmt, ap);
566b44da627Seric 	va_end(ap);
567b44da627Seric }
568b44da627Seric 
569b44da627Seric void
570b44da627Seric async_set_state(struct async *as, int state)
571b44da627Seric {
572b44da627Seric 	asr_printf("asr: [%s@%p] %s -> %s\n",
573b44da627Seric 		kvlookup(kv_query_type, as->as_type),
574b44da627Seric 		as,
575b44da627Seric 		kvlookup(kv_state, as->as_state),
576b44da627Seric 		kvlookup(kv_state, state));
577b44da627Seric 	as->as_state = state;
578b44da627Seric }
579