summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/asr/bin/common.c
diff options
context:
space:
mode:
authoreric <>2012-07-13 17:49:54 +0000
committereric <>2012-07-13 17:49:54 +0000
commit9204e59073bcf27e1487ec4ac46e981902ddd904 (patch)
treec9d57f5a2812d08f0e504c69deb162dc89ae78a9 /src/regress/lib/libc/asr/bin/common.c
parent1cb24e474ab651a39f96d1b0c7582a081ea8c2b8 (diff)
downloadopenbsd-9204e59073bcf27e1487ec4ac46e981902ddd904.tar.gz
openbsd-9204e59073bcf27e1487ec4ac46e981902ddd904.tar.bz2
openbsd-9204e59073bcf27e1487ec4ac46e981902ddd904.zip
import regression suite for asr
Diffstat (limited to 'src/regress/lib/libc/asr/bin/common.c')
-rw-r--r--src/regress/lib/libc/asr/bin/common.c633
1 files changed, 633 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..4402d08373
--- /dev/null
+++ b/src/regress/lib/libc/asr/bin/common.c
@@ -0,0 +1,633 @@
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
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 { 0, NULL, }
73};
74
75static const char *
76kv_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
86struct keyval {
87 const char *key;
88 uint16_t value;
89};
90
91static 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
99static 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
126static 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
137const char *
138rcodetostr(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
152const char *
153typetostr(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
167const char *
168classtostr(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
182uint16_t
183strtotype(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
194uint16_t
195strtoclass(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
206void
207print_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
225void
226print_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
243void
244print_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
256const char *
257rrsetstrerror(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
277void
278print_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
289void
290print_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
312static char *
313print_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
331char *
332print_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
355void
356packed_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
365static ssize_t
366dname_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
416static int
417unpack_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
433static int
434unpack_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
444static int
445unpack_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
455static int
456unpack_inaddr(struct packed *p, struct in_addr *a)
457{
458 return (unpack_data(p, a, 4));
459}
460
461static int
462unpack_in6addr(struct packed *p, struct in6_addr *a6)
463{
464 return (unpack_data(p, a6, 16));
465}
466
467static int
468unpack_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
488int
489unpack_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
503int
504unpack_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
513int
514unpack_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
592int
593sockaddr_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}