Commit 6a5a36f0 authored by Charles Longeau's avatar Charles Longeau Committed by Eric Faurot

split asr from smtpd sources

Conflicts:
	contrib/lib/libc/asr/CVS/Entries
	contrib/lib/libc/asr/asr.c
	contrib/lib/libc/asr/asr_debug.c
	contrib/lib/libc/asr/asr_private.h
	contrib/lib/libc/asr/asr_utils.c
	contrib/lib/libc/asr/getaddrinfo.c
	contrib/lib/libc/asr/getaddrinfo_async.c
	contrib/lib/libc/asr/gethostnamadr.c
	contrib/lib/libc/asr/gethostnamadr_async.c
	contrib/lib/libc/asr/getnameinfo.c
	contrib/lib/libc/asr/getnameinfo_async.c
	contrib/lib/libc/asr/getnetnamadr.c
	contrib/lib/libc/asr/getnetnamadr_async.c
	contrib/lib/libc/asr/getrrsetbyname.c
	contrib/lib/libc/asr/getrrsetbyname_async.c
	contrib/lib/libc/asr/res_init.c
	contrib/lib/libc/asr/res_mkquery.c
	contrib/lib/libc/asr/res_query.c
	contrib/lib/libc/asr/res_search_async.c
	contrib/lib/libc/asr/res_send.c
	contrib/lib/libc/asr/res_send_async.c
	mk/smtpd/Makefile.am
