From 9204e59073bcf27e1487ec4ac46e981902ddd904 Mon Sep 17 00:00:00 2001 From: eric <> Date: Fri, 13 Jul 2012 17:49:54 +0000 Subject: import regression suite for asr --- src/regress/lib/libc/asr/Makefile | 52 ++ src/regress/lib/libc/asr/bin/Makefile | 10 + src/regress/lib/libc/asr/bin/Makefile.inc | 8 + src/regress/lib/libc/asr/bin/common.c | 633 +++++++++++++++++++++ src/regress/lib/libc/asr/bin/common.h | 136 +++++ src/regress/lib/libc/asr/bin/getaddrinfo.c | 131 +++++ src/regress/lib/libc/asr/bin/getaddrinfo/Makefile | 8 + src/regress/lib/libc/asr/bin/gethostnamadr.c | 112 ++++ .../lib/libc/asr/bin/gethostnamadr/Makefile | 8 + src/regress/lib/libc/asr/bin/getnameinfo.c | 112 ++++ src/regress/lib/libc/asr/bin/getnameinfo/Makefile | 8 + src/regress/lib/libc/asr/bin/getnetnamadr.c | 85 +++ src/regress/lib/libc/asr/bin/getnetnamadr/Makefile | 8 + src/regress/lib/libc/asr/bin/getrrsetbyname.c | 88 +++ .../lib/libc/asr/bin/getrrsetbyname/Makefile | 8 + src/regress/lib/libc/asr/bin/res_mkquery.c | 319 +++++++++++ src/regress/lib/libc/asr/bin/res_mkquery/Makefile | 8 + src/regress/lib/libc/asr/bin/res_query.c | 354 ++++++++++++ src/regress/lib/libc/asr/bin/res_query/Makefile | 8 + src/regress/lib/libc/asr/bin/threads.c | 140 +++++ src/regress/lib/libc/asr/bin/threads/Makefile | 10 + src/regress/lib/libc/asr/regress.sh | 104 ++++ src/regress/lib/libc/asr/regress.subr | 114 ++++ 23 files changed, 2464 insertions(+) create mode 100644 src/regress/lib/libc/asr/Makefile create mode 100644 src/regress/lib/libc/asr/bin/Makefile create mode 100644 src/regress/lib/libc/asr/bin/Makefile.inc create mode 100644 src/regress/lib/libc/asr/bin/common.c create mode 100644 src/regress/lib/libc/asr/bin/common.h create mode 100644 src/regress/lib/libc/asr/bin/getaddrinfo.c create mode 100644 src/regress/lib/libc/asr/bin/getaddrinfo/Makefile create mode 100644 src/regress/lib/libc/asr/bin/gethostnamadr.c create mode 100644 src/regress/lib/libc/asr/bin/gethostnamadr/Makefile create mode 100644 src/regress/lib/libc/asr/bin/getnameinfo.c create mode 100644 src/regress/lib/libc/asr/bin/getnameinfo/Makefile create mode 100644 src/regress/lib/libc/asr/bin/getnetnamadr.c create mode 100644 src/regress/lib/libc/asr/bin/getnetnamadr/Makefile create mode 100644 src/regress/lib/libc/asr/bin/getrrsetbyname.c create mode 100644 src/regress/lib/libc/asr/bin/getrrsetbyname/Makefile create mode 100644 src/regress/lib/libc/asr/bin/res_mkquery.c create mode 100644 src/regress/lib/libc/asr/bin/res_mkquery/Makefile create mode 100644 src/regress/lib/libc/asr/bin/res_query.c create mode 100644 src/regress/lib/libc/asr/bin/res_query/Makefile create mode 100644 src/regress/lib/libc/asr/bin/threads.c create mode 100644 src/regress/lib/libc/asr/bin/threads/Makefile create mode 100644 src/regress/lib/libc/asr/regress.sh create mode 100644 src/regress/lib/libc/asr/regress.subr diff --git a/src/regress/lib/libc/asr/Makefile b/src/regress/lib/libc/asr/Makefile new file mode 100644 index 0000000000..f110cbe25e --- /dev/null +++ b/src/regress/lib/libc/asr/Makefile @@ -0,0 +1,52 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ + +# +# Note on building and running the regress tests: +# +# The regress suite builds two sets of static executables: one linked +# against the current libc, and one linked against a libc with the resolver +# replaced. The idea is to compare the output of all programs in both cases. +# +# So before building the regression test programs, you need to have the two +# libc.a ready. By default, it is assumed that the asr-enabled libc was just +# built from src but not installed, so the current libc.a is expected to be +# found in /usr/lib, and the new one in /usr/obj/lib/libc. If your setting +# is different, just set LIBCDIRSTD and LIBCDIRASR accordingly. +# +# When done, run "make && make install". This builds and installs the two sets +# of programs in REGRESSDIR. They will run chrooted there to allow testing with +# various /etc environment without messing up the local machine config files. +# +# When you are sure everything is in place, run "make regress". This will +# create two files: $REGRESSDIR/output.log with the output of all run tests, +# and $REGRESSDIR/regress.log with the diffs for those that "failed". +# +# Note that "install" and "regress" targets need to be run as root. +# + +LIBCDIRSTD?= /usr/lib +LIBCDIRASR?= /usr/obj/lib/libc + +REGRESSDIR?= /tmp/regress + +all: build + +build: + cd bin && EXT=.asr LDFLAGS=-L${LIBCDIRASR} make + cd bin && EXT=.std LDFLAGS=-L${LIBCDIRSTD} make + +clean: + cd bin && EXT=.std make clean + cd bin && EXT=.asr make clean + +install: + mkdir -p ${REGRESSDIR}/etc + mkdir -p ${REGRESSDIR}/bin + cd bin && BINDIR=${REGRESSDIR}/bin EXT=.std make install + cd bin && BINDIR=${REGRESSDIR}/bin EXT=.asr make install + +uninstall: + rm -rf ${REGRESSDIR} + +regress: + RUNDIR=${REGRESSDIR} sh ${.CURDIR}/regress.sh diff --git a/src/regress/lib/libc/asr/bin/Makefile b/src/regress/lib/libc/asr/bin/Makefile new file mode 100644 index 0000000000..1f986a8e69 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/Makefile @@ -0,0 +1,10 @@ +SUBDIR= res_mkquery +SUBDIR+= res_query +SUBDIR+= gethostnamadr +SUBDIR+= getnetnamadr +SUBDIR+= getrrsetbyname +SUBDIR+= getnameinfo +SUBDIR+= getaddrinfo +SUBDIR+= threads + +.include diff --git a/src/regress/lib/libc/asr/bin/Makefile.inc b/src/regress/lib/libc/asr/bin/Makefile.inc new file mode 100644 index 0000000000..9a03163906 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/Makefile.inc @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile.inc,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ + +NOMAN= noman + +SRCS+= common.c +CFLAGS+= -Wall -Wstrict-prototypes -Werror -Wundef -g +LDFLAGS+= -static +PROG:= ${PROG}${EXT} 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 @@ +/* $OpenBSD: common.c,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +int long_err; +int gai_errno; +int rrset_errno; + + +char * +gethostarg(char *n) +{ + if (n == NULL) + return (n); + if (!strcmp(n, "NULL")) + return (NULL); + if (!strcmp(n, "EMPTY")) + return (""); + return (n); +} + +const char *rrsetstrerror(int); +char * print_addr(const struct sockaddr *, char *, size_t); + +struct kv { int code; const char *name; }; + +struct kv kv_family[] = { + { AF_UNIX, "unix" }, + { AF_INET, "inet" }, + { AF_INET6, "inet6" }, + { AF_IMPLINK, "implink" }, + { AF_BLUETOOTH, "bluetooth" }, + { 0, NULL, } +}; +struct kv kv_socktype[] = { + { SOCK_STREAM, "stream" }, + { SOCK_DGRAM, "dgram" }, + { SOCK_RAW, "raw" }, + { 0, NULL, } +}; +struct kv kv_protocol[] = { + { IPPROTO_UDP, "udp" }, + { IPPROTO_TCP, "tcp" }, + { 0, NULL, } +}; + +static const char * +kv_lookup_name(struct kv *kv, int code) +{ + while (kv->name) { + if (kv->code == code) + return (kv->name); + kv++; + } + return "???"; +} + +struct keyval { + const char *key; + uint16_t value; +}; + +static struct keyval kv_class[] = { + { "IN", C_IN }, + { "CHAOS", C_CHAOS }, + { "HS", C_HS }, + { "ANY", C_ANY }, + { NULL, 0 }, +}; + +static struct keyval kv_type[] = { + { "A", T_A }, + { "NS", T_NS }, + { "MD", T_MD }, + { "MF", T_MF }, + { "CNAME", T_CNAME }, + { "SOA", T_SOA }, + { "MB", T_MB }, + { "MG", T_MG }, + { "MR", T_MR }, + { "NULL", T_NULL }, + { "WKS", T_WKS }, + { "PTR", T_PTR }, + { "HINFO", T_HINFO }, + { "MINFO", T_MINFO }, + { "MX", T_MX }, + { "TXT", T_TXT }, + + { "AAAA", T_AAAA }, + + { "AXFR", T_AXFR }, + { "MAILB", T_MAILB }, + { "MAILA", T_MAILA }, + { "ANY", T_ANY }, + { NULL, 0 }, +}; + +static struct keyval kv_rcode[] = { + { "NOERROR", NOERROR }, + { "FORMERR", FORMERR }, + { "SERVFAIL", SERVFAIL }, + { "NXDOMAIN", NXDOMAIN }, + { "NOTIMP", NOTIMP }, + { "REFUSED", REFUSED }, + { NULL, 0 }, +}; + + +const char * +rcodetostr(uint16_t v) +{ + static char buf[16]; + size_t i; + + for(i = 0; kv_rcode[i].key; i++) + if (kv_rcode[i].value == v) + return (kv_rcode[i].key); + + snprintf(buf, sizeof buf, "%"PRIu16"?", v); + + return (buf); +} + +const char * +typetostr(uint16_t v) +{ + static char buf[16]; + size_t i; + + for(i = 0; kv_type[i].key; i++) + if (kv_type[i].value == v) + return (kv_type[i].key); + + snprintf(buf, sizeof buf, "%"PRIu16"?", v); + + return (buf); +} + +const char * +classtostr(uint16_t v) +{ + static char buf[16]; + size_t i; + + for(i = 0; kv_class[i].key; i++) + if (kv_class[i].value == v) + return (kv_class[i].key); + + snprintf(buf, sizeof buf, "%"PRIu16"?", v); + + return (buf); +} + +uint16_t +strtotype(const char *name) +{ + size_t i; + + for(i = 0; kv_type[i].key; i++) + if (!strcmp(kv_type[i].key, name)) + return (kv_type[i].value); + + return (0); +} + +uint16_t +strtoclass(const char *name) +{ + size_t i; + + for(i = 0; kv_class[i].key; i++) + if (!strcmp(kv_class[i].key, name)) + return (kv_class[i].value); + + return (0); +} + +void +print_hostent(struct hostent *e) +{ + char buf[256], **c; + + printf("name = \"%s\"\n", e->h_name); + printf("aliases ="); + for(c = e->h_aliases; *c; c++) + printf(" \"%s\"", *c); + printf("\n"); + printf("addrtype = %i\n", e->h_addrtype); + printf("addrlength = %i\n", e->h_length); + printf("addr_list ="); + for(c = e->h_addr_list; *c; c++) { + printf(" %s", inet_ntop(e->h_addrtype, *c, buf, sizeof buf)); + } + printf("\n"); +} + +void +print_netent(struct netent *e) +{ + char buf[256], **c; + uint32_t addr; + + /* network number are given in host order */ + addr = htonl(e->n_net); + + printf("name = \"%s\"\n", e->n_name); + printf("aliases ="); + for (c = e->n_aliases; *c; c++) + printf(" \"%s\"", *c); + printf("\n"); + printf("addrtype = %i\n", e->n_addrtype); + printf("net = %s\n", inet_ntop(e->n_addrtype, &addr, buf, sizeof buf)); +} + +void +print_addrinfo(struct addrinfo *ai) +{ + char buf[256]; + + printf("family=%s socktype=%s protocol=%s addr=%s canonname=%s\n", + kv_lookup_name(kv_family, ai->ai_family), + kv_lookup_name(kv_socktype, ai->ai_socktype), + kv_lookup_name(kv_protocol, ai->ai_protocol), + print_addr(ai->ai_addr, buf, sizeof buf), + ai->ai_canonname); +} + +const char * +rrsetstrerror(int e) +{ + switch (e) { + case 0: + return "OK"; + case ERRSET_NONAME: + return "ERRSET_NONAME"; + case ERRSET_NODATA: + return "ERRSET_NODATA"; + case ERRSET_NOMEMORY: + return "ERRSET_NOMEMORY"; + case ERRSET_INVAL: + return "ERRSET_INVAL"; + case ERRSET_FAIL: + return "ERRSET_FAIL"; + default: + return "???"; + } +} + +void +print_rrsetinfo(struct rrsetinfo * rrset) +{ + printf("rri_flags=%u\n", rrset->rri_flags); + printf("rri_rdclass=%u\n", rrset->rri_rdclass); + printf("rri_rdtype=%u\n", rrset->rri_rdtype); + printf("rri_ttl=%u\n", rrset->rri_ttl); + printf("rri_nrdatas=%u\n", rrset->rri_nrdatas); + printf("rri_nsigs=%u\n", rrset->rri_nsigs); + printf("rri_name=\"%s\"\n", rrset->rri_name); +} + +void +print_errors(void) +{ + switch (long_err) { + case 0: + return; + case 1: + printf(" => errno %i, h_errno %i", errno, h_errno); + printf(", rrset_errno %i", rrset_errno); + printf(", gai_errno %i", gai_errno); + printf ("\n"); + return; + default: + printf(" => errno %i: %s\n => h_errno %i: %s\n => rrset_errno %i: %s\n", + errno, errno ? strerror(errno) : "ok", + h_errno, h_errno ? hstrerror(h_errno) : "ok", + rrset_errno, rrset_errno ? rrsetstrerror(rrset_errno) : "ok"); + printf(" => gai_errno %i: %s\n", + gai_errno, gai_errno ? gai_strerror(gai_errno) : "ok"); + } +} + + +static char * +print_host(const struct sockaddr *sa, char *buf, size_t len) +{ + switch (sa->sa_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, + buf, len); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, + buf, len); + break; + default: + buf[0] = '\0'; + } + return (buf); +} + + +char * +print_addr(const struct sockaddr *sa, char *buf, size_t len) +{ + char h[256]; + + print_host(sa, h, sizeof h); + + switch (sa->sa_family) { + case AF_INET: + snprintf(buf, len, "%s:%i", h, + ntohs(((struct sockaddr_in*)(sa))->sin_port)); + break; + case AF_INET6: + snprintf(buf, len, "[%s]:%i", h, + ntohs(((struct sockaddr_in6*)(sa))->sin6_port)); + break; + default: + snprintf(buf, len, "?"); + break; + } + + return (buf); +} + +void +packed_init(struct packed *pack, char *data, size_t len) +{ + pack->data = data; + pack->len = len; + pack->offset = 0; + pack->err = NULL; +} + + +static ssize_t +dname_expand(const unsigned char *data, size_t len, size_t offset, + size_t *newoffset, char *dst, size_t max) +{ + size_t n, count, end, ptr, start; + ssize_t res; + + if (offset >= len) + return (-1); + + res = 0; + end = start = offset; + + for(; (n = data[offset]); ) { + if ((n & 0xc0) == 0xc0) { + if (offset + 2 > len) + return (-1); + ptr = 256 * (n & ~0xc0) + data[offset + 1]; + if (ptr >= start) + return (-1); + if (end < offset + 2) + end = offset + 2; + offset = ptr; + continue; + } + if (offset + n + 1 > len) + return (-1); + + + /* copy n + at offset+1 */ + if (dst != NULL && max != 0) { + count = (max < n + 1) ? (max) : (n + 1); + memmove(dst, data + offset, count); + dst += count; + max -= count; + } + res += n + 1; + offset += n + 1; + if (end < offset) + end = offset; + } + if (end < offset + 1) + end = offset + 1; + + if (dst != NULL && max != 0) + dst[0] = 0; + if (newoffset) + *newoffset = end; + return (res + 1); +} + +static int +unpack_data(struct packed *p, void *data, size_t len) +{ + if (p->err) + return (-1); + + if (p->len - p->offset < len) { + p->err = "too short"; + return (-1); + } + + memmove(data, p->data + p->offset, len); + p->offset += len; + + return (0); +} + +static int +unpack_u16(struct packed *p, uint16_t *u16) +{ + if (unpack_data(p, u16, 2) == -1) + return (-1); + + *u16 = ntohs(*u16); + + return (0); +} + +static int +unpack_u32(struct packed *p, uint32_t *u32) +{ + if (unpack_data(p, u32, 4) == -1) + return (-1); + + *u32 = ntohl(*u32); + + return (0); +} + +static int +unpack_inaddr(struct packed *p, struct in_addr *a) +{ + return (unpack_data(p, a, 4)); +} + +static int +unpack_in6addr(struct packed *p, struct in6_addr *a6) +{ + return (unpack_data(p, a6, 16)); +} + +static int +unpack_dname(struct packed *p, char *dst, size_t max) +{ + ssize_t e; + + if (p->err) + return (-1); + + e = dname_expand(p->data, p->len, p->offset, &p->offset, dst, max); + if (e == -1) { + p->err = "bad domain name"; + return (-1); + } + if (e < 0 || e > MAXDNAME) { + p->err = "domain name too long"; + return (-1); + } + + return (0); +} + +int +unpack_header(struct packed *p, struct header *h) +{ + if (unpack_data(p, h, HFIXEDSZ) == -1) + return (-1); + + h->flags = ntohs(h->flags); + h->qdcount = ntohs(h->qdcount); + h->ancount = ntohs(h->ancount); + h->nscount = ntohs(h->nscount); + h->arcount = ntohs(h->arcount); + + return (0); +} + +int +unpack_query(struct packed *p, struct query *q) +{ + unpack_dname(p, q->q_dname, sizeof(q->q_dname)); + unpack_u16(p, &q->q_type); + unpack_u16(p, &q->q_class); + + return (p->err) ? (-1) : (0); +} + +int +unpack_rr(struct packed *p, struct rr *rr) +{ + uint16_t rdlen; + size_t save_offset; + + unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname)); + unpack_u16(p, &rr->rr_type); + unpack_u16(p, &rr->rr_class); + unpack_u32(p, &rr->rr_ttl); + unpack_u16(p, &rdlen); + + if (p->err) + return (-1); + + if (p->len - p->offset < rdlen) { + p->err = "too short"; + return (-1); + } + + save_offset = p->offset; + + switch(rr->rr_type) { + + case T_CNAME: + unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname)); + break; + + case T_MX: + unpack_u16(p, &rr->rr.mx.preference); + unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange)); + break; + + case T_NS: + unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname)); + break; + + case T_PTR: + unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname)); + break; + + case T_SOA: + unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname)); + unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname)); + unpack_u32(p, &rr->rr.soa.serial); + unpack_u32(p, &rr->rr.soa.refresh); + unpack_u32(p, &rr->rr.soa.retry); + unpack_u32(p, &rr->rr.soa.expire); + unpack_u32(p, &rr->rr.soa.minimum); + break; + + case T_A: + if (rr->rr_class != C_IN) + goto other; + unpack_inaddr(p, &rr->rr.in_a.addr); + break; + + case T_AAAA: + if (rr->rr_class != C_IN) + goto other; + unpack_in6addr(p, &rr->rr.in_aaaa.addr6); + break; + default: + other: + rr->rr.other.rdata = p->data + p->offset; + rr->rr.other.rdlen = rdlen; + p->offset += rdlen; + } + + if (p->err) + return (-1); + + /* make sure that the advertised rdlen is really ok */ + if (p->offset - save_offset != rdlen) + p->err = "bad dlen"; + + return (p->err) ? (-1) : (0); +} + +int +sockaddr_from_str(struct sockaddr *sa, int family, const char *str) +{ + struct in_addr ina; + struct in6_addr in6a; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + switch (family) { + case PF_UNSPEC: + if (sockaddr_from_str(sa, PF_INET, str) == 0) + return (0); + return sockaddr_from_str(sa, PF_INET6, str); + + case PF_INET: + if (inet_pton(PF_INET, str, &ina) != 1) + return (-1); + + sin = (struct sockaddr_in *)sa; + memset(sin, 0, sizeof *sin); + sin->sin_len = sizeof(struct sockaddr_in); + sin->sin_family = PF_INET; + sin->sin_addr.s_addr = ina.s_addr; + return (0); + + case PF_INET6: + if (inet_pton(PF_INET6, str, &in6a) != 1) + return (-1); + + sin6 = (struct sockaddr_in6 *)sa; + memset(sin6, 0, sizeof *sin6); + sin6->sin6_len = sizeof(struct sockaddr_in6); + sin6->sin6_family = PF_INET6; + sin6->sin6_addr = in6a; + return (0); + + default: + break; + } + + return (-1); +} diff --git a/src/regress/lib/libc/asr/bin/common.h b/src/regress/lib/libc/asr/bin/common.h new file mode 100644 index 0000000000..87df4ae4a2 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/common.h @@ -0,0 +1,136 @@ +/* $OpenBSD: common.h,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include + +#include + +#include + +#include + + +#define unpack_rr __unpack_rr +#define unpack_header __unpack_header +#define packed_init __packed_init +#define unpack_query __unpack_query +#define sockaddr_from_str __sockaddr_from_str +#define print_addr __print_addr + +extern int long_err; +extern int gai_errno; +extern int rrset_errno; + +const char *classtostr(uint16_t); +const char *typetostr(uint16_t); +const char *rcodetostr(uint16_t); + +uint16_t strtotype(const char*); +uint16_t strtoclass(const char*); + +void print_rrsetinfo(struct rrsetinfo *); +void print_addrinfo(struct addrinfo *); +void print_errors(void); +void print_hostent(struct hostent *); +void print_netent(struct netent *); + +int sockaddr_from_str(struct sockaddr *, int, const char *); +int addr_from_str(char *, int *, int *, const char *); +char* gethostarg(char *); + +#define QR_MASK (0x1 << 15) +#define OPCODE_MASK (0xf << 11) +#define AA_MASK (0x1 << 10) +#define TC_MASK (0x1 << 9) +#define RD_MASK (0x1 << 8) +#define RA_MASK (0x1 << 7) +#define Z_MASK (0x7 << 4) +#define RCODE_MASK (0xf) + +#define OPCODE(v) ((v) & OPCODE_MASK) +#define RCODE(v) ((v) & RCODE_MASK) + + +struct packed { + char *data; + size_t len; + size_t offset; + const char *err; +}; + +struct header { + uint16_t id; + uint16_t flags; + uint16_t qdcount; + uint16_t ancount; + uint16_t nscount; + uint16_t arcount; +}; + +struct query { + char q_dname[MAXDNAME]; + uint16_t q_type; + uint16_t q_class; +}; + +struct rr { + char rr_dname[MAXDNAME]; + uint16_t rr_type; + uint16_t rr_class; + uint32_t rr_ttl; + union { + struct { + char cname[MAXDNAME]; + } cname; + struct { + uint16_t preference; + char exchange[MAXDNAME]; + } mx; + struct { + char nsname[MAXDNAME]; + } ns; + struct { + char ptrname[MAXDNAME]; + } ptr; + struct { + char mname[MAXDNAME]; + char rname[MAXDNAME]; + uint32_t serial; + uint32_t refresh; + uint32_t retry; + uint32_t expire; + uint32_t minimum; + } soa; + struct { + struct in_addr addr; + } in_a; + struct { + struct in6_addr addr6; + } in_aaaa; + struct { + uint16_t rdlen; + const void *rdata; + } other; + } rr; +}; + +void packed_init(struct packed*, char*, size_t); +int pack_header(struct packed*, const struct header*); +int pack_query(struct packed*, uint16_t, uint16_t, const char*); +int unpack_header(struct packed*, struct header*); +int unpack_query(struct packed*, struct query*); +int unpack_rr(struct packed*, struct rr*); diff --git a/src/regress/lib/libc/asr/bin/getaddrinfo.c b/src/regress/lib/libc/asr/bin/getaddrinfo.c new file mode 100644 index 0000000000..8c4abf361e --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getaddrinfo.c @@ -0,0 +1,131 @@ +/* $OpenBSD: getaddrinfo.c,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + extern const char * __progname; + + fprintf(stderr, "usage: %s [-CHSPe] [-f family] [-p proto] " + "[-s servname]\n [-t socktype] \n", __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + struct addrinfo *ai, *res, hints; + char *servname = NULL, *host; + int i, ch; + + memset(&hints, 0, sizeof hints); + + while((ch = getopt(argc, argv, "CFHPSef:p:s:t:")) != -1) { + switch(ch) { + case 'C': + hints.ai_flags |= AI_CANONNAME; + break; + case 'F': + hints.ai_flags |= AI_FQDN; + break; + case 'H': + hints.ai_flags |= AI_NUMERICHOST; + break; + case 'P': + hints.ai_flags |= AI_PASSIVE; + break; + case 'S': + hints.ai_flags |= AI_NUMERICSERV; + break; + case 'e': + long_err += 1; + break; + case 'f': + if (!strcmp(optarg, "inet")) + hints.ai_family = AF_INET; + else if (!strcmp(optarg, "inet6")) + hints.ai_family = AF_INET6; + else + usage(); + break; + case 'p': + if (!strcmp(optarg, "udp")) + hints.ai_protocol = IPPROTO_UDP; + else if (!strcmp(optarg, "tcp")) + hints.ai_protocol = IPPROTO_TCP; + else + usage(); + break; + case 's': + servname = optarg; + break; + case 't': + if (!strcmp(optarg, "stream")) + hints.ai_socktype = SOCK_STREAM; + else if (!strcmp(optarg, "dgram")) + hints.ai_socktype = SOCK_DGRAM; + else if (!strcmp(optarg, "raw")) + hints.ai_socktype = SOCK_RAW; + else + usage(); + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + for(i = 0; i < argc; i++) { + + if (i) + printf("\n"); + printf("===> \"%s\"\n", argv[i]); + host = gethostarg(argv[i]); + + errno = 0; + h_errno = 0; + gai_errno = 0; + rrset_errno = 0; + + gai_errno = getaddrinfo(host, servname, &hints, &ai); + + print_errors(); + if (gai_errno == 0) { + for (res = ai; res; res = res->ai_next) + print_addrinfo(res); + freeaddrinfo(ai); + } + } + + return (0); +} diff --git a/src/regress/lib/libc/asr/bin/getaddrinfo/Makefile b/src/regress/lib/libc/asr/bin/getaddrinfo/Makefile new file mode 100644 index 0000000000..ec2f104ec7 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getaddrinfo/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= getaddrinfo +SRCS+= getaddrinfo.c + +.include diff --git a/src/regress/lib/libc/asr/bin/gethostnamadr.c b/src/regress/lib/libc/asr/bin/gethostnamadr.c new file mode 100644 index 0000000000..336c6b9db3 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/gethostnamadr.c @@ -0,0 +1,112 @@ +/* $OpenBSD: gethostnamadr.c,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + extern const char * __progname; + + fprintf(stderr, "usage: %s [-46e] \n", __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int i, ch, isname, family = AF_INET; + struct hostent *h; + char *host; + char addr[16]; + int addraf; + int addrlen; + + while((ch = getopt(argc, argv, "46e")) != -1) { + switch(ch) { + case '4': + family = AF_INET; + break; + case '6': + family = AF_INET6; + break; + case 'e': + long_err += 1; + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + for(i = 0; i < argc; i++) { + + if (i) + printf("\n"); + printf("===> \"%s\"\n", argv[i]); + host = gethostarg(argv[i]); + + if (addr_from_str(addr, &addraf, &addrlen, argv[i]) == -1) + isname = 1; + else + isname = 0; + + errno = 0; + h_errno = 0; + gai_errno = 0; + rrset_errno = 0; + + if (isname) + h = gethostbyname2(host, family); + else + h = gethostbyaddr(addr, addrlen, addraf); + if (h) + print_hostent(h); + print_errors(); + } + + return (0); +} + +int +addr_from_str(char *addr, int *family, int *len, const char *src) +{ + if (inet_pton(AF_INET6, src, addr) == 1) { + *family = AF_INET6; + *len = 16; + return (0); + } + if (inet_pton(AF_INET, src, addr) == 1) { + *family = AF_INET; + *len = 4; + return (0); + } + return (-1); +} diff --git a/src/regress/lib/libc/asr/bin/gethostnamadr/Makefile b/src/regress/lib/libc/asr/bin/gethostnamadr/Makefile new file mode 100644 index 0000000000..84906ffbbd --- /dev/null +++ b/src/regress/lib/libc/asr/bin/gethostnamadr/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= gethostnamadr +SRCS+= gethostnamadr.c + +.include diff --git a/src/regress/lib/libc/asr/bin/getnameinfo.c b/src/regress/lib/libc/asr/bin/getnameinfo.c new file mode 100644 index 0000000000..8702937a47 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getnameinfo.c @@ -0,0 +1,112 @@ +/* $OpenBSD: getnameinfo.c,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + extern const char * __progname; + + fprintf(stderr, "usage: %s [-DFHNSe] [-p portno] \n", __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char serv[1024]; + char host[1024]; + const char *e; + int i, ch, flags = 0, port = 0; + struct sockaddr_storage ss; + struct sockaddr *sa; + + sa = (struct sockaddr*)&ss; + + while((ch = getopt(argc, argv, "DFHNSaep:")) != -1) { + switch(ch) { + case 'D': + flags |= NI_DGRAM; + break; + case 'F': + flags |= NI_NOFQDN; + break; + case 'H': + flags |= NI_NUMERICHOST; + break; + case 'N': + flags |= NI_NAMEREQD; + break; + case 'S': + flags |= NI_NUMERICSERV; + break; + case 'e': + long_err += 1; + break; + case 'p': + port = strtonum(optarg, 0, 65535, &e); + if (e) + usage(); + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + for(i = 0; i < argc; i++) { + + if (i) + printf("\n"); + printf("===> \"%s\"\n", argv[i]); + + if (sockaddr_from_str(sa, AF_UNSPEC, argv[i]) == -1) { + printf(" => invalid address\n"); + continue; + } + + if (sa->sa_family == PF_INET) + ((struct sockaddr_in *)sa)->sin_port = htons(port); + else if (sa->sa_family == PF_INET6) + ((struct sockaddr_in6 *)sa)->sin6_port = htons(port); + + errno = 0; + h_errno = 0; + gai_errno = 0; + rrset_errno = 0; + + gai_errno = getnameinfo(sa, sa->sa_len, host, sizeof host, serv, + sizeof serv, flags); + + if (gai_errno == 0) + printf(" %s:%s\n", host, serv); + print_errors(); + + } + + return (0); +} diff --git a/src/regress/lib/libc/asr/bin/getnameinfo/Makefile b/src/regress/lib/libc/asr/bin/getnameinfo/Makefile new file mode 100644 index 0000000000..4927ee9486 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getnameinfo/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= getnameinfo +SRCS+= getnameinfo.c + +.include diff --git a/src/regress/lib/libc/asr/bin/getnetnamadr.c b/src/regress/lib/libc/asr/bin/getnetnamadr.c new file mode 100644 index 0000000000..4b7414264b --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getnetnamadr.c @@ -0,0 +1,85 @@ +/* $OpenBSD: getnetnamadr.c,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + extern const char * __progname; + + fprintf(stderr, "usage: %s [-aen] [host...]\n", __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int i, ch, nflag = 0; + struct netent *n; + char *host; + + while((ch = getopt(argc, argv, "en")) != -1) { + switch(ch) { + case 'e': + long_err += 1; + break; + case 'n': + nflag = 1; + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + for(i = 0; i < argc; i++) { + + if (i) + printf("\n"); + printf("===> \"%s\"\n", argv[i]); + host = gethostarg(argv[i]); + + errno = 0; + h_errno = 0; + gai_errno = 0; + rrset_errno = 0; + + if (nflag) + n = getnetbyname(host); + else + n = getnetbyaddr(inet_network(host), AF_INET); + if (n) + print_netent(n); + print_errors(); + } + + return (0); +} diff --git a/src/regress/lib/libc/asr/bin/getnetnamadr/Makefile b/src/regress/lib/libc/asr/bin/getnetnamadr/Makefile new file mode 100644 index 0000000000..521bf8eb7e --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getnetnamadr/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= getnetnamadr +SRCS+= getnetnamadr.c + +.include diff --git a/src/regress/lib/libc/asr/bin/getrrsetbyname.c b/src/regress/lib/libc/asr/bin/getrrsetbyname.c new file mode 100644 index 0000000000..4a5aa57209 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getrrsetbyname.c @@ -0,0 +1,88 @@ +/* $OpenBSD: getrrsetbyname.c,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + extern const char * __progname; + + fprintf(stderr, "usage: %s [-e] [-t type] [host...]\n", + __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int ch, i; + uint16_t type = T_A; + char *host; + struct rrsetinfo *rrset; + + while((ch = getopt(argc, argv, "et:")) != -1) { + switch(ch) { + case 'e': + long_err += 1; + break; + case 't': + if ((type = strtotype(optarg)) == 0) + usage(); + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + for (i = 0; i < argc; i++) { + + if (i) + printf("\n"); + printf("===> \"%s\"\n", argv[i]); + host = gethostarg(argv[i]); + + errno = 0; + h_errno = 0; + gai_errno = 0; + rrset_errno = 0; + + rrset_errno = getrrsetbyname(host, C_IN, type, 0, &rrset); + + if (rrset_errno == 0) + print_rrsetinfo(rrset); + print_errors(); + } + + return (0); +} diff --git a/src/regress/lib/libc/asr/bin/getrrsetbyname/Makefile b/src/regress/lib/libc/asr/bin/getrrsetbyname/Makefile new file mode 100644 index 0000000000..131403bea1 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/getrrsetbyname/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= getrrsetbyname +SRCS+= getrrsetbyname.c + +.include diff --git a/src/regress/lib/libc/asr/bin/res_mkquery.c b/src/regress/lib/libc/asr/bin/res_mkquery.c new file mode 100644 index 0000000000..a52023c5c0 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/res_mkquery.c @@ -0,0 +1,319 @@ +/* $OpenBSD: res_mkquery.c,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/* in asr.c but we don't want them exposed right now */ +static void dump_packet(const void *, size_t); + +static char *print_query(struct query *, char *, size_t); +static char *print_rr(struct rr *, char *, size_t); +static char *print_host(const struct sockaddr *, char *, size_t); +static char* print_dname(const char *, char *, size_t); + + +static void +usage(void) +{ + extern const char * __progname; + + fprintf(stderr, "usage: %s [-deq] [-t type] [host...]\n", + __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int ch, i, r; + uint16_t type = T_A; + char buf[1024], *host; + + while((ch = getopt(argc, argv, "et:")) != -1) { + switch(ch) { + case 'e': + long_err += 1; + break; + case 't': + if ((type = strtotype(optarg)) == 0) + usage(); + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + for (i = 0; i < argc; i++) { + + if (i) + printf("\n"); + + printf("===> \"%s\"\n", argv[i]); + host = gethostarg(argv[i]); + + errno = 0; + h_errno = 0; + gai_errno = 0; + rrset_errno = 0; + + r = res_mkquery(QUERY, host, C_IN, type, NULL, 0, NULL, buf, sizeof(buf)); + if (r != -1) { + dump_packet(buf, r); + printf(";; MSG SIZE %i\n", r); + } + print_errors(); + } + + return (0); +} + +#define OPCODE_SHIFT 11 +#define Z_SHIFT 4 + +static char* +print_header(struct header *h, char *buf, size_t max) +{ + snprintf(buf, max, + "id:0x.... %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i", + (h->flags & QR_MASK) ? "QR":" ", + (int)(OPCODE(h->flags) >> OPCODE_SHIFT), + (h->flags & AA_MASK) ? "AA":" ", + (h->flags & TC_MASK) ? "TC":" ", + (h->flags & RD_MASK) ? "RD":" ", + (h->flags & RA_MASK) ? "RA":" ", + ((h->flags & Z_MASK) >> Z_SHIFT), + rcodetostr(RCODE(h->flags)), + h->qdcount, h->ancount, h->nscount, h->arcount); + + return buf; +} + +static void +dump_packet(const void *data, size_t len) +{ + char buf[1024]; + struct packed p; + struct header h; + struct query q; + struct rr rr; + int i, an, ns, ar, n; + + packed_init(&p, (char *)data, len); + + if (unpack_header(&p, &h) == -1) { + printf(";; BAD PACKET: %s\n", p.err); + return; + } + + printf(";; HEADER %s\n", print_header(&h, buf, sizeof buf)); + + if (h.qdcount) + printf(";; QUERY SECTION:\n"); + for (i = 0; i < h.qdcount; i++) { + if (unpack_query(&p, &q) == -1) + goto error; + printf("%s\n", print_query(&q, buf, sizeof buf)); + } + + an = 0; + ns = an + h.ancount; + ar = ns + h.nscount; + n = ar + h.arcount; + + for (i = 0; i < n; i++) { + if (i == an) + printf("\n;; ANSWER SECTION:\n"); + if (i == ns) + printf("\n;; AUTHORITY SECTION:\n"); + if (i == ar) + printf("\n;; ADDITIONAL SECTION:\n"); + + if (unpack_rr(&p, &rr) == -1) + goto error; + printf("%s\n", print_rr(&rr, buf, sizeof buf)); + } + + if (p.offset != len) + printf(";; REMAINING GARBAGE %zu\n", len - p.offset); + + error: + if (p.err) + printf(";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len, + p.err); +} + +static const char * +inet6_ntoa(struct in6_addr a) +{ + static char buf[256]; + struct sockaddr_in6 si; + + si.sin6_len = sizeof(si); + si.sin6_family = PF_INET6; + si.sin6_addr = a; + + return print_host((struct sockaddr*)&si, buf, sizeof buf); +} + +static char* +print_rr(struct rr *rr, char *buf, size_t max) +{ + char *res; + char tmp[256]; + char tmp2[256]; + int r; + + res = buf; + + r = snprintf(buf, max, "%s %u %s %s ", + print_dname(rr->rr_dname, tmp, sizeof tmp), + rr->rr_ttl, + classtostr(rr->rr_class), + typetostr(rr->rr_type)); + if (r == -1) { + buf[0] = '\0'; + return buf; + } + + if ((size_t)r >= max) + return buf; + + max -= r; + buf += r; + + switch(rr->rr_type) { + case T_CNAME: + print_dname(rr->rr.cname.cname, buf, max); + break; + case T_MX: + snprintf(buf, max, "%"PRIu32" %s", + rr->rr.mx.preference, + print_dname(rr->rr.mx.exchange, tmp, sizeof tmp)); + break; + case T_NS: + print_dname(rr->rr.ns.nsname, buf, max); + break; + case T_PTR: + print_dname(rr->rr.ptr.ptrname, buf, max); + break; + case T_SOA: + snprintf(buf, max, + "%s %s %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32, + print_dname(rr->rr.soa.rname, tmp, sizeof tmp), + print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2), + rr->rr.soa.serial, + rr->rr.soa.refresh, + rr->rr.soa.retry, + rr->rr.soa.expire, + rr->rr.soa.minimum); + break; + case T_A: + if (rr->rr_class != C_IN) + goto other; + snprintf(buf, max, "%s", inet_ntoa(rr->rr.in_a.addr)); + break; + case T_AAAA: + if (rr->rr_class != C_IN) + goto other; + snprintf(buf, max, "%s", inet6_ntoa(rr->rr.in_aaaa.addr6)); + break; + default: + other: + snprintf(buf, max, "(rdlen=%"PRIu16 ")", rr->rr.other.rdlen); + break; + } + + return (res); +} + +static char* +print_query(struct query *q, char *buf, size_t max) +{ + char b[256]; + + snprintf(buf, max, "%s %s %s", + print_dname(q->q_dname, b, sizeof b), + classtostr(q->q_class), typetostr(q->q_type)); + + return (buf); +} + + +static char * +print_host(const struct sockaddr *sa, char *buf, size_t len) +{ + switch (sa->sa_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, buf, len); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, buf, len); + break; + default: + buf[0] = '\0'; + } + return (buf); +} + +static char* +print_dname(const char *_dname, char *buf, size_t max) +{ + const unsigned char *dname = _dname; + char *res; + size_t left, n, count; + + if (_dname[0] == 0) { + strlcpy(buf, ".", max); + return buf; + } + + res = buf; + left = max - 1; + for (n = 0; dname[0] && left; n += dname[0]) { + count = (dname[0] < (left - 1)) ? dname[0] : (left - 1); + memmove(buf, dname + 1, count); + dname += dname[0] + 1; + left -= count; + buf += count; + if (left) { + left -= 1; + *buf++ = '.'; + } + } + buf[0] = 0; + + return (res); +} diff --git a/src/regress/lib/libc/asr/bin/res_mkquery/Makefile b/src/regress/lib/libc/asr/bin/res_mkquery/Makefile new file mode 100644 index 0000000000..770fa9f633 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/res_mkquery/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= res_mkquery${BINEXT} +SRCS+= res_mkquery.c + +.include diff --git a/src/regress/lib/libc/asr/bin/res_query.c b/src/regress/lib/libc/asr/bin/res_query.c new file mode 100644 index 0000000000..fd96f1de22 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/res_query.c @@ -0,0 +1,354 @@ +/* $OpenBSD: res_query.c,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/* in asr.c but we don't want them exposed right now */ +static void dump_packet(const void *, size_t); + +static char *print_query(struct query *, char *, size_t); +static char *print_rr(struct rr *, char *, size_t); +static char *print_host(const struct sockaddr *, char *, size_t); +static char* print_dname(const char *, char *, size_t); + + +static int +msec(struct timeval start, struct timeval end) +{ + return (int)((end.tv_sec - start.tv_sec) * 1000 + + (end.tv_usec - start.tv_usec) / 1000); +} + +static void +usage(void) +{ + extern const char * __progname; + + fprintf(stderr, "usage: %s [-deq] [-t type] [host...]\n", + __progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + struct timeval start, end; + time_t when; + int ch, i, qflag, dflag, r; + uint16_t type = T_A; + char buf[1024], *host; + + dflag = 0; + qflag = 0; + + while((ch = getopt(argc, argv, "deqt:")) != -1) { + switch(ch) { + case 'd': + dflag = 1; + break; + case 'e': + long_err += 1; + break; + case 'q': + qflag = 1; + break; + case 't': + if ((type = strtotype(optarg)) == 0) + usage(); + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + for (i = 0; i < argc; i++) { + + if (i) + printf("\n"); + + printf("===> \"%s\"\n", argv[i]); + host = gethostarg(argv[i]); + + errno = 0; + h_errno = 0; + gai_errno = 0; + rrset_errno = 0; + + if (gettimeofday(&start, NULL) != 0) + err(1, "gettimeofday"); + + if (qflag) + r = res_query(host, C_IN, type, buf, sizeof(buf)); + else + r = res_search(host, C_IN, type, buf, sizeof(buf)); + + if (gettimeofday(&end, NULL) != 0) + err(1, "gettimeofday"); + + if (r != -1) { + dump_packet(buf, r); + printf("\n"); + if (dflag) { + printf(";; Query time: %d msec\n", + msec(start, end)); + when = time(NULL); + printf(";; WHEN: %s", ctime(&when)); + } + printf(";; MSG SIZE rcvd: %i\n", r); + } + print_errors(); + } + + return (0); +} + +#define OPCODE_SHIFT 11 +#define Z_SHIFT 4 + +static char* +print_header(struct header *h, char *buf, size_t max) +{ + snprintf(buf, max, + "id:0x.... %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i", + (h->flags & QR_MASK) ? "QR":" ", + (int)(OPCODE(h->flags) >> OPCODE_SHIFT), + (h->flags & AA_MASK) ? "AA":" ", + (h->flags & TC_MASK) ? "TC":" ", + (h->flags & RD_MASK) ? "RD":" ", + (h->flags & RA_MASK) ? "RA":" ", + ((h->flags & Z_MASK) >> Z_SHIFT), + rcodetostr(RCODE(h->flags)), + h->qdcount, h->ancount, h->nscount, h->arcount); + + return buf; +} + +static void +dump_packet(const void *data, size_t len) +{ + char buf[1024]; + struct packed p; + struct header h; + struct query q; + struct rr rr; + int i, an, ns, ar, n; + + packed_init(&p, (char *)data, len); + + if (unpack_header(&p, &h) == -1) { + printf(";; BAD PACKET: %s\n", p.err); + return; + } + + printf(";; HEADER %s\n", print_header(&h, buf, sizeof buf)); + + if (h.qdcount) + printf(";; QUERY SECTION:\n"); + for (i = 0; i < h.qdcount; i++) { + if (unpack_query(&p, &q) == -1) + goto error; + printf("%s\n", print_query(&q, buf, sizeof buf)); + } + + an = 0; + ns = an + h.ancount; + ar = ns + h.nscount; + n = ar + h.arcount; + + for (i = 0; i < n; i++) { + if (i == an) + printf("\n;; ANSWER SECTION:\n"); + if (i == ns) + printf("\n;; AUTHORITY SECTION:\n"); + if (i == ar) + printf("\n;; ADDITIONAL SECTION:\n"); + + if (unpack_rr(&p, &rr) == -1) + goto error; + printf("%s\n", print_rr(&rr, buf, sizeof buf)); + } + + if (p.offset != len) + printf(";; REMAINING GARBAGE %zu\n", len - p.offset); + + error: + if (p.err) + printf(";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len, + p.err); +} + +static const char * +inet6_ntoa(struct in6_addr a) +{ + static char buf[256]; + struct sockaddr_in6 si; + + si.sin6_len = sizeof(si); + si.sin6_family = PF_INET6; + si.sin6_addr = a; + + return print_host((struct sockaddr*)&si, buf, sizeof buf); +} + +static char* +print_rr(struct rr *rr, char *buf, size_t max) +{ + char *res; + char tmp[256]; + char tmp2[256]; + int r; + + res = buf; + + r = snprintf(buf, max, "%s %u %s %s ", + print_dname(rr->rr_dname, tmp, sizeof tmp), + rr->rr_ttl, + classtostr(rr->rr_class), + typetostr(rr->rr_type)); + if (r == -1) { + buf[0] = '\0'; + return buf; + } + + if ((size_t)r >= max) + return buf; + + max -= r; + buf += r; + + switch(rr->rr_type) { + case T_CNAME: + print_dname(rr->rr.cname.cname, buf, max); + break; + case T_MX: + snprintf(buf, max, "%"PRIu32" %s", + rr->rr.mx.preference, + print_dname(rr->rr.mx.exchange, tmp, sizeof tmp)); + break; + case T_NS: + print_dname(rr->rr.ns.nsname, buf, max); + break; + case T_PTR: + print_dname(rr->rr.ptr.ptrname, buf, max); + break; + case T_SOA: + snprintf(buf, max, + "%s %s %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32 " %" PRIu32, + print_dname(rr->rr.soa.rname, tmp, sizeof tmp), + print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2), + rr->rr.soa.serial, + rr->rr.soa.refresh, + rr->rr.soa.retry, + rr->rr.soa.expire, + rr->rr.soa.minimum); + break; + case T_A: + if (rr->rr_class != C_IN) + goto other; + snprintf(buf, max, "%s", inet_ntoa(rr->rr.in_a.addr)); + break; + case T_AAAA: + if (rr->rr_class != C_IN) + goto other; + snprintf(buf, max, "%s", inet6_ntoa(rr->rr.in_aaaa.addr6)); + break; + default: + other: + snprintf(buf, max, "(rdlen=%"PRIu16 ")", rr->rr.other.rdlen); + break; + } + + return (res); +} + +static char* +print_query(struct query *q, char *buf, size_t max) +{ + char b[256]; + + snprintf(buf, max, "%s %s %s", + print_dname(q->q_dname, b, sizeof b), + classtostr(q->q_class), typetostr(q->q_type)); + + return (buf); +} + + +static char * +print_host(const struct sockaddr *sa, char *buf, size_t len) +{ + switch (sa->sa_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr, buf, len); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr, buf, len); + break; + default: + buf[0] = '\0'; + } + return (buf); +} + +static char* +print_dname(const char *_dname, char *buf, size_t max) +{ + const unsigned char *dname = _dname; + char *res; + size_t left, n, count; + + if (_dname[0] == 0) { + strlcpy(buf, ".", max); + return buf; + } + + res = buf; + left = max - 1; + for (n = 0; dname[0] && left; n += dname[0]) { + count = (dname[0] < (left - 1)) ? dname[0] : (left - 1); + memmove(buf, dname + 1, count); + dname += dname[0] + 1; + left -= count; + buf += count; + if (left) { + left -= 1; + *buf++ = '.'; + } + } + buf[0] = 0; + + return (res); +} diff --git a/src/regress/lib/libc/asr/bin/res_query/Makefile b/src/regress/lib/libc/asr/bin/res_query/Makefile new file mode 100644 index 0000000000..75380ee079 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/res_query/Makefile @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= res_query${BINEXT} +SRCS+= res_query.c + +.include diff --git a/src/regress/lib/libc/asr/bin/threads.c b/src/regress/lib/libc/asr/bin/threads.c new file mode 100644 index 0000000000..f296f1d6f7 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/threads.c @@ -0,0 +1,140 @@ +/* $OpenBSD: threads.c,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ */ +/* + * Copyright (c) 2012 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_THREADS 50 + +int ac; +char **av; +int loop; +int nthreads; + +int long_err; +int gai_errno; +int rrset_errno; + +void async_resolver_done(void *); + +void stats(void) +{ + struct rusage ru; + + getrusage(RUSAGE_SELF, &ru); + printf("%li\n", ru.ru_maxrss); +} + +void* +task(void *arg) +{ + int id, i, j, c; + struct addrinfo *ai, *n; + + id = *((int*) arg); + + n = NULL; c =0; + + for(j = 0; j < loop; j++) + for(i = 0; i < ac; i++) { + if (getaddrinfo(av[i], NULL, NULL, &ai) == 0) { +/* + for (c = 0, n = ai; n; c++, n = n->ai_next); + printf("%i:%s: ok: %i\n", id, av[i], c); +*/ + freeaddrinfo(ai); + } else { +/* + printf("%i:%s: fail\n", id, av[i]); +*/ + } + } + return (NULL); +} + +void +usage(void) +{ + extern const char *__progname; + fprintf(stderr, "usage: %s [-L loop] [-l loop] [-t threads] ...\n", + __progname); +} + +int +main(int argc, char **argv) +{ + pthread_t th[MAX_THREADS]; + int th_args[MAX_THREADS], r, i, ch; + int n, LOOP; + + nthreads = 1; + loop = 1; + LOOP = 1; + + while ((ch = getopt(argc, argv, "L:l:t:")) != -1) { + switch (ch) { + case 'L': + LOOP = atoi(optarg); + break; + case 'l': + loop = atoi(optarg); + break; + case 't': + nthreads = atoi(optarg); + if (nthreads > MAX_THREADS) + nthreads = MAX_THREADS; + break; + default: + usage(); + /* NOTREACHED */ + } + } + + argc -= optind; + argv += optind; + + ac = argc; + av = argv; + + printf("%i %i %i\n", LOOP, nthreads, loop); + for (n = 0; n < LOOP; n ++) { + for (i = 0; i < nthreads; i++) { + th_args[i] = i; + r = pthread_create(&th[i], NULL, task, (void *) &th_args[i]); + if (r == -1) + errx(1, "pthread_create"); + } + for (i = 0; i < nthreads; i++) + pthread_join(th[i], NULL); + + if (nthreads == 0) + task(&n); + + stats(); + } + + return (0); +} diff --git a/src/regress/lib/libc/asr/bin/threads/Makefile b/src/regress/lib/libc/asr/bin/threads/Makefile new file mode 100644 index 0000000000..3252511cd1 --- /dev/null +++ b/src/regress/lib/libc/asr/bin/threads/Makefile @@ -0,0 +1,10 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2012/07/13 17:49:54 eric Exp $ + +.PATH: ${.CURDIR}/.. + +PROG= threads +SRCS+= threads.c + +LDADD= -lpthread + +.include diff --git a/src/regress/lib/libc/asr/regress.sh b/src/regress/lib/libc/asr/regress.sh new file mode 100644 index 0000000000..b4d1c1db59 --- /dev/null +++ b/src/regress/lib/libc/asr/regress.sh @@ -0,0 +1,104 @@ +# $OpenBSD: regress.sh,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ + +. regress.subr + +EFLAG= + +test_res_mkquery() +{ + for i in $@; do + regress res_mkquery $i + done +} + +test_res_query() +{ + for i in $@; do + regress res_query $i + regress res_query -q $i + done +} + +test_getrrsetbyname() +{ + for i in $@; do + regress getrrsetbyname $i + regress getrrsetbyname -t MX $i + regress getrrsetbyname -t AAAA $i + done +} + +test_gethostbyname() +{ + for i in $@; do + regress gethostnamadr $i + regress gethostnamadr -4 $i + regress gethostnamadr -6 $i + done +} + +test_gethostbyaddr() +{ + for i in $@; do + regress gethostnamadr $i + done +} + +test_getaddrinfo() +{ + for i in $@; do + regress getaddrinfo $i + regress getaddrinfo -C $i + regress getaddrinfo -F $i + regress getaddrinfo -CF $i + regress getaddrinfo -P $i + regress getaddrinfo -PF $i + regress getaddrinfo -PC $i + regress getaddrinfo -H $i + regress getaddrinfo -p tcp $i + regress getaddrinfo -p udp $i + regress getaddrinfo -s www $i + regress getaddrinfo -s bad $i + regress getaddrinfo -S -s 8081 $i + regress getaddrinfo -S -s bad $i + regress getaddrinfo -P -s syslog $i + regress getaddrinfo -P -s syslog -p tcp $i + regress getaddrinfo -P -s syslog -p udp $i + done +} + +test_getnameinfo() +{ + for i in $@; do + regress getnameinfo $i + regress getnameinfo -D $i + regress getnameinfo -F $i + regress getnameinfo -H $i + regress getnameinfo -N $i + regress getnameinfo -S $i + regress getnameinfo -p 80 $i + regress getnameinfo -p 514 $i + regress getnameinfo -p 514 -D $i + regress getnameinfo -p 5566 $i + done +} + +WEIRD="EMPTY . .. ..." +BASIC="localhost $(hostname -s) $(hostname)" +EXTRA="undeadly.org www.openbsd.org cvs.openbsd.org" + +ADDRS="0.0.0.0 :: 127.0.0.1 ::1 212.227.193.194" + +for e in file bind; do + regress_setenv $e + + test_res_mkquery $WEIRD $BASIC + test_res_query $WEIRD $BASIC $EXTRA + test_getrrsetbyname $WEIRD $BASIC $EXTRA + test_gethostbyname $WEIRD $BASIC $EXTRA + test_gethostbyaddr $ADDRS + test_getaddrinfo NULL $WEIRD $BASIC $EXTRA + test_getnameinfo $ADDRS +done + +regress_digest diff --git a/src/regress/lib/libc/asr/regress.subr b/src/regress/lib/libc/asr/regress.subr new file mode 100644 index 0000000000..dafb7ddf75 --- /dev/null +++ b/src/regress/lib/libc/asr/regress.subr @@ -0,0 +1,114 @@ +#!/bin/sh +# $OpenBSD: regress.subr,v 1.1.1.1 2012/07/13 17:49:53 eric Exp $ + +TOTAL=0 +FAIL=0 +OK=0 + +EXT0=.std +EXT1=.asr +EFLAG=-ee + +set -e + +fail() +{ + echo "*** ERROR: $@" + exit 1 +} + +regress() +{ + local out; + local _cmd=$1; + local _bin0=/bin/$_cmd$EXT0 + local _bin1=/bin/$_cmd$EXT1 + shift; + + TOTAL=$((TOTAL+1)) + + # XXX with user "bin" + test -x $_RUNDIR$_bin0 || fail $_RUNDIR$_bin0 not executable + test -x $_RUNDIR$_bin1 || fail $_RUNDIR$_bin1 not executable + + out=/tmp/asr_regress + + echo -n $_cmd $EFLAG $@ "." + + set +e + chroot -u bin "$_RUNDIR" $_bin0 $EFLAG $@ > $out.0 + echo -n . + chroot -u bin "$_RUNDIR" $_bin1 $EFLAG $@ > $out.1 + echo -n ". " + + diff -u $out.0 $out.1 > $out.diff + set -e + if test -s $out.diff; then + FAIL=$((FAIL+1)) + echo fail + echo "*** FAIL (env=$REGRESSENV)" $_cmd $EFLAG $@ >> $REG + tail -n +3 $out.diff >> $REG + echo >> $REG + else + OK=$((OK+1)) + echo ok + echo "OK (env=$REGRESSENV)" $_cmd $EFLAG $@ >> $OUT + cat $out.0 >> $OUT + echo >> $OUT + fi + rm $out.diff $out.0 $out.1 +} + +regress_setenv() +{ + local _name="$1" + + echo "===> using env $_name" + + cp /etc/hosts $_RUNDIR/etc/ + cp /etc/resolv.conf $_RUNDIR/etc/ + cp /etc/protocols $_RUNDIR/etc/ + cp /etc/networks $_RUNDIR/etc/ + + case $_name in + empty) + rm -f $_RUNDIR/etc/* + ;; + local) + ;; + file) + grep -v lookup /etc/resolv.conf > $_RUNDIR/etc/resolv.conf + echo "lookup file" >> $_RUNDIR/etc/resolv.conf + ;; + bind) + grep -v lookup /etc/resolv.conf > $_RUNDIR/etc/resolv.conf + echo "lookup bind" >> $_RUNDIR/etc/resolv.conf + ;; + *) + fail unknown env $_name + ;; + esac + REGRESSENV=$_name +} + +regress_digest() +{ + echo + cat $REG + echo "===>" run=$TOTAL fail=$FAIL +} + + +# needed for chroot +test "$(id -u)" -ne 0 && fail need root privileges to run this script + +# we really really want to avoid erasing /etc later +test "$RUNDIR" || fail RUNDIR is not set +_RUNDIR=$(readlink -fn ${RUNDIR}) +test "$_RUNDIR" == / && fail RUNDIR is root dir: $RUNDIR + +OUT=$_RUNDIR/output.log +REG=$_RUNDIR/regress.log + +echo -n > $REG +echo -n > $OUT -- cgit v1.2.3-55-g6feb