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