xref: /openbsd-src/regress/lib/libc/asr/bin/common.c (revision ac9b4aacc1da35008afea06a5d23c2f2dea9b93e)
1 /*	$OpenBSD: common.c,v 1.1.1.1 2012/07/13 17:49:53 eric 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 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <arpa/nameser.h>
22 
23 #include <err.h>
24 #include <errno.h>
25 #include <inttypes.h>
26 #include <netdb.h>
27 #include <resolv.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "common.h"
32 
33 int long_err;
34 int gai_errno;
35 int rrset_errno;
36 
37 
38 char *
39 gethostarg(char *n)
40 {
41 	if (n == NULL)
42 		return (n);
43 	if (!strcmp(n, "NULL"))
44 		return (NULL);
45 	if (!strcmp(n, "EMPTY"))
46 		return ("");
47 	return (n);
48 }
49 
50 const char *rrsetstrerror(int);
51 char * print_addr(const struct sockaddr *, char *, size_t);
52 
53 struct kv { int code; const char *name; };
54 
55 struct kv kv_family[] = {
56 	{ AF_UNIX,	"unix" },
57 	{ AF_INET,	"inet" },
58 	{ AF_INET6,	"inet6" },
59 	{ AF_IMPLINK,	"implink" },
60 	{ AF_BLUETOOTH,	"bluetooth" },
61 	{ 0,	NULL, }
62 };
63 struct kv kv_socktype[] = {
64 	{ SOCK_STREAM,	"stream" },
65 	{ SOCK_DGRAM,	"dgram" },
66 	{ SOCK_RAW,	"raw" },
67 	{ 0,	NULL, }
68 };
69 struct kv kv_protocol[] = {
70 	{ IPPROTO_UDP, "udp" },
71 	{ IPPROTO_TCP, "tcp" },
72 	{ 0,	NULL, }
73 };
74 
75 static const char *
76 kv_lookup_name(struct kv *kv, int code)
77 {
78 	while (kv->name) {
79 		if (kv->code == code)
80 			return (kv->name);
81 		kv++;
82 	}
83 	return "???";
84 }
85 
86 struct keyval {
87         const char      *key;
88         uint16_t         value;
89 };
90 
91 static struct keyval kv_class[] = {
92 	{ "IN",	C_IN },
93 	{ "CHAOS", C_CHAOS },
94 	{ "HS", C_HS },
95 	{ "ANY", C_ANY },
96 	{ NULL, 	0 },
97 };
98 
99 static struct keyval kv_type[] = {
100 	{ "A",		T_A	},
101 	{ "NS",		T_NS	},
102 	{ "MD",		T_MD	},
103 	{ "MF",		T_MF	},
104 	{ "CNAME",	T_CNAME	},
105 	{ "SOA",	T_SOA	},
106 	{ "MB",		T_MB	},
107 	{ "MG",		T_MG	},
108 	{ "MR",		T_MR	},
109 	{ "NULL",	T_NULL	},
110 	{ "WKS",	T_WKS	},
111 	{ "PTR",	T_PTR	},
112 	{ "HINFO",	T_HINFO	},
113 	{ "MINFO",	T_MINFO	},
114 	{ "MX",		T_MX	},
115 	{ "TXT",	T_TXT	},
116 
117 	{ "AAAA",	T_AAAA	},
118 
119 	{ "AXFR",	T_AXFR	},
120 	{ "MAILB",	T_MAILB	},
121 	{ "MAILA",	T_MAILA	},
122 	{ "ANY",	T_ANY	},
123 	{ NULL, 	0 },
124 };
125 
126 static struct keyval kv_rcode[] = {
127 	{ "NOERROR",	NOERROR	},
128 	{ "FORMERR",	FORMERR },
129 	{ "SERVFAIL",	SERVFAIL },
130 	{ "NXDOMAIN",	NXDOMAIN },
131 	{ "NOTIMP",	NOTIMP },
132 	{ "REFUSED",	REFUSED },
133 	{ NULL, 	0 },
134 };
135 
136 
137 const char *
138 rcodetostr(uint16_t v)
139 {
140 	static char	buf[16];
141 	size_t		i;
142 
143 	for(i = 0; kv_rcode[i].key; i++)
144 		if (kv_rcode[i].value == v)
145 			return (kv_rcode[i].key);
146 
147 	snprintf(buf, sizeof buf, "%"PRIu16"?", v);
148 
149 	return (buf);
150 }
151 
152 const char *
153 typetostr(uint16_t v)
154 {
155 	static char	 buf[16];
156 	size_t		 i;
157 
158 	for(i = 0; kv_type[i].key; i++)
159 		if (kv_type[i].value == v)
160 			return (kv_type[i].key);
161 
162 	snprintf(buf, sizeof buf, "%"PRIu16"?", v);
163 
164 	return (buf);
165 }
166 
167 const char *
168 classtostr(uint16_t v)
169 {
170 	static char	 buf[16];
171 	size_t		 i;
172 
173 	for(i = 0; kv_class[i].key; i++)
174 		if (kv_class[i].value == v)
175 			return (kv_class[i].key);
176 
177 	snprintf(buf, sizeof buf, "%"PRIu16"?", v);
178 
179 	return (buf);
180 }
181 
182 uint16_t
183 strtotype(const char *name)
184 {
185 	size_t	i;
186 
187 	for(i = 0; kv_type[i].key; i++)
188 		if (!strcmp(kv_type[i].key, name))
189 			return (kv_type[i].value);
190 
191 	return (0);
192 }
193 
194 uint16_t
195 strtoclass(const char *name)
196 {
197 	size_t	i;
198 
199 	for(i = 0; kv_class[i].key; i++)
200 		if (!strcmp(kv_class[i].key, name))
201 			return (kv_class[i].value);
202 
203 	return (0);
204 }
205 
206 void
207 print_hostent(struct hostent *e)
208 {
209 	char	buf[256], **c;
210 
211 	printf("name = \"%s\"\n", e->h_name);
212 	printf("aliases =");
213 	for(c = e->h_aliases; *c; c++)
214 		printf(" \"%s\"", *c);
215 	printf("\n");
216 	printf("addrtype = %i\n", e->h_addrtype);
217 	printf("addrlength = %i\n", e->h_length);
218 	printf("addr_list =");
219 	for(c = e->h_addr_list; *c; c++) {
220 		printf(" %s", inet_ntop(e->h_addrtype, *c, buf, sizeof buf));
221 	}
222 	printf("\n");
223 }
224 
225 void
226 print_netent(struct netent *e)
227 {
228 	char	buf[256], **c;
229 	uint32_t addr;
230 
231 	/* network number are given in host order */
232 	addr = htonl(e->n_net);
233 
234 	printf("name = \"%s\"\n", e->n_name);
235 	printf("aliases =");
236 	for (c = e->n_aliases; *c; c++)
237 		printf(" \"%s\"", *c);
238 	printf("\n");
239 	printf("addrtype = %i\n", e->n_addrtype);
240 	printf("net = %s\n", inet_ntop(e->n_addrtype, &addr, buf, sizeof buf));
241 }
242 
243 void
244 print_addrinfo(struct addrinfo *ai)
245 {
246 	char	buf[256];
247 
248 	printf("family=%s socktype=%s protocol=%s addr=%s canonname=%s\n",
249 		kv_lookup_name(kv_family, ai->ai_family),
250 		kv_lookup_name(kv_socktype, ai->ai_socktype),
251 		kv_lookup_name(kv_protocol, ai->ai_protocol),
252 		print_addr(ai->ai_addr, buf, sizeof buf),
253 		ai->ai_canonname);
254 }
255 
256 const char *
257 rrsetstrerror(int e)
258 {
259 	switch (e) {
260 	case 0:
261 		return "OK";
262 	case ERRSET_NONAME:
263 		return "ERRSET_NONAME";
264 	case ERRSET_NODATA:
265 		return "ERRSET_NODATA";
266 	case ERRSET_NOMEMORY:
267 		return "ERRSET_NOMEMORY";
268 	case ERRSET_INVAL:
269 		return "ERRSET_INVAL";
270 	case ERRSET_FAIL:
271 		return "ERRSET_FAIL";
272 	default:
273 		return "???";
274 	}
275 }
276 
277 void
278 print_rrsetinfo(struct rrsetinfo * rrset)
279 {
280 	printf("rri_flags=%u\n", rrset->rri_flags);
281 	printf("rri_rdclass=%u\n", rrset->rri_rdclass);
282 	printf("rri_rdtype=%u\n", rrset->rri_rdtype);
283 	printf("rri_ttl=%u\n", rrset->rri_ttl);
284 	printf("rri_nrdatas=%u\n", rrset->rri_nrdatas);
285 	printf("rri_nsigs=%u\n", rrset->rri_nsigs);
286 	printf("rri_name=\"%s\"\n", rrset->rri_name);
287 }
288 
289 void
290 print_errors(void)
291 {
292 	switch (long_err) {
293 	case 0:
294 		return;
295 	case 1:
296 		printf("  => errno %i, h_errno %i", errno, h_errno);
297 		printf(", rrset_errno %i", rrset_errno);
298 		printf(", gai_errno %i", gai_errno);
299 		printf ("\n");
300 		return;
301 	default:
302 		printf("  => errno %i: %s\n  => h_errno %i: %s\n  => rrset_errno %i: %s\n",
303 		    errno, errno ? strerror(errno) : "ok",
304 		    h_errno, h_errno ? hstrerror(h_errno) : "ok",
305 		    rrset_errno, rrset_errno ? rrsetstrerror(rrset_errno) : "ok");
306 		printf("  => gai_errno %i: %s\n",
307 		    gai_errno, gai_errno ? gai_strerror(gai_errno) : "ok");
308 	}
309 }
310 
311 
312 static char *
313 print_host(const struct sockaddr *sa, char *buf, size_t len)
314 {
315 	switch (sa->sa_family) {
316 	case AF_INET:
317 		inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr,
318 			  buf, len);
319 		break;
320 	case AF_INET6:
321 		inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr,
322 			  buf, len);
323 		break;
324 	default:
325 		buf[0] = '\0';
326 	}
327 	return (buf);
328 }
329 
330 
331 char *
332 print_addr(const struct sockaddr *sa, char *buf, size_t len)
333 {
334 	char	h[256];
335 
336 	print_host(sa, h, sizeof h);
337 
338 	switch (sa->sa_family) {
339 	case AF_INET:
340 		snprintf(buf, len, "%s:%i", h,
341 		    ntohs(((struct sockaddr_in*)(sa))->sin_port));
342 		break;
343 	case AF_INET6:
344 		snprintf(buf, len, "[%s]:%i", h,
345 		    ntohs(((struct sockaddr_in6*)(sa))->sin6_port));
346 		break;
347 	default:
348 		snprintf(buf, len, "?");
349 		break;
350 	}
351 
352 	return (buf);
353 }
354 
355 void
356 packed_init(struct packed *pack, char *data, size_t len)
357 {
358 	pack->data = data;
359 	pack->len = len;
360 	pack->offset = 0;
361 	pack->err = NULL;
362 }
363 
364 
365 static ssize_t
366 dname_expand(const unsigned char *data, size_t len, size_t offset,
367     size_t *newoffset, char *dst, size_t max)
368 {
369 	size_t		 n, count, end, ptr, start;
370 	ssize_t		 res;
371 
372 	if (offset >= len)
373 		return (-1);
374 
375 	res = 0;
376 	end = start = offset;
377 
378 	for(; (n = data[offset]); ) {
379 		if ((n & 0xc0) == 0xc0) {
380 			if (offset + 2 > len)
381 				return (-1);
382 			ptr = 256 * (n & ~0xc0) + data[offset + 1];
383 			if (ptr >= start)
384 				return (-1);
385 			if (end < offset + 2)
386 				end = offset + 2;
387 			offset = ptr;
388 			continue;
389 		}
390 		if (offset + n + 1 > len)
391 			return (-1);
392 
393 
394 		/* copy n + at offset+1 */
395 		if (dst != NULL && max != 0) {
396 			count = (max < n + 1) ? (max) : (n + 1);
397 			memmove(dst, data + offset, count);
398 			dst += count;
399 			max -= count;
400 		}
401 		res += n + 1;
402 		offset += n + 1;
403 		if (end < offset)
404 			end = offset;
405 	}
406 	if (end < offset + 1)
407 		end = offset + 1;
408 
409 	if (dst != NULL && max != 0)
410 		dst[0] = 0;
411 	if (newoffset)
412 		*newoffset = end;
413 	return (res + 1);
414 }
415 
416 static int
417 unpack_data(struct packed *p, void *data, size_t len)
418 {
419 	if (p->err)
420 		return (-1);
421 
422 	if (p->len - p->offset < len) {
423 		p->err = "too short";
424 		return (-1);
425 	}
426 
427 	memmove(data, p->data + p->offset, len);
428 	p->offset += len;
429 
430 	return (0);
431 }
432 
433 static int
434 unpack_u16(struct packed *p, uint16_t *u16)
435 {
436 	if (unpack_data(p, u16, 2) == -1)
437 		return (-1);
438 
439 	*u16 = ntohs(*u16);
440 
441 	return (0);
442 }
443 
444 static int
445 unpack_u32(struct packed *p, uint32_t *u32)
446 {
447 	if (unpack_data(p, u32, 4) == -1)
448 		return (-1);
449 
450 	*u32 = ntohl(*u32);
451 
452 	return (0);
453 }
454 
455 static int
456 unpack_inaddr(struct packed *p, struct in_addr *a)
457 {
458 	return (unpack_data(p, a, 4));
459 }
460 
461 static int
462 unpack_in6addr(struct packed *p, struct in6_addr *a6)
463 {
464 	return (unpack_data(p, a6, 16));
465 }
466 
467 static int
468 unpack_dname(struct packed *p, char *dst, size_t max)
469 {
470 	ssize_t e;
471 
472 	if (p->err)
473 		return (-1);
474 
475 	e = dname_expand(p->data, p->len, p->offset, &p->offset, dst, max);
476 	if (e == -1) {
477 		p->err = "bad domain name";
478 		return (-1);
479 	}
480 	if (e < 0 || e > MAXDNAME) {
481 		p->err = "domain name too long";
482 		return (-1);
483 	}
484 
485 	return (0);
486 }
487 
488 int
489 unpack_header(struct packed *p, struct header *h)
490 {
491 	if (unpack_data(p, h, HFIXEDSZ) == -1)
492 		return (-1);
493 
494 	h->flags = ntohs(h->flags);
495 	h->qdcount = ntohs(h->qdcount);
496 	h->ancount = ntohs(h->ancount);
497 	h->nscount = ntohs(h->nscount);
498 	h->arcount = ntohs(h->arcount);
499 
500 	return (0);
501 }
502 
503 int
504 unpack_query(struct packed *p, struct query *q)
505 {
506 	unpack_dname(p, q->q_dname, sizeof(q->q_dname));
507 	unpack_u16(p, &q->q_type);
508 	unpack_u16(p, &q->q_class);
509 
510 	return (p->err) ? (-1) : (0);
511 }
512 
513 int
514 unpack_rr(struct packed *p, struct rr *rr)
515 {
516 	uint16_t	rdlen;
517 	size_t		save_offset;
518 
519 	unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname));
520 	unpack_u16(p, &rr->rr_type);
521 	unpack_u16(p, &rr->rr_class);
522 	unpack_u32(p, &rr->rr_ttl);
523 	unpack_u16(p, &rdlen);
524 
525 	if (p->err)
526 		return (-1);
527 
528 	if (p->len - p->offset < rdlen) {
529 		p->err = "too short";
530 		return (-1);
531 	}
532 
533 	save_offset = p->offset;
534 
535 	switch(rr->rr_type) {
536 
537 	case T_CNAME:
538 		unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname));
539 		break;
540 
541 	case T_MX:
542 		unpack_u16(p, &rr->rr.mx.preference);
543 		unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange));
544 		break;
545 
546 	case T_NS:
547 		unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname));
548 		break;
549 
550 	case T_PTR:
551 		unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname));
552 		break;
553 
554 	case T_SOA:
555 		unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname));
556 		unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname));
557 		unpack_u32(p, &rr->rr.soa.serial);
558 		unpack_u32(p, &rr->rr.soa.refresh);
559 		unpack_u32(p, &rr->rr.soa.retry);
560 		unpack_u32(p, &rr->rr.soa.expire);
561 		unpack_u32(p, &rr->rr.soa.minimum);
562 		break;
563 
564 	case T_A:
565 		if (rr->rr_class != C_IN)
566 			goto other;
567 		unpack_inaddr(p, &rr->rr.in_a.addr);
568 		break;
569 
570 	case T_AAAA:
571 		if (rr->rr_class != C_IN)
572 			goto other;
573 		unpack_in6addr(p, &rr->rr.in_aaaa.addr6);
574 		break;
575 	default:
576 	other:
577 		rr->rr.other.rdata = p->data + p->offset;
578 		rr->rr.other.rdlen = rdlen;
579 		p->offset += rdlen;
580 	}
581 
582 	if (p->err)
583 		return (-1);
584 
585 	/* make sure that the advertised rdlen is really ok */
586 	if (p->offset - save_offset != rdlen)
587 		p->err = "bad dlen";
588 
589 	return (p->err) ? (-1) : (0);
590 }
591 
592 int
593 sockaddr_from_str(struct sockaddr *sa, int family, const char *str)
594 {
595 	struct in_addr		 ina;
596 	struct in6_addr		 in6a;
597 	struct sockaddr_in	*sin;
598 	struct sockaddr_in6	*sin6;
599 
600 	switch (family) {
601 	case PF_UNSPEC:
602 		if (sockaddr_from_str(sa, PF_INET, str) == 0)
603 			return (0);
604 		return sockaddr_from_str(sa, PF_INET6, str);
605 
606 	case PF_INET:
607 		if (inet_pton(PF_INET, str, &ina) != 1)
608 			return (-1);
609 
610 		sin = (struct sockaddr_in *)sa;
611 		memset(sin, 0, sizeof *sin);
612 		sin->sin_len = sizeof(struct sockaddr_in);
613 		sin->sin_family = PF_INET;
614 		sin->sin_addr.s_addr = ina.s_addr;
615 		return (0);
616 
617 	case PF_INET6:
618 		if (inet_pton(PF_INET6, str, &in6a) != 1)
619 			return (-1);
620 
621 		sin6 = (struct sockaddr_in6 *)sa;
622 		memset(sin6, 0, sizeof *sin6);
623 		sin6->sin6_len = sizeof(struct sockaddr_in6);
624 		sin6->sin6_family = PF_INET6;
625 		sin6->sin6_addr = in6a;
626 		return (0);
627 
628 	default:
629 		break;
630 	}
631 
632 	return (-1);
633 }
634