xref: /openbsd-src/lib/libc/asr/asr_debug.c (revision d4cf23af83453521ab3070a1df538b5d7a823794)
1*d4cf23afSeric /*	$OpenBSD: asr_debug.c,v 1.8 2012/09/09 12:15:32 eric Exp $	*/
2b44da627Seric /*
3*d4cf23afSeric  * Copyright (c) 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/nameser.h>
22*d4cf23afSeric #include <arpa/inet.h>
23b44da627Seric 
24b44da627Seric #include <resolv.h>
25b44da627Seric 
26b44da627Seric #include "asr.h"
27b44da627Seric #include "asr_private.h"
28b44da627Seric 
29b44da627Seric static const char* rcodetostr(uint16_t);
30*d4cf23afSeric static const char* print_dname(const char *, char *, size_t);
31*d4cf23afSeric static const char* print_header(const struct header *, char *, size_t);
32*d4cf23afSeric static const char* print_query(const struct query *, char *, size_t);
33*d4cf23afSeric static const char* print_rr(const struct rr*, char *, size_t);
34b44da627Seric 
35*d4cf23afSeric FILE *asr_debug = NULL;
36b44da627Seric 
37b44da627Seric #define OPCODE_SHIFT	11
38b44da627Seric #define Z_SHIFT		 4
39b44da627Seric 
40b44da627Seric static const char *
41b44da627Seric rcodetostr(uint16_t v)
42b44da627Seric {
43*d4cf23afSeric 	switch(v) {
44*d4cf23afSeric 	case NOERROR:	return "NOERROR";
45*d4cf23afSeric 	case FORMERR:	return "FORMERR";
46*d4cf23afSeric 	case SERVFAIL:	return "SERVFAIL";
47*d4cf23afSeric 	case NXDOMAIN:	return "NXDOMAIN";
48*d4cf23afSeric 	case NOTIMP:	return "NOTIMP";
49*d4cf23afSeric 	case REFUSED:	return "REFUSED";
50*d4cf23afSeric 	default:	return "?";
51*d4cf23afSeric 	}
52b44da627Seric }
53b44da627Seric 
54b44da627Seric static const char*
55*d4cf23afSeric print_dname(const char *_dname, char *buf, size_t max)
56b44da627Seric {
57*d4cf23afSeric 	return (asr_strdname(_dname, buf, max));
58b44da627Seric }
59b44da627Seric 
60*d4cf23afSeric static const char*
61*d4cf23afSeric print_rr(const struct rr *rr, char *buf, size_t max)
62b44da627Seric {
63b44da627Seric 	char	*res;
64b44da627Seric 	char	 tmp[256];
65b44da627Seric 	char	 tmp2[256];
66b44da627Seric 	int	 r;
67b44da627Seric 
68b44da627Seric 	res = buf;
69b44da627Seric 
70b44da627Seric 	r = snprintf(buf, max, "%s %u %s %s ",
71b44da627Seric 	    print_dname(rr->rr_dname, tmp, sizeof tmp),
72b44da627Seric 	    rr->rr_ttl,
73*d4cf23afSeric 	    __p_class(rr->rr_class),
74*d4cf23afSeric 	    __p_type(rr->rr_type));
75b44da627Seric 	if (r == -1) {
76b44da627Seric 		buf[0] = '\0';
77*d4cf23afSeric 		return (buf);
78b44da627Seric 	}
79b44da627Seric 
80b44da627Seric 	if ((size_t)r >= max)
81*d4cf23afSeric 		return (buf);
82b44da627Seric 
83b44da627Seric 	max -= r;
84b44da627Seric 	buf += r;
85b44da627Seric 
86b44da627Seric 	switch(rr->rr_type) {
87b44da627Seric 	case T_CNAME:
88b44da627Seric 		print_dname(rr->rr.cname.cname, buf, max);
89b44da627Seric 		break;
90b44da627Seric 	case T_MX:
91*d4cf23afSeric 		snprintf(buf, max, "%lu %s",
92*d4cf23afSeric 		    (unsigned long)rr->rr.mx.preference,
93b44da627Seric 		    print_dname(rr->rr.mx.exchange, tmp, sizeof tmp));
94b44da627Seric 		break;
95b44da627Seric 	case T_NS:
96b44da627Seric 		print_dname(rr->rr.ns.nsname, buf, max);
97b44da627Seric 		break;
98b44da627Seric 	case T_PTR:
99b44da627Seric 		print_dname(rr->rr.ptr.ptrname, buf, max);
100b44da627Seric 		break;
101b44da627Seric 	case T_SOA:
102*d4cf23afSeric 		snprintf(buf, max, "%s %s %lu %lu %lu %lu %lu",
103b44da627Seric 		    print_dname(rr->rr.soa.rname, tmp, sizeof tmp),
104b44da627Seric 		    print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2),
105*d4cf23afSeric 		    (unsigned long)rr->rr.soa.serial,
106*d4cf23afSeric 		    (unsigned long)rr->rr.soa.refresh,
107*d4cf23afSeric 		    (unsigned long)rr->rr.soa.retry,
108*d4cf23afSeric 		    (unsigned long)rr->rr.soa.expire,
109*d4cf23afSeric 		    (unsigned long)rr->rr.soa.minimum);
110b44da627Seric 		break;
111b44da627Seric 	case T_A:
112b44da627Seric 		if (rr->rr_class != C_IN)
113b44da627Seric 			goto other;
114*d4cf23afSeric 		snprintf(buf, max, "%s", inet_ntop(AF_INET,
115*d4cf23afSeric 		    &rr->rr.in_a.addr, tmp, sizeof tmp));
116b44da627Seric 		break;
117b44da627Seric 	case T_AAAA:
118b44da627Seric 		if (rr->rr_class != C_IN)
119b44da627Seric 			goto other;
120*d4cf23afSeric 		snprintf(buf, max, "%s", inet_ntop(AF_INET6,
121*d4cf23afSeric 		    &rr->rr.in_aaaa.addr6, tmp, sizeof tmp));
122b44da627Seric 		break;
123b44da627Seric 	default:
124b44da627Seric 	other:
125*d4cf23afSeric 		snprintf(buf, max, "(rdlen=%i)", (int)rr->rr.other.rdlen);
126b44da627Seric 		break;
127b44da627Seric 	}
128b44da627Seric 
129b44da627Seric 	return (res);
130b44da627Seric }
131b44da627Seric 
132*d4cf23afSeric static const char*
133*d4cf23afSeric print_query(const struct query *q, char *buf, size_t max)
134b44da627Seric {
135b44da627Seric 	char b[256];
136b44da627Seric 
137b44da627Seric 	snprintf(buf, max, "%s	%s %s",
138b44da627Seric 	    print_dname(q->q_dname, b, sizeof b),
139*d4cf23afSeric 	    __p_class(q->q_class), __p_type(q->q_type));
140b44da627Seric 
141b44da627Seric 	return (buf);
142b44da627Seric }
143b44da627Seric 
144*d4cf23afSeric static const char*
145*d4cf23afSeric print_header(const struct header *h, char *buf, size_t max)
146b44da627Seric {
147b44da627Seric 	snprintf(buf, max,
148b44da627Seric 	"id:0x%04x %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i",
149*d4cf23afSeric 	    ((int)h->id),
150b44da627Seric 	    (h->flags & QR_MASK) ? "QR":"  ",
151b44da627Seric 	    (int)(OPCODE(h->flags) >> OPCODE_SHIFT),
152b44da627Seric 	    (h->flags & AA_MASK) ? "AA":"  ",
153b44da627Seric 	    (h->flags & TC_MASK) ? "TC":"  ",
154b44da627Seric 	    (h->flags & RD_MASK) ? "RD":"  ",
155b44da627Seric 	    (h->flags & RA_MASK) ? "RA":"  ",
156b44da627Seric 	    ((h->flags & Z_MASK) >> Z_SHIFT),
157b44da627Seric 	    rcodetostr(RCODE(h->flags)),
158b44da627Seric 	    h->qdcount, h->ancount, h->nscount, h->arcount);
159b44da627Seric 
160b44da627Seric 	return (buf);
161b44da627Seric }
162b44da627Seric 
163b44da627Seric void
164*d4cf23afSeric asr_dump_packet(FILE *f, const void *data, size_t len)
165b44da627Seric {
166b44da627Seric 	char		buf[1024];
167b44da627Seric 	struct packed	p;
168b44da627Seric 	struct header	h;
169b44da627Seric 	struct query	q;
170b44da627Seric 	struct rr	rr;
171b44da627Seric 	int		i, an, ns, ar, n;
172b44da627Seric 
173b44da627Seric 	if (f == NULL)
174b44da627Seric 		return;
175b44da627Seric 
176b44da627Seric 	packed_init(&p, (char *)data, len);
177b44da627Seric 
178b44da627Seric 	if (unpack_header(&p, &h) == -1) {
179b44da627Seric 		fprintf(f, ";; BAD PACKET: %s\n", p.err);
180b44da627Seric 		return;
181b44da627Seric 	}
182b44da627Seric 
183*d4cf23afSeric 	fprintf(f, ";; HEADER %s\n", print_header(&h, buf, sizeof buf));
184b44da627Seric 
185b44da627Seric 	if (h.qdcount)
186b44da627Seric 		fprintf(f, ";; QUERY SECTION:\n");
187b44da627Seric 	for (i = 0; i < h.qdcount; i++) {
188b44da627Seric 		if (unpack_query(&p, &q) == -1)
189b44da627Seric 			goto error;
190b44da627Seric 		fprintf(f, "%s\n", print_query(&q, buf, sizeof buf));
191b44da627Seric 	}
192b44da627Seric 
193b44da627Seric 	an = 0;
194b44da627Seric 	ns = an + h.ancount;
195b44da627Seric 	ar = ns + h.nscount;
196b44da627Seric 	n = ar + h.arcount;
197b44da627Seric 
198b44da627Seric 	for (i = 0; i < n; i++) {
199b44da627Seric 		if (i == an)
200b44da627Seric 			fprintf(f, "\n;; ANSWER SECTION:\n");
201b44da627Seric 		if (i == ns)
202b44da627Seric 			fprintf(f, "\n;; AUTHORITY SECTION:\n");
203b44da627Seric 		if (i == ar)
204b44da627Seric 			fprintf(f, "\n;; ADDITIONAL SECTION:\n");
205b44da627Seric 
206b44da627Seric 		if (unpack_rr(&p, &rr) == -1)
207b44da627Seric 			goto error;
208b44da627Seric 		fprintf(f, "%s\n", print_rr(&rr, buf, sizeof buf));
209b44da627Seric 	}
210b44da627Seric 
211b44da627Seric 	if (p.offset != len)
212b44da627Seric 		fprintf(f, ";; REMAINING GARBAGE %zu\n", len - p.offset);
213b44da627Seric 
214b44da627Seric     error:
215b44da627Seric 	if (p.err)
216b44da627Seric 		fprintf(f, ";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len,
217b44da627Seric 		    p.err);
218b44da627Seric }
219b44da627Seric 
220*d4cf23afSeric const char *
221*d4cf23afSeric print_sockaddr(const struct sockaddr *sa, char *buf, size_t len)
222b44da627Seric {
223*d4cf23afSeric 	char	h[256];
224*d4cf23afSeric 	int	portno;
225*d4cf23afSeric 	union {
226*d4cf23afSeric 		const struct sockaddr		*sa;
227*d4cf23afSeric 		const struct sockaddr_in	*sin;
228*d4cf23afSeric 		const struct sockaddr_in6	*sin6;
229*d4cf23afSeric 	}	s;
230b44da627Seric 
231*d4cf23afSeric 	s.sa = sa;
23246ab4803Seric 
233*d4cf23afSeric 	switch (sa->sa_family) {
234*d4cf23afSeric 	case AF_INET:
235*d4cf23afSeric 		inet_ntop(AF_INET, &s.sin->sin_addr, h, sizeof h);
236*d4cf23afSeric 		portno = ntohs(s.sin->sin_port);
237*d4cf23afSeric 		break;
238*d4cf23afSeric 	case AF_INET6:
239*d4cf23afSeric 		inet_ntop(AF_INET6, &s.sin6->sin6_addr, h, sizeof h);
240*d4cf23afSeric 		portno = ntohs(s.sin6->sin6_port);
241*d4cf23afSeric 		break;
242*d4cf23afSeric 	default:
243*d4cf23afSeric 		snprintf(buf, len, "?");
244*d4cf23afSeric 		return (buf);
245*d4cf23afSeric 	}
246*d4cf23afSeric 
247*d4cf23afSeric 	snprintf(buf, len, "%s:%i", h, portno);
248*d4cf23afSeric 	return (buf);
249b44da627Seric }
250b44da627Seric 
251b44da627Seric void
252*d4cf23afSeric asr_dump_config(FILE *f, struct asr *a)
253b44da627Seric {
254*d4cf23afSeric 	char		 buf[256];
255*d4cf23afSeric 	int		 i;
256*d4cf23afSeric 	struct asr_ctx	*ac;
257*d4cf23afSeric 	unsigned int	 o;
258*d4cf23afSeric 
259*d4cf23afSeric 	if (f == NULL)
260*d4cf23afSeric 		return;
261*d4cf23afSeric 
262*d4cf23afSeric 	ac = a->a_ctx;
263*d4cf23afSeric 
264*d4cf23afSeric 	fprintf(f, "--------- ASR CONFIG ---------------\n");
265*d4cf23afSeric 	if (a->a_path)
266*d4cf23afSeric 		fprintf(f, "CONF FILE \"%s\"\n", a->a_path);
267*d4cf23afSeric 	else
268*d4cf23afSeric 		fprintf(f, "STATIC CONF\n");
269*d4cf23afSeric 	fprintf(f, "DOMAIN \"%s\"\n", ac->ac_domain);
270*d4cf23afSeric 	fprintf(f, "SEARCH\n");
271*d4cf23afSeric 	for(i = 0; i < ac->ac_domcount; i++)
272*d4cf23afSeric 		fprintf(f, "   \"%s\"\n", ac->ac_dom[i]);
273*d4cf23afSeric 	fprintf(f, "OPTIONS\n");
274*d4cf23afSeric 	fprintf(f, " options:");
275*d4cf23afSeric 	o = ac->ac_options;
276*d4cf23afSeric 
277*d4cf23afSeric #define PRINTOPT(flag, n) if (o & (flag)) { fprintf(f, " " n); o &= ~(flag); }
278*d4cf23afSeric 	PRINTOPT(RES_INIT, "INIT");
279*d4cf23afSeric 	PRINTOPT(RES_DEBUG, "DEBUG");
280*d4cf23afSeric 	PRINTOPT(RES_USEVC, "USEVC");
281*d4cf23afSeric 	PRINTOPT(RES_IGNTC, "IGNTC");
282*d4cf23afSeric 	PRINTOPT(RES_RECURSE, "RECURSE");
283*d4cf23afSeric 	PRINTOPT(RES_DEFNAMES, "DEFNAMES");
284*d4cf23afSeric 	PRINTOPT(RES_STAYOPEN, "STAYOPEN");
285*d4cf23afSeric 	PRINTOPT(RES_DNSRCH, "DNSRCH");
286*d4cf23afSeric 	PRINTOPT(RES_NOALIASES, "NOALIASES");
287*d4cf23afSeric 	PRINTOPT(RES_USE_EDNS0, "USE_EDNS0");
288*d4cf23afSeric 	PRINTOPT(RES_USE_DNSSEC, "USE_DNSSEC");
289*d4cf23afSeric 	if (o)
290*d4cf23afSeric 		fprintf(f, " 0x%08x", o);
291*d4cf23afSeric 	fprintf(f, "\n");
292*d4cf23afSeric 
293*d4cf23afSeric 	fprintf(f, " ndots: %i\n", ac->ac_ndots);
294*d4cf23afSeric 	fprintf(f, " family:");
295*d4cf23afSeric 	for(i = 0; ac->ac_family[i] != -1; i++)
296*d4cf23afSeric 		fprintf(f, " %s", (ac->ac_family[i] == AF_INET)?"inet":"inet6");
297*d4cf23afSeric 	fprintf(f, "\n");
298*d4cf23afSeric 	fprintf(f, "NAMESERVERS timeout=%i retry=%i\n",
299*d4cf23afSeric 		   ac->ac_nstimeout,
300*d4cf23afSeric 		   ac->ac_nsretries);
301*d4cf23afSeric 	for(i = 0; i < ac->ac_nscount; i++)
302*d4cf23afSeric 		fprintf(f, "	%s\n", print_sockaddr(ac->ac_ns[i], buf,
303*d4cf23afSeric 		    sizeof buf));
304*d4cf23afSeric 	fprintf(f, "HOSTFILE %s\n", ac->ac_hostfile);
305*d4cf23afSeric 	fprintf(f, "LOOKUP");
306*d4cf23afSeric 	for(i = 0; i < ac->ac_dbcount; i++) {
307*d4cf23afSeric 		switch (ac->ac_db[i]) {
308*d4cf23afSeric 		case ASR_DB_FILE:
309*d4cf23afSeric 			fprintf(f, " file");
310*d4cf23afSeric 			break;
311*d4cf23afSeric 		case ASR_DB_DNS:
312*d4cf23afSeric 			fprintf(f, " dns");
313*d4cf23afSeric 			break;
314*d4cf23afSeric 		case ASR_DB_YP:
315*d4cf23afSeric 			fprintf(f, " yp");
316*d4cf23afSeric 			break;
317*d4cf23afSeric 		default:
318*d4cf23afSeric 			fprintf(f, " ?%i", ac->ac_db[i]);
319*d4cf23afSeric 		}
320*d4cf23afSeric 	}
321*d4cf23afSeric 	fprintf(f, "\n------------------------------------\n");
322*d4cf23afSeric }
323*d4cf23afSeric 
324*d4cf23afSeric #define CASE(n) case n: return #n
325*d4cf23afSeric 
326*d4cf23afSeric const char *
327*d4cf23afSeric asr_statestr(int state)
328*d4cf23afSeric {
329*d4cf23afSeric 	switch (state) {
330*d4cf23afSeric 	CASE(ASR_STATE_INIT);
331*d4cf23afSeric 	CASE(ASR_STATE_NEXT_DOMAIN);
332*d4cf23afSeric 	CASE(ASR_STATE_NEXT_DB);
333*d4cf23afSeric 	CASE(ASR_STATE_SAME_DB);
334*d4cf23afSeric 	CASE(ASR_STATE_NEXT_FAMILY);
335*d4cf23afSeric 	CASE(ASR_STATE_NEXT_NS);
336*d4cf23afSeric 	CASE(ASR_STATE_UDP_SEND);
337*d4cf23afSeric 	CASE(ASR_STATE_UDP_RECV);
338*d4cf23afSeric 	CASE(ASR_STATE_TCP_WRITE);
339*d4cf23afSeric 	CASE(ASR_STATE_TCP_READ);
340*d4cf23afSeric 	CASE(ASR_STATE_PACKET);
341*d4cf23afSeric 	CASE(ASR_STATE_SUBQUERY);
342*d4cf23afSeric 	CASE(ASR_STATE_NOT_FOUND);
343*d4cf23afSeric 	CASE(ASR_STATE_HALT);
344*d4cf23afSeric 	default:
345*d4cf23afSeric 		return "?";
346*d4cf23afSeric 	}
347*d4cf23afSeric };
348*d4cf23afSeric 
349*d4cf23afSeric const char *
350*d4cf23afSeric asr_querystr(int type)
351*d4cf23afSeric {
352*d4cf23afSeric 	switch (type) {
353*d4cf23afSeric 	CASE(ASR_SEND);
354*d4cf23afSeric 	CASE(ASR_SEARCH);
355*d4cf23afSeric 	CASE(ASR_GETRRSETBYNAME);
356*d4cf23afSeric 	CASE(ASR_GETHOSTBYNAME);
357*d4cf23afSeric 	CASE(ASR_GETHOSTBYADDR);
358*d4cf23afSeric 	CASE(ASR_GETNETBYNAME);
359*d4cf23afSeric 	CASE(ASR_GETNETBYADDR);
360*d4cf23afSeric 	CASE(ASR_GETADDRINFO);
361*d4cf23afSeric 	CASE(ASR_GETNAMEINFO);
362*d4cf23afSeric 	default:
363*d4cf23afSeric 		return "?";
364*d4cf23afSeric 	}
365*d4cf23afSeric }
366*d4cf23afSeric 
367*d4cf23afSeric const char *
368*d4cf23afSeric asr_transitionstr(int type)
369*d4cf23afSeric {
370*d4cf23afSeric 	switch(type) {
371*d4cf23afSeric 	CASE(ASYNC_COND);
372*d4cf23afSeric 	CASE(ASYNC_YIELD);
373*d4cf23afSeric 	CASE(ASYNC_DONE);
374*d4cf23afSeric 	default:
375*d4cf23afSeric 		return "?";
376*d4cf23afSeric 	}
377b44da627Seric }
378