#include "internal.h"
/*
- * IPv4
+ * General address-family operations.
*/
#define SIN(sa) ((struct sockaddr_in *)(sa))
#define CSIN(sa) ((const struct sockaddr_in *)(sa))
-static const void *inet_sockaddr_to_inaddr(const struct sockaddr *sa)
- { return &CSIN(sa)->sin_addr; }
+#define SIN6(sa) ((struct sockaddr_in6 *)(sa))
+#define CSIN6(sa) ((const struct sockaddr_in6 *)(sa))
+
+/* This gadget (thanks, Richard Kettlewell) makes sure that we handle the
+ * same set of address families in each switch. */
+#define AF_CASES(pre) \
+ case AF_INET: goto pre##_inet; \
+ case AF_INET6: goto pre##_inet6
+
+static void unknown_af(int af) {
+ fprintf(stderr, "ADNS INTERNAL: unknown address family %d\n", af);
+ abort();
+}
-static int inet_sockaddr_equalp(const struct sockaddr *sa,
- const struct sockaddr *sb)
+int adns__af_supported_p(int af)
{
- const struct sockaddr_in *sina = CSIN(sa), *sinb = CSIN(sb);
- return (sina->sin_addr.s_addr == sinb->sin_addr.s_addr &&
- sina->sin_port == sinb->sin_port);
+ switch (af) {
+ AF_CASES(af);
+ af_inet: af_inet6: return 1;
+ default: return 0;
+ }
}
-static void inet_prefix_mask(int len, union gen_addr *mask)
- { mask->v4.s_addr = htonl(!len ? 0 : 0xffffffff << (32 - len)); }
+int adns__sockaddr_equal_p(const struct sockaddr *sa,
+ const struct sockaddr *sb)
+{
+ if (sa->sa_family != sb->sa_family) return 0;
+ switch (sa->sa_family) {
+ AF_CASES(af);
+ af_inet: {
+ const struct sockaddr_in *sina = CSIN(sa), *sinb = CSIN(sb);
+ return (sina->sin_addr.s_addr == sinb->sin_addr.s_addr &&
+ sina->sin_port == sinb->sin_port);
+ }
+ af_inet6: {
+ /* Don't check the flowlabel. That's apparently useful for routing
+ * performance, but doesn't affect the address in any important
+ * respect.
+ */
+ const struct sockaddr_in6 *sin6a = CSIN6(sa), *sin6b = CSIN6(sb);
+ return (memcmp(sin6a->sin6_addr.s6_addr,
+ sin6b->sin6_addr.s6_addr,
+ sizeof(sin6a->sin6_addr.s6_addr)) == 0 &&
+ sin6a->sin6_port == sin6b->sin6_port &&
+ sin6a->sin6_scope_id == sin6b->sin6_scope_id);
+ }
+ default:
+ unknown_af(sa->sa_family);
+ return -1;
+ }
+}
-static int inet_guess_len(const union gen_addr *addr)
+int adns__gen_pton(const char *p, int *af_r, union gen_addr *addr_r)
{
- unsigned a = (ntohl(addr->v4.s_addr) >> 24) & 0xff;
+ static const int aflist[] = { AF_INET6, AF_INET };
+ int i, rc;
- if (a < 128) return 8;
- else if (a < 192) return 16;
- else if (a < 224) return 24;
- else return -1;
+ for (i = 0; i < sizeof(aflist)/sizeof(*aflist); i++) {
+ rc = inet_pton(aflist[i], p, addr_r);
+ assert(rc >= 0);
+ if (rc) { *af_r = aflist[i]; return 1; }
+ }
+ return 0;
}
-static int inet_matchp(const union gen_addr *addr,
- const union gen_addr *base,
- const union gen_addr *mask)
- { return (addr->v4.s_addr & mask->v4.s_addr) == base->v4.s_addr; }
-
-static int inet_rev_parsecomp(const char *p, size_t n)
+int adns__addr_width(int af)
{
- int i = 0;
- if (n > 3) return -1;
-
- while (n--) {
- if ('0' <= *p && *p <= '9') i = 10*i + *p++ - '0';
- else return -1;
+ switch (af) {
+ AF_CASES(af);
+ af_inet: return 32;
+ af_inet6: return 128;
+ default: unknown_af(af); return -1;
}
- return i;
}
-static void inet_rev_mkaddr(union gen_addr *addr, const byte *ipv)
+void adns__prefix_mask(int af, int len, union gen_addr *mask_r)
{
- addr->v4.s_addr = htonl((ipv[3]<<24) | (ipv[2]<<16) |
- (ipv[1]<<8) | (ipv[0]));
+ switch (af) {
+ AF_CASES(af);
+ af_inet:
+ assert(len <= 32);
+ mask_r->v4.s_addr = htonl(!len ? 0 : 0xffffffff << (32 - len));
+ break;
+ af_inet6: {
+ int i = len/8, j = len%8;
+ unsigned char *m = mask_r->v6.s6_addr;
+
+ assert(len <= 128);
+ memset(m, 0xff, i);
+ if (j) m[i++] = (0xff << (8-j)) & 0xff;
+ memset(m+i, 0, 16-i);
+ } break;
+ default:
+ unknown_af(af);
+ break;
+ }
}
-static char *inet_rev_mkname(const struct sockaddr *sa, char *buf)
+int adns__guess_prefix_length(int af, const union gen_addr *addr)
{
- unsigned long a = ntohl(CSIN(sa)->sin_addr.s_addr);
- int i;
+ switch (af) {
+ AF_CASES(af);
+ af_inet: {
+ unsigned a = (ntohl(addr->v4.s_addr) >> 24) & 0xff;
+
+ if (a < 128) return 8;
+ else if (a < 192) return 16;
+ else if (a < 224) return 24;
+ else return -1;
+ } break;
+ af_inet6:
+ return 64;
+ default:
+ unknown_af(af);
+ return -1;
+ }
+}
- for (i = 0; i < 4; i++) {
- if (i) *buf++ = '.';
- buf += sprintf(buf, "%d", (int)(a & 0xff));
- a >>= 8;
+int adns__addr_match_p(int addraf, const union gen_addr *addr,
+ int netaf, const union gen_addr *base,
+ const union gen_addr *mask)
+{
+ if (addraf != netaf) return 0;
+ switch (addraf) {
+ AF_CASES(af);
+ af_inet:
+ return (addr->v4.s_addr & mask->v4.s_addr) == base->v4.s_addr;
+ af_inet6: {
+ int i;
+ const char *a = addr->v6.s6_addr;
+ const char *b = base->v6.s6_addr;
+ const char *m = mask->v6.s6_addr;
+
+ for (i = 0; i < 16; i++)
+ if ((a[i] & m[i]) != b[i]) return 0;
+ return 1;
+ } break;
+ default:
+ unknown_af(addraf);
+ return -1;
}
- return buf;
}
-const afinfo adns__inet_afinfo = {
- AF_INET, 32, '.', 4, 3, adns_r_a,
- inet_sockaddr_to_inaddr, inet_sockaddr_equalp,
- inet_prefix_mask, inet_guess_len, inet_matchp,
- inet_rev_parsecomp, inet_rev_mkaddr, inet_rev_mkname
-};
+const void *adns__sockaddr_to_inaddr(const struct sockaddr *sa)
+{
+ switch (sa->sa_family) {
+ AF_CASES(af);
+ af_inet: return &CSIN(sa)->sin_addr;
+ af_inet6: return &CSIN6(sa)->sin6_addr;
+ default: unknown_af(sa->sa_family); return 0;
+ }
+}
/*
- * IPv6
+ * Reverse-domain parsing and construction.
*/
-#define SIN6(sa) ((struct sockaddr_in6 *)(sa))
-#define CSIN6(sa) ((const struct sockaddr_in6 *)(sa))
+int adns__make_reverse_domain(const struct sockaddr *sa,
+ const char *zone,
+ char **buf_io, size_t bufsz,
+ char **buf_free_r)
+{
+ size_t req;
+ char *p;
+ unsigned c, y;
+ unsigned long aa;
+ const unsigned char *ap;
+ int i, j;
-static const void *inet6_sockaddr_to_inaddr(const struct sockaddr *sa)
- { return &CSIN6(sa)->sin6_addr; }
+ switch (sa->sa_family) {
+ AF_CASES(af);
+ af_inet:
+ req = 4 * 4;
+ if (!zone) zone = "in-addr.arpa";
+ break;
+ af_inet6:
+ req = 2 * 32;
+ if (!zone) zone = "ip6.arpa";
+ break;
+ default:
+ return ENOSYS;
+ }
-static int inet6_sockaddr_equalp(const struct sockaddr *sa,
- const struct sockaddr *sb)
-{
- const struct sockaddr_in6 *sin6a = CSIN6(sa), *sin6b = CSIN6(sb);
- return (memcmp(sin6a->sin6_addr.s6_addr,
- sin6b->sin6_addr.s6_addr,
- sizeof(sin6a->sin6_addr.s6_addr)) == 0 &&
- sin6a->sin6_port == sin6b->sin6_port &&
- sin6a->sin6_scope_id == sin6b->sin6_scope_id);
-}
+ req += strlen(zone) + 1;
+ if (req <= bufsz)
+ p = *buf_io;
+ else {
+ p = malloc(req); if (!p) return errno;
+ *buf_free_r = p;
+ }
-static void inet6_prefix_mask(int len, union gen_addr *mask)
-{
- int i = len/8, j = len%8;
- unsigned char *m = mask->v6.s6_addr;
+ *buf_io = p;
+ switch (sa->sa_family) {
+ AF_CASES(bf);
+ bf_inet:
+ aa = ntohl(CSIN(sa)->sin_addr.s_addr);
+ for (i = 0; i < 4; i++) {
+ p += sprintf(p, "%d", (int)(aa & 0xff));
+ *p++ = '.';
+ aa >>= 8;
+ }
+ break;
+ bf_inet6:
+ ap = CSIN6(sa)->sin6_addr.s6_addr + 16;
+ for (i = 0; i < 16; i++) {
+ c = *--ap;
+ for (j = 0; j < 2; j++) {
+ y = c & 0xf;
+ if (y < 10) *p++ = y + '0';
+ else *p++ = y - 10 + 'a';
+ c >>= 4;
+ *p++ = '.';
+ }
+ }
+ break;
+ default:
+ unknown_af(sa->sa_family);
+ }
- assert(len < 128);
- memset(m, 0xff, i);
- if (j) m[i++] = (0xff << (8-j)) & 0xff;
- memset(m + i, 0, 16-i);
+ strcpy(p, zone);
+ return 0;
}
-static int inet6_guess_len(const union gen_addr *addr)
- { return 64; }
-static int inet6_matchp(const union gen_addr *addr,
- const union gen_addr *base,
- const union gen_addr *mask)
+static int inet_rev_parsecomp(const char *p, size_t n)
{
- int i;
- const char *a = addr->v6.s6_addr;
- const char *b = base->v6.s6_addr;
- const char *m = mask->v6.s6_addr;
+ int i = 0;
+ if (n > 3) return -1;
- for (i = 0; i < 16; i++)
- if ((a[i] & m[i]) != b[i]) return 0;
- return 1;
+ while (n--) {
+ if ('0' <= *p && *p <= '9') i = 10*i + *p++ - '0';
+ else return -1;
+ }
+ return i;
+}
+
+static void inet_rev_mkaddr(union gen_addr *addr, const byte *ipv)
+{
+ addr->v4.s_addr = htonl((ipv[3]<<24) | (ipv[2]<<16) |
+ (ipv[1]<<8) | (ipv[0]));
}
static int inet6_rev_parsecomp(const char *p, size_t n)
a[i] = (ipv[31-2*i] << 4) | (ipv[30-2*i] << 0);
}
-static char *inet6_rev_mkname(const struct sockaddr *sa, char *buf)
-{
- const unsigned char *a = CSIN6(sa)->sin6_addr.s6_addr + 16;
- unsigned c, y;
- int i, j;
+static const struct revparse_domain {
+ int af; /* address family */
+ int nrevlab; /* n of reverse-address labels */
+ adns_rrtype rrtype; /* forward-lookup type */
+
+ int (*rev_parsecomp)(const char *p, size_t n);
+ /* parse a single component from a label; return the integer value, or -1
+ * if it was unintelligible.
+ */
+
+ void (*rev_mkaddr)(union gen_addr *addr, const byte *ipv);
+ /* write out the parsed address from a vector of parsed components */
+
+ const char *const tail[3]; /* tail label names */
+} revparse_domains[NREVDOMAINS] = {
+ { AF_INET, 4, adns_r_a, inet_rev_parsecomp, inet_rev_mkaddr,
+ { DNS_INADDR_ARPA, 0 } },
+ { AF_INET6, 32, adns_r_aaaa, inet6_rev_parsecomp, inet6_rev_mkaddr,
+ { DNS_IP6_ARPA, 0 } },
+};
- for (i = 0; i < 16; i++) {
- c = *--a;
- for (j = 0; j < 2; j++) {
- if (i || j) *buf++ = '.';
- y = c & 0xf;
- if (y < 10) *buf++ = y + '0';
- else *buf++ = y - 10 + 'a';
- c >>= 4;
+#define REVDOMAIN_MAP(rps, labnum) \
+ ((labnum) ? (rps)->map : (1 << NREVDOMAINS) - 1)
+
+int adns__revparse_label(struct revparse_state *rps, int labnum,
+ const char *label, int lablen)
+{
+ unsigned f = REVDOMAIN_MAP(rps, labnum);
+ const struct revparse_domain *rpd;
+ const char *tp;
+ unsigned d;
+ int i, ac;
+
+ for (rpd=revparse_domains, i=0, d=1; i<NREVDOMAINS; rpd++, i++, d <<= 1) {
+ if (!(f & d)) continue;
+ if (labnum >= rpd->nrevlab) {
+ tp = rpd->tail[labnum - rpd->nrevlab];
+ if (!tp || strncmp(label, tp, lablen) != 0 || tp[lablen])
+ goto mismatch;
+ } else {
+ ac = rpd->rev_parsecomp(label, lablen);
+ if (ac < 0) goto mismatch;
+ assert(labnum < sizeof(rps->ipv[i]));
+ rps->ipv[i][labnum] = ac;
}
+ continue;
+
+ mismatch:
+ f &= ~d;
+ if (!f) return -1;
}
- return buf;
+
+ rps->map = f;
+ return 0;
}
-const afinfo adns__inet6_afinfo = {
- AF_INET6, 128, ':', 32, 1, adns_r_aaaa,
- inet6_sockaddr_to_inaddr, inet6_sockaddr_equalp,
- inet6_prefix_mask, inet6_guess_len, inet6_matchp,
- inet6_rev_parsecomp, inet6_rev_mkaddr, inet6_rev_mkname
-};
+int adns__revparse_done(struct revparse_state *rps, int nlabels,
+ adns_rrtype *rrtype_r, struct af_addr *addr_r)
+{
+ unsigned f = REVDOMAIN_MAP(rps, nlabels);
+ const struct revparse_domain *rpd;
+ unsigned d;
+ int i, found = -1;
+
+ for (rpd=revparse_domains, i=0, d=1; i<NREVDOMAINS; rpd++, i++, d <<= 1) {
+ if (!(f & d)) continue;
+ if (nlabels >= rpd->nrevlab && !rpd->tail[nlabels - rpd->nrevlab])
+ { found = i; continue; }
+ f &= ~d;
+ if (!f) return -1;
+ }
+ assert(found >= 0); assert(f == (1 << found));
+
+ rpd = &revparse_domains[found];
+ *rrtype_r = rpd->rrtype;
+ addr_r->af = rpd->af;
+ rpd->rev_mkaddr(&addr_r->addr, rps->ipv[found]);
+ return 0;
+}
for (i=0; i<ads->nsortlist; i++) {
sl = &ads->sortlist[i];
- assert(sl->ai->matchp(&sl->base, &sl->base, &sl->mask));
+ assert(adns__addr_match_p(sl->af,&sl->base, sl->af,&sl->base, &sl->mask));
}
assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers);
}
for (serv= 0;
serv < ads->nservers &&
- !(udpaddr.sa.sa_family == ads->servers[serv].addr.sa.sa_family &&
- udp->ai->sockaddr_equalp(&udpaddr.sa,
- &ads->servers[serv].addr.sa));
+ !adns__sockaddr_equal_p(&udpaddr.sa,
+ &ads->servers[serv].addr.sa);
serv++);
if (serv >= ads->nservers) {
adns__warn(ads,-1,0,"datagram received from unknown nameserver %s",
struct in6_addr v6;
};
+#define NREVDOMAINS 2 /* keep in sync with addrfam! */
+struct revparse_state {
+ unsigned map; /* which domains are still live */
+ byte ipv[NREVDOMAINS][32]; /* address components so far */
+};
+
union checklabel_state {
- struct {
-#define PTR_NDOMAIN 2
- unsigned domainmap; /* which domains are still live */
- byte ipv[PTR_NDOMAIN][32]; /* address components so far */
- } ptr;
+ struct revparse_state ptr;
};
-typedef struct {
- int af;
- int width;
- int delim;
- int nrevcomp;
- int revcompwd;
- adns_rrtype rrtype;
- const void *(*sockaddr_to_inaddr)(const struct sockaddr *sa);
- int (*sockaddr_equalp)(const struct sockaddr *sa,
- const struct sockaddr *sb);
- void (*prefix_mask)(int len, union gen_addr *a);
- int (*guess_len)(const union gen_addr *a);
- int (*matchp)(const union gen_addr *addr,
- const union gen_addr *base, const union gen_addr *mask);
- int (*rev_parsecomp)(const char *p, size_t n);
- void (*rev_mkaddr)(union gen_addr *addr, const byte *ipv);
- char *(*rev_mkname)(const struct sockaddr *sa, char *buf);
-} afinfo;
-
-struct afinfo_addr { const afinfo *ai; union gen_addr addr; };
+struct af_addr { int af; union gen_addr addr; };
typedef struct {
void *ext;
union {
struct {
- struct afinfo_addr addr;
+ adns_rrtype rev_rrtype;
+ struct af_addr addr;
} ptr;
struct {
unsigned want, have;
struct query_queue udpw, tcpw, childw, output;
adns_query forallnext;
int nextid, tcpsocket;
- struct udpsocket { const afinfo *ai; int fd; } udpsocket[MAXUDP];
+ struct udpsocket { int af; int fd; } udpsocket[MAXUDP];
int nudp;
vbuf tcpsend, tcprecv;
int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip;
struct pollfd pollfds_buf[MAX_POLLFDS];
adns_rr_addr servers[MAXSERVERS];
struct sortlist {
- const afinfo *ai;
+ int af;
union gen_addr base, mask;
} sortlist[MAXSORTLIST];
char **searchlist;
/* From addrfam.c: */
-extern const afinfo adns__inet_afinfo, adns__inet6_afinfo;
+extern int adns__af_supported_p(int af);
+/* Return nonzero if the address family af known to the library and supported
+ * by the other addrfam operations. Note that the other operations will
+ * abort on an unrecognized address family rather than returning an error
+ * code.
+ */
+
+extern int adns__sockaddr_equal_p(const struct sockaddr *sa,
+ const struct sockaddr *sb);
+/* Return nonzero if the two socket addresses are equal (in all significant
+ * respects).
+ */
+
+extern int adns__gen_pton(const char *p, int *af_r, union gen_addr *addr_r);
+/* Parse an address at p, deciding which address family it belongs to. On
+ * success, returns 1 (like inet_aton) having stashed the address family in
+ * *af_r and the parsed address in *addr_r. If the address string is
+ * invalid, returns 0.
+ */
+
+extern int adns__addr_width(int af);
+/* Return the width of addresses of family af, in bits. */
+
+extern void adns__prefix_mask(int af, int len, union gen_addr *mask_r);
+/* Store in mask_r an address mask for address family af, whose first len
+ * bits are set and the remainder are clear. This is what you want for
+ * converting a prefix length into a netmask.
+ */
+
+extern int adns__guess_prefix_length(int af, const union gen_addr *addr);
+/* Given a network base address, guess the appropriate prefix length based on
+ * the appropriate rules for the address family (e.g., for IPv4, this uses
+ * the old address classes).
+ */
+
+extern int adns__addr_match_p(int addraf, const union gen_addr *addr,
+ int netaf, const union gen_addr *base,
+ const union gen_addr *mask);
+/* Given an address af (with family addraf) and a network (with family netaf,
+ * base address base, and netmask mask), return nonzero if the address lies
+ * within the network.
+ */
+
+const void *adns__sockaddr_to_inaddr(const struct sockaddr *sa);
+/* Given a socket address, return a pointer to the actual network address
+ * within it.
+ */
+
+extern int adns__make_reverse_domain(const struct sockaddr *sa,
+ const char *zone,
+ char **buf_io, size_t bufsz,
+ char **buf_free_r);
+/* Construct a reverse domain string, given a socket address and a parent
+ * zone. If zone is null, then use the standard reverse-lookup zone for the
+ * address family. If the length of the resulting string is no larger than
+ * bufsz, then the result is stored starting at *buf_io; otherwise a new
+ * buffer is allocated is used, and a pointer to it is stored in both *buf_io
+ * and *buf_free_r (the latter of which should be null on entry). If
+ * something goes wrong, then an errno value is returned: ENOSYS if the
+ * address family of sa isn't recognized, or ENOMEM if the attempt to
+ * allocate an output buffer failed.
+ */
+
+extern int adns__revparse_label(struct revparse_state *rps, int labnum,
+ const char *label, int lablen);
+/* Parse a label in a reverse-domain name, given its index labnum (starting
+ * from zero), a pointer to its contents (which need not be null-terminated),
+ * and its length. The state in *rps is initialized implicitly when labnum
+ * is zero.
+ *
+ * Returns zero if the parse was successful, nonzero if the domain name is
+ * definitely invalid and the parse must be abandoned.
+ */
+
+extern int adns__revparse_done(struct revparse_state *rps, int nlabels,
+ adns_rrtype *rrtype_r, struct af_addr *addr_r);
+/* Finishes parsing a reverse-domain name, given the total number of labels
+ * in the name. On success, fills in the address in *addr_r, and the forward
+ * query type in *rrtype_r (because that turns out to be useful). Returns
+ * nonzero if the parse must be abandoned.
+ */
/* From setup.c: */
adns_queryflags flags,
void *context,
adns_query *query_r) {
- char *buf, *buf_free, *p;
+ char *buf, *buf_free = 0;
char shortbuf[100];
- const afinfo *ai;
- int r, lreq;
+ int r;
flags &= ~adns_qf_search;
- switch (addr->sa_family) {
- case AF_INET:
- ai = &adns__inet_afinfo;
- if (!zone) zone = "in-addr.arpa";
- break;
- case AF_INET6:
- ai = &adns__inet6_afinfo;
- if (!zone) zone = "ip6.arpa";
- break;
- default:
- return ENOSYS;
- }
-
- lreq= strlen(zone) + ai->nrevcomp*(ai->revcompwd + 1) + 1;
- if (lreq > sizeof(shortbuf)) {
- buf= malloc(lreq);
- if (!buf) return errno;
- buf_free= buf;
- } else {
- buf= shortbuf;
- buf_free= 0;
- }
-
- p = ai->rev_mkname(addr, buf);
- *p++ = '.';
- strcpy(p, zone);
-
+ buf = shortbuf;
+ r= adns__make_reverse_domain(addr,zone, &buf,sizeof(shortbuf),&buf_free);
+ if (r) return r;
r= adns_submit(ads,buf,type,flags,context,query_r);
free(buf_free);
return r;
static void readconfig(adns_state ads, const char *filename, int warnmissing);
-static const afinfo *const transport_aftab[] = {
- &adns__inet_afinfo,
- &adns__inet6_afinfo,
- 0
-};
-
-static const afinfo *find_afinfo(int af)
-{
- int i;
-
- for (i = 0; transport_aftab[i]; i++)
- if (transport_aftab[i]->af == af) return transport_aftab[i];
- return 0;
-}
-
static void addserver(adns_state ads, struct sockaddr *sa, int n) {
int i;
adns_rr_addr *ss;
- const afinfo *ai;
char buf[MAX_ADDRSTRLEN];
- ai = find_afinfo(sa->sa_family);
- if (!ai) {
+ if (!adns__af_supported_p(sa->sa_family)) {
adns__diag(ads,-1,0,
"nameserver %s for unknown address family %d ignored",
adns__sockaddr_ntoa(sa, n, buf), sa->sa_family);
}
for (i=0; i<ads->nservers; i++) {
- if (ads->servers[i].addr.sa.sa_family == sa->sa_family &&
- ai->sockaddr_equalp(sa, &ads->servers[i].addr.sa)) {
+ if (adns__sockaddr_equal_p(sa, &ads->servers[i].addr.sa)) {
adns__debug(ads,-1,0,"duplicate nameserver %s ignored",
adns__sockaddr_ntoa(sa, n, buf));
return;
const char *maskwhat;
struct sortlist *sl;
int l;
- const afinfo *ai;
+ int af;
int initial = -1;
if (!buf) return;
sl= &ads->sortlist[ads->nsortlist];
- if (strchr(tbuf, ':'))
- ai= &adns__inet6_afinfo;
- else
- ai= &adns__inet_afinfo;
-
- if (!inet_pton(ai->af, tbuf, &sl->base)) {
+ if (!adns__gen_pton(tbuf, &af, &sl->base)) {
configparseerr(ads,fn,lno,"invalid address `%s' in sortlist",tbuf);
continue;
}
if (slash) {
- if (strchr(slash,ai->delim)) {
+ if (slash[strspn(slash, "0123456789")]) {
maskwhat = "mask";
- if (!inet_pton(ai->af,slash,&sl->mask)) {
+ if (!inet_pton(af,slash,&sl->mask)) {
configparseerr(ads,fn,lno,"invalid mask `%s' in sortlist",slash);
continue;
}
} else {
maskwhat = "prefix length";
initial= strtoul(slash,&ep,10);
- if (*ep || initial>ai->width) {
+ if (*ep || initial>adns__addr_width(af)) {
configparseerr(ads,fn,lno,"mask length `%s' invalid",slash);
continue;
}
- ai->prefix_mask(initial, &sl->mask);
+ adns__prefix_mask(af, initial, &sl->mask);
}
} else {
maskwhat = "implied prefix length";
- initial = ai->guess_len(&sl->base);
+ initial = adns__guess_prefix_length(af, &sl->base);
if (initial < 0) {
configparseerr(ads,fn,lno, "network address `%s'"
" in sortlist is not in classed ranges,"
" must specify mask explicitly", tbuf);
continue;
}
- ai->prefix_mask(initial, &sl->mask);
+ adns__prefix_mask(af, initial, &sl->mask);
}
- if (!ai->matchp(&sl->base, &sl->base, &sl->mask)) {
+ if (!adns__addr_match_p(af,&sl->base, af,&sl->base,&sl->mask)) {
if (initial >= 0) {
configparseerr(ads,fn,lno, "%s %d in sortlist"
" overlaps address `%s'",maskwhat,initial,tbuf);
continue;
}
- sl->ai = ai;
+ sl->af = af;
ads->nsortlist++;
}
}
continue;
assert(ads->nudp < MAXUDP);
udp = &ads->udpsocket[ads->nudp];
- udp->ai = find_afinfo(ads->servers[i].addr.sa.sa_family);
- assert(udp->ai);
- udp->fd = socket(udp->ai->af,SOCK_DGRAM,proto->p_proto);
+ udp->af = ads->servers[i].addr.sa.sa_family;
+ udp->fd = socket(udp->af,SOCK_DGRAM,proto->p_proto);
if (udp->fd < 0) { r= errno; goto x_free; }
r= adns__setnonblock(ads,udp->fd);
if (r) { r= errno; goto x_closeudp; }
for (i=0, slp=ads->sortlist;
i<ads->nsortlist &&
- !(af == slp->ai->af &&
- slp->ai->matchp(ad, &slp->base, &slp->mask)) &&
- !(v6mappedp && slp->ai->af == AF_INET &&
- slp->ai->matchp(&a, &slp->base, &slp->mask));
+ !adns__addr_match_p(af,ad, slp->af,&slp->base,&slp->mask) &&
+ !(v6mappedp &&
+ adns__addr_match_p(AF_INET,&a, slp->af,&slp->base,&slp->mask));
i++, slp++);
return i;
}
static int search_sortlist_sa(adns_state ads, const struct sockaddr *sa)
{
- const afinfo *ai = 0;
-
- switch (sa->sa_family) {
- case AF_INET: ai = &adns__inet_afinfo; break;
- case AF_INET6: ai = &adns__inet6_afinfo; break;
- }
- assert(ai);
-
- return search_sortlist(ads, sa->sa_family, ai->sockaddr_to_inaddr(sa));
+ return search_sortlist(ads, sa->sa_family, adns__sockaddr_to_inaddr(sa));
}
static int dip_sockaddr(adns_state ads,
adns__query_fail(parent,adns_s_inconsistent);
}
-static const struct ptr_expectdomain {
- const afinfo *ai;
- const char *const tail[3];
-} ptr_expectdomain[PTR_NDOMAIN] = {
- { &adns__inet_afinfo, { DNS_INADDR_ARPA, 0 } },
- { &adns__inet6_afinfo, { DNS_IP6_ARPA, 0 } }
-};
-
static adns_status ckl_ptr(adns_state ads, adns_queryflags flags,
union checklabel_state *css, qcontext *ctx,
int labnum, const char *label, int lablen)
{
- int i, found, ac;
- unsigned f = labnum ? css->ptr.domainmap : (1 << PTR_NDOMAIN) - 1;
- unsigned d;
- const char *tp;
- const struct ptr_expectdomain *ed;
- struct afinfo_addr *ap;
-
if (lablen) {
- for (ed = ptr_expectdomain, i = 0, d = 1;
- i < PTR_NDOMAIN;
- ed++, i++, d <<= 1) {
- if (!(f & d)) continue;
- if (labnum < ed->ai->nrevcomp) {
- ac = ed->ai->rev_parsecomp(label, lablen);
- if (ac < 0) goto mismatch;
- assert(labnum < sizeof(css->ptr.ipv[i]));
- css->ptr.ipv[i][labnum] = ac;
- } else {
- tp = ed->tail[labnum - ed->ai->nrevcomp];
- if (!tp || strncmp(label, tp, lablen) != 0 || tp[lablen])
- goto mismatch;
- }
- continue;
-
- mismatch:
- f &= ~d;
- if (!f) return adns_s_querydomainwrong;
- }
+ if (adns__revparse_label(&css->ptr, labnum, label,lablen))
+ return adns_s_querydomainwrong;
} else {
- found = -1;
- for (ed = ptr_expectdomain, i = 0, d = 1;
- i < PTR_NDOMAIN;
- ed++, i++, d <<= 1) {
- if (!(f & d)) continue;
- if (labnum >= ed->ai->nrevcomp && !ed->tail[labnum - ed->ai->nrevcomp])
- { found = i; continue; }
- f &= ~d;
- if (!f) return adns_s_querydomainwrong;
- }
- assert(found >= 0 && f == (1 << found));
-
- ed = &ptr_expectdomain[found];
- ap = &ctx->tinfo.ptr.addr;
- ap->ai = ed->ai;
- ed->ai->rev_mkaddr(&ap->addr, css->ptr.ipv[found]);
+ if (adns__revparse_done(&css->ptr, labnum,
+ &ctx->tinfo.ptr.rev_rrtype,
+ &ctx->tinfo.ptr.addr))
+ return adns_s_querydomainwrong;
}
-
- css->ptr.domainmap = f;
return adns_s_ok;
}
int max, void *datap) {
char **rrp= datap;
adns_status st;
- struct afinfo_addr *ap;
+ adns_rrtype rrtype = pai->qu->ctx.tinfo.ptr.rev_rrtype;
int cbyte, id;
adns_query nqu;
qcontext ctx;
if (st) return st;
if (cbyte != max) return adns_s_invaliddata;
- ap= &pai->qu->ctx.tinfo.ptr.addr;
- assert(ap->ai);
-
st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
pai->dgram, pai->dglen, dmstart,
- ap->ai->rrtype, adns_qf_quoteok_query);
+ rrtype, adns_qf_quoteok_query);
if (st) return st;
ctx.ext= 0;
ctx.callback= icb_ptr;
memset(&ctx.pinfo,0,sizeof(ctx.pinfo));
memset(&ctx.tinfo,0,sizeof(ctx.tinfo));
- st= adns__internal_submit(pai->ads, &nqu, adns__findtype(ap->ai->rrtype),
- ap->ai->rrtype, &pai->qu->vb, id,
+ st= adns__internal_submit(pai->ads, &nqu, adns__findtype(rrtype),
+ rrtype, &pai->qu->vb, id,
adns_qf_quoteok_query, pai->now, &ctx);
if (st) return st;