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