GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/asr/asr_debug.c Lines: 0 188 0.0 %
Date: 2017-11-07 Branches: 0 110 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: asr_debug.c,v 1.24 2017/02/27 11:31:01 jca Exp $	*/
2
/*
3
 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <sys/types.h>
19
#include <sys/socket.h>
20
#include <netinet/in.h>
21
#include <arpa/nameser.h>
22
#include <arpa/inet.h>
23
#include <netdb.h>
24
25
#include <asr.h>
26
#include <resolv.h>
27
#include <string.h>
28
29
#include "asr_private.h"
30
31
static const char *rcodetostr(uint16_t);
32
static const char *print_dname(const char *, char *, size_t);
33
static const char *print_header(const struct asr_dns_header *, char *, size_t);
34
static const char *print_query(const struct asr_dns_query *, char *, size_t);
35
static const char *print_rr(const struct asr_dns_rr *, char *, size_t);
36
37
FILE *_asr_debug = NULL;
38
39
#define OPCODE_SHIFT	11
40
41
static const char *
42
rcodetostr(uint16_t v)
43
{
44
	switch (v) {
45
	case NOERROR:	return "NOERROR";
46
	case FORMERR:	return "FORMERR";
47
	case SERVFAIL:	return "SERVFAIL";
48
	case NXDOMAIN:	return "NXDOMAIN";
49
	case NOTIMP:	return "NOTIMP";
50
	case REFUSED:	return "REFUSED";
51
	default:	return "?";
52
	}
53
}
54
55
static const char *
56
print_dname(const char *_dname, char *buf, size_t max)
57
{
58
	return (_asr_strdname(_dname, buf, max));
59
}
60
61
static const char *
62
print_rr(const struct asr_dns_rr *rr, char *buf, size_t max)
63
{
64
	char	*res;
65
	char	 tmp[256];
66
	char	 tmp2[256];
67
	int	 r;
68
69
	res = buf;
70
71
	r = snprintf(buf, max, "%s %u %s %s ",
72
	    print_dname(rr->rr_dname, tmp, sizeof tmp),
73
	    rr->rr_ttl,
74
	    __p_class(rr->rr_class),
75
	    __p_type(rr->rr_type));
76
	if (r == -1) {
77
		buf[0] = '\0';
78
		return (buf);
79
	}
80
81
	if ((size_t)r >= max)
82
		return (buf);
83
84
	max -= r;
85
	buf += r;
86
87
	switch (rr->rr_type) {
88
	case T_CNAME:
89
		print_dname(rr->rr.cname.cname, buf, max);
90
		break;
91
	case T_MX:
92
		snprintf(buf, max, "%lu %s",
93
		    (unsigned long)rr->rr.mx.preference,
94
		    print_dname(rr->rr.mx.exchange, tmp, sizeof tmp));
95
		break;
96
	case T_NS:
97
		print_dname(rr->rr.ns.nsname, buf, max);
98
		break;
99
	case T_PTR:
100
		print_dname(rr->rr.ptr.ptrname, buf, max);
101
		break;
102
	case T_SOA:
103
		snprintf(buf, max, "%s %s %lu %lu %lu %lu %lu",
104
		    print_dname(rr->rr.soa.rname, tmp, sizeof tmp),
105
		    print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2),
106
		    (unsigned long)rr->rr.soa.serial,
107
		    (unsigned long)rr->rr.soa.refresh,
108
		    (unsigned long)rr->rr.soa.retry,
109
		    (unsigned long)rr->rr.soa.expire,
110
		    (unsigned long)rr->rr.soa.minimum);
111
		break;
112
	case T_A:
113
		if (rr->rr_class != C_IN)
114
			goto other;
115
		snprintf(buf, max, "%s", inet_ntop(AF_INET,
116
		    &rr->rr.in_a.addr, tmp, sizeof tmp));
117
		break;
118
	case T_AAAA:
119
		if (rr->rr_class != C_IN)
120
			goto other;
121
		snprintf(buf, max, "%s", inet_ntop(AF_INET6,
122
		    &rr->rr.in_aaaa.addr6, tmp, sizeof tmp));
123
		break;
124
	default:
125
	other:
126
		snprintf(buf, max, "(rdlen=%i)", (int)rr->rr.other.rdlen);
127
		break;
128
	}
129
130
	return (res);
131
}
132
133
static const char *
134
print_query(const struct asr_dns_query *q, char *buf, size_t max)
135
{
136
	char b[256];
137
138
	snprintf(buf, max, "%s	%s %s",
139
	    print_dname(q->q_dname, b, sizeof b),
140
	    __p_class(q->q_class), __p_type(q->q_type));
141
142
	return (buf);
143
}
144
145
static const char *
146
print_header(const struct asr_dns_header *h, char *buf, size_t max)
147
{
148
	snprintf(buf, max,
149
	"id:0x%04x %s op:%i %s %s %s %s z:%i %s %s r:%s qd:%i an:%i ns:%i ar:%i",
150
	    ((int)h->id),
151
	    (h->flags & QR_MASK) ? "QR":"  ",
152
	    (int)(OPCODE(h->flags) >> OPCODE_SHIFT),
153
	    (h->flags & AA_MASK) ? "AA":"  ",
154
	    (h->flags & TC_MASK) ? "TC":"  ",
155
	    (h->flags & RD_MASK) ? "RD":"  ",
156
	    (h->flags & RA_MASK) ? "RA":"  ",
157
	    (h->flags & Z_MASK),
158
	    (h->flags & AD_MASK) ? "AD":"  ",
159
	    (h->flags & CD_MASK) ? "CD":"  ",
160
	    rcodetostr(RCODE(h->flags)),
161
	    h->qdcount, h->ancount, h->nscount, h->arcount);
162
163
	return (buf);
164
}
165
166
void
167
_asr_dump_packet(FILE *f, const void *data, size_t len)
168
{
169
	char			buf[1024];
170
	struct asr_unpack	p;
171
	struct asr_dns_header	h;
172
	struct asr_dns_query	q;
173
	struct asr_dns_rr	rr;
174
	int			i, an, ns, ar, n;
175
176
	if (f == NULL)
177
		return;
178
179
	_asr_unpack_init(&p, data, len);
180
181
	if (_asr_unpack_header(&p, &h) == -1) {
182
		fprintf(f, ";; BAD PACKET: %s\n", strerror(p.err));
183
		return;
184
	}
185
186
	fprintf(f, ";; HEADER %s\n", print_header(&h, buf, sizeof buf));
187
188
	if (h.qdcount)
189
		fprintf(f, ";; QUERY SECTION:\n");
190
	for (i = 0; i < h.qdcount; i++) {
191
		if (_asr_unpack_query(&p, &q) == -1)
192
			goto error;
193
		fprintf(f, "%s\n", print_query(&q, buf, sizeof buf));
194
	}
195
196
	an = 0;
197
	ns = an + h.ancount;
198
	ar = ns + h.nscount;
199
	n = ar + h.arcount;
200
201
	for (i = 0; i < n; i++) {
202
		if (i == an)
203
			fprintf(f, "\n;; ANSWER SECTION:\n");
204
		if (i == ns)
205
			fprintf(f, "\n;; AUTHORITY SECTION:\n");
206
		if (i == ar)
207
			fprintf(f, "\n;; ADDITIONAL SECTION:\n");
208
209
		if (_asr_unpack_rr(&p, &rr) == -1)
210
			goto error;
211
		fprintf(f, "%s\n", print_rr(&rr, buf, sizeof buf));
212
	}
213
214
	if (p.offset != len)
215
		fprintf(f, ";; REMAINING GARBAGE %zu\n", len - p.offset);
216
217
    error:
218
	if (p.err)
219
		fprintf(f, ";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len,
220
		    strerror(p.err));
221
}
222
223
const char *
224
_asr_print_sockaddr(const struct sockaddr *sa, char *buf, size_t len)
225
{
226
	char	h[256];
227
	int	portno;
228
	union {
229
		const struct sockaddr		*sa;
230
		const struct sockaddr_in	*sin;
231
		const struct sockaddr_in6	*sin6;
232
	}	s;
233
234
	s.sa = sa;
235
236
	switch (sa->sa_family) {
237
	case AF_INET:
238
		inet_ntop(AF_INET, &s.sin->sin_addr, h, sizeof h);
239
		portno = ntohs(s.sin->sin_port);
240
		break;
241
	case AF_INET6:
242
		inet_ntop(AF_INET6, &s.sin6->sin6_addr, h, sizeof h);
243
		portno = ntohs(s.sin6->sin6_port);
244
		break;
245
	default:
246
		snprintf(buf, len, "?");
247
		return (buf);
248
	}
249
250
	snprintf(buf, len, "%s:%i", h, portno);
251
	return (buf);
252
}
253
254
void
255
_asr_dump_config(FILE *f, struct asr *a)
256
{
257
	char		 buf[256];
258
	int		 i;
259
	struct asr_ctx	*ac;
260
	unsigned int	 o;
261
262
	if (f == NULL)
263
		return;
264
265
	ac = a->a_ctx;
266
267
	fprintf(f, "--------- ASR CONFIG ---------------\n");
268
	fprintf(f, "DOMAIN \"%s\"\n", ac->ac_domain);
269
	fprintf(f, "SEARCH\n");
270
	for (i = 0; i < ac->ac_domcount; i++)
271
		fprintf(f, "   \"%s\"\n", ac->ac_dom[i]);
272
	fprintf(f, "OPTIONS\n");
273
	fprintf(f, " options:");
274
	o = ac->ac_options;
275
276
#define PRINTOPT(flag, n) if (o & (flag)) { fprintf(f, " " n); o &= ~(flag); }
277
	PRINTOPT(RES_INIT, "INIT");
278
	PRINTOPT(RES_DEBUG, "DEBUG");
279
	PRINTOPT(RES_USEVC, "USEVC");
280
	PRINTOPT(RES_IGNTC, "IGNTC");
281
	PRINTOPT(RES_RECURSE, "RECURSE");
282
	PRINTOPT(RES_DEFNAMES, "DEFNAMES");
283
	PRINTOPT(RES_STAYOPEN, "STAYOPEN");
284
	PRINTOPT(RES_DNSRCH, "DNSRCH");
285
	PRINTOPT(RES_NOALIASES, "NOALIASES");
286
	PRINTOPT(RES_USE_EDNS0, "USE_EDNS0");
287
	PRINTOPT(RES_USE_DNSSEC, "USE_DNSSEC");
288
	if (o)
289
		fprintf(f, " 0x%08x", o);
290
	fprintf(f, "\n");
291
292
	fprintf(f, " ndots: %i\n", ac->ac_ndots);
293
	fprintf(f, " family:");
294
	for (i = 0; ac->ac_family[i] != -1; i++)
295
		fprintf(f, " %s", (ac->ac_family[i] == AF_INET)?"inet4":"inet6");
296
	fprintf(f, "\n");
297
	fprintf(f, "NAMESERVERS timeout=%i retry=%i\n",
298
		    ac->ac_nstimeout,
299
		    ac->ac_nsretries);
300
	for (i = 0; i < ac->ac_nscount; i++)
301
		fprintf(f, "	%s\n", _asr_print_sockaddr(ac->ac_ns[i], buf,
302
		    sizeof buf));
303
	fprintf(f, "LOOKUP %s", ac->ac_db);
304
	fprintf(f, "\n------------------------------------\n");
305
}
306
307
#define CASE(n) case n: return #n
308
309
const char *
310
_asr_statestr(int state)
311
{
312
	switch (state) {
313
	CASE(ASR_STATE_INIT);
314
	CASE(ASR_STATE_NEXT_DOMAIN);
315
	CASE(ASR_STATE_NEXT_DB);
316
	CASE(ASR_STATE_SAME_DB);
317
	CASE(ASR_STATE_NEXT_FAMILY);
318
	CASE(ASR_STATE_NEXT_NS);
319
	CASE(ASR_STATE_UDP_SEND);
320
	CASE(ASR_STATE_UDP_RECV);
321
	CASE(ASR_STATE_TCP_WRITE);
322
	CASE(ASR_STATE_TCP_READ);
323
	CASE(ASR_STATE_PACKET);
324
	CASE(ASR_STATE_SUBQUERY);
325
	CASE(ASR_STATE_NOT_FOUND);
326
	CASE(ASR_STATE_HALT);
327
	default:
328
		return "?";
329
	}
330
};
331
332
const char *
333
_asr_querystr(int type)
334
{
335
	switch (type) {
336
	CASE(ASR_SEND);
337
	CASE(ASR_SEARCH);
338
	CASE(ASR_GETRRSETBYNAME);
339
	CASE(ASR_GETHOSTBYNAME);
340
	CASE(ASR_GETHOSTBYADDR);
341
	CASE(ASR_GETNETBYNAME);
342
	CASE(ASR_GETNETBYADDR);
343
	CASE(ASR_GETADDRINFO);
344
	CASE(ASR_GETNAMEINFO);
345
	default:
346
		return "?";
347
	}
348
}
349
350
const char *
351
_asr_transitionstr(int type)
352
{
353
	switch (type) {
354
	CASE(ASYNC_COND);
355
	CASE(ASYNC_DONE);
356
	default:
357
		return "?";
358
	}
359
}