summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreric <eric@openbsd.org>2012-07-13 17:49:53 +0000
committereric <eric@openbsd.org>2012-07-13 17:49:53 +0000
commit4c1e55dc91edd6e69ccc60ce855900fbc12cf34f (patch)
treec8a893bd405af08b5f73b5eeb9ec99045bfcd1e4
parentCleanup the knexthop mess and make sure we only send an update to the RDE (diff)
downloadwireguard-openbsd-4c1e55dc91edd6e69ccc60ce855900fbc12cf34f.tar.xz
wireguard-openbsd-4c1e55dc91edd6e69ccc60ce855900fbc12cf34f.zip
import regression suite for asr
-rw-r--r--regress/lib/libc/asr/Makefile52
-rw-r--r--regress/lib/libc/asr/bin/Makefile10
-rw-r--r--regress/lib/libc/asr/bin/Makefile.inc8
-rw-r--r--regress/lib/libc/asr/bin/common.c633
-rw-r--r--regress/lib/libc/asr/bin/common.h136
-rw-r--r--regress/lib/libc/asr/bin/getaddrinfo.c131
-rw-r--r--regress/lib/libc/asr/bin/getaddrinfo/Makefile8
-rw-r--r--regress/lib/libc/asr/bin/gethostnamadr.c112
-rw-r--r--regress/lib/libc/asr/bin/gethostnamadr/Makefile8
-rw-r--r--regress/lib/libc/asr/bin/getnameinfo.c112
-rw-r--r--regress/lib/libc/asr/bin/getnameinfo/Makefile8
-rw-r--r--regress/lib/libc/asr/bin/getnetnamadr.c85
-rw-r--r--regress/lib/libc/asr/bin/getnetnamadr/Makefile8
-rw-r--r--regress/lib/libc/asr/bin/getrrsetbyname.c88
-rw-r--r--regress/lib/libc/asr/bin/getrrsetbyname/Makefile8
-rw-r--r--regress/lib/libc/asr/bin/res_mkquery.c319
-rw-r--r--regress/lib/libc/asr/bin/res_mkquery/Makefile8
-rw-r--r--regress/lib/libc/asr/bin/res_query.c354
-rw-r--r--regress/lib/libc/asr/bin/res_query/Makefile8
-rw-r--r--regress/lib/libc/asr/bin/threads.c140
-rw-r--r--regress/lib/libc/asr/bin/threads/Makefile10
-rw-r--r--regress/lib/libc/asr/regress.sh104
-rw-r--r--regress/lib/libc/asr/regress.subr114
23 files changed, 2464 insertions, 0 deletions
diff --git a/regress/lib/libc/asr/Makefile b/regress/lib/libc/asr/Makefile
new file mode 100644
index 00000000000..f110cbe25ea
--- /dev/null
+++ b/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/regress/lib/libc/asr/bin/Makefile b/regress/lib/libc/asr/bin/Makefile
new file mode 100644
index 00000000000..1f986a8e697
--- /dev/null
+++ b/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 <bsd.subdir.mk>
diff --git a/regress/lib/libc/asr/bin/Makefile.inc b/regress/lib/libc/asr/bin/Makefile.inc
new file mode 100644
index 00000000000..9a03163906d
--- /dev/null
+++ b/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/regress/lib/libc/asr/bin/common.c b/regress/lib/libc/asr/bin/common.c
new file mode 100644
index 00000000000..4402d083738
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+#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/regress/lib/libc/asr/bin/common.h b/regress/lib/libc/asr/bin/common.h
new file mode 100644
index 00000000000..87df4ae4a28
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/nameser.h>
+
+#include <netinet/in.h>
+
+#include <netdb.h>
+
+
+#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/regress/lib/libc/asr/bin/getaddrinfo.c b/regress/lib/libc/asr/bin/getaddrinfo.c
new file mode 100644
index 00000000000..8c4abf361e1
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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] <host...>\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/regress/lib/libc/asr/bin/getaddrinfo/Makefile b/regress/lib/libc/asr/bin/getaddrinfo/Makefile
new file mode 100644
index 00000000000..ec2f104ec75
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/bin/gethostnamadr.c b/regress/lib/libc/asr/bin/gethostnamadr.c
new file mode 100644
index 00000000000..336c6b9db37
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+static void
+usage(void)
+{
+ extern const char * __progname;
+
+ fprintf(stderr, "usage: %s [-46e] <host...>\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/regress/lib/libc/asr/bin/gethostnamadr/Makefile b/regress/lib/libc/asr/bin/gethostnamadr/Makefile
new file mode 100644
index 00000000000..84906ffbbd1
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/bin/getnameinfo.c b/regress/lib/libc/asr/bin/getnameinfo.c
new file mode 100644
index 00000000000..8702937a47c
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+
+static void
+usage(void)
+{
+ extern const char * __progname;
+
+ fprintf(stderr, "usage: %s [-DFHNSe] [-p portno] <addr...>\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/regress/lib/libc/asr/bin/getnameinfo/Makefile b/regress/lib/libc/asr/bin/getnameinfo/Makefile
new file mode 100644
index 00000000000..4927ee94860
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/bin/getnetnamadr.c b/regress/lib/libc/asr/bin/getnetnamadr.c
new file mode 100644
index 00000000000..4b7414264bd
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/regress/lib/libc/asr/bin/getnetnamadr/Makefile b/regress/lib/libc/asr/bin/getnetnamadr/Makefile
new file mode 100644
index 00000000000..521bf8eb7e5
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/bin/getrrsetbyname.c b/regress/lib/libc/asr/bin/getrrsetbyname.c
new file mode 100644
index 00000000000..4a5aa572093
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/regress/lib/libc/asr/bin/getrrsetbyname/Makefile b/regress/lib/libc/asr/bin/getrrsetbyname/Makefile
new file mode 100644
index 00000000000..131403bea12
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/bin/res_mkquery.c b/regress/lib/libc/asr/bin/res_mkquery.c
new file mode 100644
index 00000000000..a52023c5c04
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/regress/lib/libc/asr/bin/res_mkquery/Makefile b/regress/lib/libc/asr/bin/res_mkquery/Makefile
new file mode 100644
index 00000000000..770fa9f633a
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/bin/res_query.c b/regress/lib/libc/asr/bin/res_query.c
new file mode 100644
index 00000000000..fd96f1de224
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/regress/lib/libc/asr/bin/res_query/Makefile b/regress/lib/libc/asr/bin/res_query/Makefile
new file mode 100644
index 00000000000..75380ee079c
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/bin/threads.c b/regress/lib/libc/asr/bin/threads.c
new file mode 100644
index 00000000000..f296f1d6f7d
--- /dev/null
+++ b/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 <eric@openbsd.org>
+ *
+ * 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 <sys/time.h>
+#include <sys/resource.h>
+
+#include <assert.h>
+#include <err.h>
+#include <getopt.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <netdb.h>
+
+#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] <host> ...\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/regress/lib/libc/asr/bin/threads/Makefile b/regress/lib/libc/asr/bin/threads/Makefile
new file mode 100644
index 00000000000..3252511cd10
--- /dev/null
+++ b/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 <bsd.prog.mk>
diff --git a/regress/lib/libc/asr/regress.sh b/regress/lib/libc/asr/regress.sh
new file mode 100644
index 00000000000..b4d1c1db594
--- /dev/null
+++ b/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/regress/lib/libc/asr/regress.subr b/regress/lib/libc/asr/regress.subr
new file mode 100644
index 00000000000..dafb7ddf758
--- /dev/null
+++ b/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