parent b85b0bc6
...@@ -6,9 +6,8 @@ are under a BSD licence, or a licence more free than that. ...@@ -6,9 +6,8 @@ are under a BSD licence, or a licence more free than that.
OpenSMTPD contains no GPL code. OpenSMTPD contains no GPL code.
Portable OpenSMTPD is divided in 5 parts: Portable OpenSMTPD is divided in 4 parts:
- Original OpenSMTPD - Original OpenSMTPD
- asr
- mail.local - mail.local
- openbsd-compat - openbsd-compat
- smtpctl encrypt sub command - smtpctl encrypt sub command
...@@ -107,47 +106,6 @@ OpenSMTPD ...@@ -107,47 +106,6 @@ OpenSMTPD
asr
===
1) Almost all code is licensed under an ISC-style license, to the following
copyright holders:
Eric Faurot
Internet Software Consortium
2) last part of getrrsetbyname_async.c is covered by 2-clause BSD license
/*
* Copyright (c) 2001 Jakob Schlyter. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
mail.local mail.local
========== ==========
......
D/csu////
D/i18n_module////
D/libaltq////
D/libarch////
D/libasn1////
D/libc////
/Makefile/-1.59/dummy timestamp//
anoncvs@anoncvs.spacehopper.org:/cvs
SUBDIRS = libc
\ No newline at end of file
D/arch////
D/asr////
D/citrus////
D/compat-43////
D/crypt////
D/db////
D/dlfcn////
D/gdtoa////
D/gen////
D/gmon////
D/hash////
D/iconv////
D/include////
D/locale////
D/md////
D/net////
D/nls////
D/ohash////
D/posix1e////
D/quad////
D/regex////
D/rpc////
D/softfloat////
D/stdio////
D/stdlib////
D/string////
D/sys////
/Makefile/-1.29/dummy timestamp//
/Makefile.inc/-1.17/dummy timestamp//
/shlib_version/-1.144/dummy timestamp//
anoncvs@anoncvs.spacehopper.org:/cvs
SUBDIRS = asr
\ No newline at end of file
/asr.c/1.31/Result of merge//
/asr.h/1.7/Result of merge//
/asr_debug.c/1.14/Result of merge//
/getaddrinfo_async.c/1.19/Result of merge//
/getnameinfo_async.c/1.7/Result of merge//
/getnetnamadr_async.c/1.10/Result of merge//
/getrrsetbyname_async.c/1.5/Result of merge//
/res_search_async.c/1.10/Result of merge//
/res_send_async.c/1.19/Result of merge//
/Makefile.inc/1.6/Sat Sep 28 15:48:04 2013//
/asr_resolver.3/1.1/Thu Aug 8 06:55:42 2013//
/asr_private.h/1.23/Mon Nov 25 20:11:46 2013//
/asr_utils.c/1.9/Result of merge//
/getaddrinfo.c/1.3/Mon Nov 25 20:11:46 2013//
/gethostnamadr.c/1.9/Mon Nov 25 20:11:46 2013//
/gethostnamadr_async.c/1.23/Result of merge//
/getnameinfo.c/1.3/Mon Nov 25 20:11:46 2013//
/getnetnamadr.c/1.6/Mon Nov 25 20:11:46 2013//
/getrrsetbyname.c/1.3/Mon Nov 25 20:11:46 2013//
/res_debug.c/1.1/Mon Nov 25 20:11:46 2013//
/res_init.c/1.2/Mon Nov 25 20:11:46 2013//
/res_mkquery.c/1.6/Mon Nov 25 20:11:46 2013//
/res_query.c/1.6/Mon Nov 25 20:11:46 2013//
/res_send.c/1.6/Mon Nov 25 20:11:46 2013//
/sethostent.c/1.1/Mon Nov 25 20:11:46 2013//
D
anoncvs@anoncvs.spacehopper.org:/cvs
This diff is collapsed.
/* $OpenBSD: asr.h,v 1.7 2013/07/12 14:36:21 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 <netdb.h>
#include <netinet/in.h>
/*
* This part is the generic API for the async mechanism. It could be useful
* beyond the resolver.
*/
/* Return values for async_run() */
#define ASYNC_COND 0 /* wait for fd condition */
#define ASYNC_YIELD 1 /* partial result */
#define ASYNC_DONE 2 /* done */
/* Expected fd conditions */
#define ASYNC_READ 1
#define ASYNC_WRITE 2
/* This opaque structure holds an async query state. */
struct async;
/*
* This is the structure through which async_run() returns async
* results to the caller.
*/
struct async_res {
int ar_cond;
int ar_fd;
int ar_timeout;
int ar_errno;
int ar_h_errno;
int ar_gai_errno;
int ar_rrset_errno;
int ar_count;
int ar_rcode;
void *ar_data;
int ar_datalen;
union {
struct sockaddr sa;
struct sockaddr_in sain;
struct sockaddr_in6 sain6;
} ar_sa;
struct addrinfo *ar_addrinfo;
struct rrsetinfo *ar_rrsetinfo;
struct hostent *ar_hostent;
struct netent *ar_netent;
};
int asr_async_run(struct async *, struct async_res *);
int asr_async_run_sync(struct async *, struct async_res *);
void asr_async_abort(struct async *);
/* This opaque structure holds an async resolver context. */
struct asr;
struct asr *asr_resolver(const char *);
void asr_resolver_done(struct asr *);
/* Async version of the resolver API */
struct async *res_send_async(const unsigned char *, int, struct asr *);
struct async *res_query_async(const char *, int, int, struct asr *);
struct async *res_search_async(const char *, int, int, struct asr *);
struct async *getrrsetbyname_async(const char *, unsigned int, unsigned int,
unsigned int, struct asr *);
struct async *gethostbyname_async(const char *, struct asr *);
struct async *gethostbyname2_async(const char *, int, struct asr *);
struct async *gethostbyaddr_async(const void *, socklen_t, int, struct asr *);
struct async *getnetbyname_async(const char *, struct asr *);
struct async *getnetbyaddr_async(in_addr_t, int, struct asr *);
struct async *getaddrinfo_async(const char *, const char *,
const struct addrinfo *, struct asr *);
struct async *getnameinfo_async(const struct sockaddr *, socklen_t, char *,
size_t, char *, size_t, int, struct asr *);
void asr_freeaddrinfo(struct addrinfo *);
/* $OpenBSD: asr_debug.c,v 1.14 2013/07/12 14:36:21 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 "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#include "asr.h"
#include "asr_private.h"
static const char *rcodetostr(uint16_t);
static const char *print_dname(const char *, char *, size_t);
static const char *print_header(const struct header *, char *, size_t);
static const char *print_query(const struct query *, char *, size_t);
static const char *print_rr(const struct rr *, char *, size_t);
FILE *asr_debug = NULL;
#define OPCODE_SHIFT 11
#define Z_SHIFT 4
static const char *
rcodetostr(uint16_t v)
{
switch (v) {
case NOERROR: return "NOERROR";
case FORMERR: return "FORMERR";
case SERVFAIL: return "SERVFAIL";
case NXDOMAIN: return "NXDOMAIN";
case NOTIMP: return "NOTIMP";
case REFUSED: return "REFUSED";
default: return "?";
}
}
static const char *
print_dname(const char *_dname, char *buf, size_t max)
{
return (asr_strdname(_dname, buf, max));
}
static const char *
print_rr(const 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,
__p_class(rr->rr_class),
__p_type(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, "%lu %s",
(unsigned long)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 %lu %lu %lu %lu %lu",
print_dname(rr->rr.soa.rname, tmp, sizeof tmp),
print_dname(rr->rr.soa.mname, tmp2, sizeof tmp2),
(unsigned long)rr->rr.soa.serial,
(unsigned long)rr->rr.soa.refresh,
(unsigned long)rr->rr.soa.retry,
(unsigned long)rr->rr.soa.expire,
(unsigned long)rr->rr.soa.minimum);
break;
case T_A:
if (rr->rr_class != C_IN)
goto other;
snprintf(buf, max, "%s", inet_ntop(AF_INET,
&rr->rr.in_a.addr, tmp, sizeof tmp));
break;
case T_AAAA:
if (rr->rr_class != C_IN)
goto other;
snprintf(buf, max, "%s", inet_ntop(AF_INET6,
&rr->rr.in_aaaa.addr6, tmp, sizeof tmp));
break;
default:
other:
snprintf(buf, max, "(rdlen=%i)", (int)rr->rr.other.rdlen);
break;
}
return (res);
}
static const char *
print_query(const 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),
__p_class(q->q_class), __p_type(q->q_type));
return (buf);
}
static const char *
print_header(const struct header *h, char *buf, size_t max)
{
snprintf(buf, max,
"id:0x%04x %s op:%i %s %s %s %s z:%i r:%s qd:%i an:%i ns:%i ar:%i",
((int)h->id),
(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);
}
void
asr_dump_packet(FILE *f, const void *data, size_t len)
{
char buf[1024];
struct unpack p;
struct header h;
struct query q;
struct rr rr;
int i, an, ns, ar, n;
if (f == NULL)
return;
asr_unpack_init(&p, data, len);
if (asr_unpack_header(&p, &h) == -1) {
fprintf(f, ";; BAD PACKET: %s\n", p.err);
return;
}
fprintf(f, ";; HEADER %s\n", print_header(&h, buf, sizeof buf));
if (h.qdcount)
fprintf(f, ";; QUERY SECTION:\n");
for (i = 0; i < h.qdcount; i++) {
if (asr_unpack_query(&p, &q) == -1)
goto error;
fprintf(f, "%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)
fprintf(f, "\n;; ANSWER SECTION:\n");
if (i == ns)
fprintf(f, "\n;; AUTHORITY SECTION:\n");
if (i == ar)
fprintf(f, "\n;; ADDITIONAL SECTION:\n");
if (asr_unpack_rr(&p, &rr) == -1)
goto error;
fprintf(f, "%s\n", print_rr(&rr, buf, sizeof buf));
}
if (p.offset != len)
fprintf(f, ";; REMAINING GARBAGE %zu\n", len - p.offset);
error:
if (p.err)
fprintf(f, ";; ERROR AT OFFSET %zu/%zu: %s\n", p.offset, p.len,
p.err);
}
const char *
print_sockaddr(const struct sockaddr *sa, char *buf, size_t len)
{
char h[256];
int portno;
union {
const struct sockaddr *sa;
const struct sockaddr_in *sin;
const struct sockaddr_in6 *sin6;
} s;
s.sa = sa;
switch (sa->sa_family) {
case AF_INET:
inet_ntop(AF_INET, &s.sin->sin_addr, h, sizeof h);
portno = ntohs(s.sin->sin_port);
break;
case AF_INET6:
inet_ntop(AF_INET6, &s.sin6->sin6_addr, h, sizeof h);
portno = ntohs(s.sin6->sin6_port);
break;
default:
snprintf(buf, len, "?");
return (buf);
}
snprintf(buf, len, "%s:%i", h, portno);
return (buf);
}
void
asr_dump_config(FILE *f, struct asr *a)
{
char buf[256];
int i;
struct asr_ctx *ac;
unsigned int o;
if (f == NULL)
return;
ac = a->a_ctx;
fprintf(f, "--------- ASR CONFIG ---------------\n");
if (a->a_path)
fprintf(f, "CONF FILE \"%s\"\n", a->a_path);
else
fprintf(f, "STATIC CONF\n");
fprintf(f, "DOMAIN \"%s\"\n", ac->ac_domain);
fprintf(f, "SEARCH\n");
for (i = 0; i < ac->ac_domcount; i++)
fprintf(f, " \"%s\"\n", ac->ac_dom[i]);
fprintf(f, "OPTIONS\n");
fprintf(f, " options:");
o = ac->ac_options;
#define PRINTOPT(flag, n) if (o & (flag)) { fprintf(f, " " n); o &= ~(flag); }
PRINTOPT(RES_INIT, "INIT");
PRINTOPT(RES_DEBUG, "DEBUG");
PRINTOPT(RES_USEVC, "USEVC");
PRINTOPT(RES_IGNTC, "IGNTC");
PRINTOPT(RES_RECURSE, "RECURSE");
PRINTOPT(RES_DEFNAMES, "DEFNAMES");
PRINTOPT(RES_STAYOPEN, "STAYOPEN");
PRINTOPT(RES_DNSRCH, "DNSRCH");
PRINTOPT(RES_NOALIASES, "NOALIASES");
PRINTOPT(RES_USE_EDNS0, "USE_EDNS0");
PRINTOPT(RES_USE_DNSSEC, "USE_DNSSEC");
if (o)
fprintf(f, " 0x%08x", o);
fprintf(f, "\n");
fprintf(f, " ndots: %i\n", ac->ac_ndots);
fprintf(f, " family:");
for (i = 0; ac->ac_family[i] != -1; i++)
fprintf(f, " %s", (ac->ac_family[i] == AF_INET)?"inet4":"inet6");
fprintf(f, "\n");
fprintf(f, "NAMESERVERS timeout=%i retry=%i\n",
ac->ac_nstimeout,
ac->ac_nsretries);
for (i = 0; i < ac->ac_nscount; i++)
fprintf(f, " %s\n", print_sockaddr(ac->ac_ns[i], buf,
sizeof buf));
fprintf(f, "HOSTFILE %s\n", ac->ac_hostfile);
fprintf(f, "LOOKUP %s", ac->ac_db);
fprintf(f, "\n------------------------------------\n");
}
#define CASE(n) case n: return #n
const char *
asr_statestr(int state)
{
switch (state) {
CASE(ASR_STATE_INIT);
CASE(ASR_STATE_NEXT_DOMAIN);
CASE(ASR_STATE_NEXT_DB);
CASE(ASR_STATE_SAME_DB);
CASE(ASR_STATE_NEXT_FAMILY);
CASE(ASR_STATE_NEXT_NS);
CASE(ASR_STATE_UDP_SEND);
CASE(ASR_STATE_UDP_RECV);
CASE(ASR_STATE_TCP_WRITE);
CASE(ASR_STATE_TCP_READ);
CASE(ASR_STATE_PACKET);
CASE(ASR_STATE_SUBQUERY);
CASE(ASR_STATE_NOT_FOUND);
CASE(ASR_STATE_HALT);
default:
return "?";
}
};
const char *
asr_querystr(int type)
{
switch (type) {
CASE(ASR_SEND);
CASE(ASR_SEARCH);
CASE(ASR_GETRRSETBYNAME);
CASE(ASR_GETHOSTBYNAME);
CASE(ASR_GETHOSTBYADDR);
CASE(ASR_GETNETBYNAME);
CASE(ASR_GETNETBYADDR);
CASE(ASR_GETADDRINFO);
CASE(ASR_GETNAMEINFO);
default:
return "?";
}
}
const char *
asr_transitionstr(int type)
{
switch (type) {
CASE(ASYNC_COND);
CASE(ASYNC_YIELD);
CASE(ASYNC_DONE);
default:
return "?";
}
}
/* $OpenBSD: asr_private.h,v 1.23 2013/07/12 14:36:21 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 <stdio.h>
#ifndef ASRNODEBUG
#define DEBUG
#endif
#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 pack {
char *buf;
size_t len;
size_t offset;
const char *err;
};
struct unpack {
const char *buf;
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;
};
#define ASR_MAXNS 5
#define ASR_MAXDB 3
#define ASR_MAXDOM 10