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