chiark / gitweb /
addrfam: New arrangements for protocol address types
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 12 Jul 2014 11:56:46 +0000 (12:56 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 19 Oct 2014 20:14:46 +0000 (21:14 +0100)
Abolish union gen_addr and struct af_addr.  It is not legitimate to
up-cast to a union (since the alignment might be wrong), and the
profusion of additonal address types is confusing.

The new arrangements are:

* Use adns_sockaddr wherever we can.  That includes situations
  where the port (or v6 scope, etc.) is not relevant.

* Where that's not possible, use a struct sockaddr if we can.

* Where we need to deal with an IP address of unspecified family (we
  use the phrase `protocol address') we must use a void*.

Other changes we make here:

* Reorganise the set of functions provided by addrfam.c.  Previously
  there was a comprehensive set of manipulators.  Now, we have
  precisely the set of functions we need.

  The new functions are called adns__addr_* when they deal with
  adns_sockaddrs, and adns_sockaddr_* when dealing with struct
  sockaddrs.

  The new functions normally no longer need to take an explicit af
  parameter, since they can use the af field in the sockaddr.

* adns__sockaddrs_equal (previously, adns__sockaddr_equal_p) now uses
  the generic protocol address comparison function; consequently
  remove the IN6_ADDR_EQUALP macro since it now has only one use site.

* Remove the Lispy "-p" suffix from predicate function names.

And of course the very formulaic changes to code which accesses
addresses of various kinds.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/addrfam.c
src/check.c
src/event.c
src/internal.h
src/setup.c
src/types.c

index b03b6ab..0f6bc18 100644 (file)
@@ -62,39 +62,43 @@ static void unknown_af(int af) {
   abort();
 }
 
-#define IN6_ADDR_EQUALP(a, b)                                          \
-  (!memcmp((a).s6_addr, (b).s6_addr, sizeof((a).s6_addr)))
-
-int adns__genaddr_equal_p(int af, const union gen_addr *a,
-                         int bf, const void *b) {
-  const union gen_addr *bb= b;
-  if (af != bf) return 0;
-  switch (af) {
+int adns__addrs_equal_raw(const struct sockaddr *a,
+                        int bf, const void *b) {
+  if (a->sa_family != bf) return 0;
+  switch (a->sa_family) {
   AF_CASES(af);
-  af_inet: return a->v4.s_addr == bb->v4.s_addr;
-  af_inet6: return IN6_ADDR_EQUALP(a->v6, bb->v6);
-  default: unknown_af(af); return -1;
+  af_inet:
+    return ((const struct sockaddr_in*)a)->sin_addr.s_addr ==
+           ((const struct in_addr*)b)->s_addr;
+  af_inet6:
+    return !memcmp(&((const struct sockaddr_in6*)a)->sin6_addr,
+                  b, sizeof(struct in6_addr));
+  default: unknown_af(a->sa_family); return -1;
   }
 }
 
-int adns__sockaddr_equal_p(const struct sockaddr *sa,
-                          const struct sockaddr *sb) {
-  if (sa->sa_family != sb->sa_family) return 0;
+int adns__addrs_equal(const adns_sockaddr *a, const adns_sockaddr *b) {
+  return adns__addrs_equal_raw(&a->sa, b->sa.sa_family,
+                              adns__sockaddr_addr(&b->sa));
+}
+
+int adns__sockaddrs_equal(const struct sockaddr *sa,
+                         const struct sockaddr *sb) {
+  if (!adns__addrs_equal_raw(sa, sb->sa_family, adns__sockaddr_addr(sb)))
+    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);
+    return 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 (IN6_ADDR_EQUALP(sin6a->sin6_addr, sin6b->sin6_addr) &&
-           sin6a->sin6_port == sin6b->sin6_port &&
-           sin6a->sin6_scope_id == sin6b->sin6_scope_id);
+    return sin6a->sin6_port == sin6b->sin6_port &&
+           sin6a->sin6_scope_id == sin6b->sin6_scope_id;
   }
   default:
     unknown_af(sa->sa_family);
@@ -111,16 +115,17 @@ int adns__addr_width(int af) {
   }
 }
 
-void adns__prefix_mask(int af, int len, union gen_addr *mask_r) {
+void adns__prefix_mask(adns_sockaddr *sa, int len) {
+  int af= sa->sa.sa_family;
   switch (af) {
   AF_CASES(af);
   af_inet:
     assert(len <= 32);
-    mask_r->v4.s_addr= htonl(!len ? 0 : 0xffffffff << (32-len));
+    sa->inet.sin_addr.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;
+    unsigned char *m= sa->inet6.sin6_addr.s6_addr;
     assert(len <= 128);
     memset(m, 0xff, i);
     if (j) m[i++]= (0xff << (8-j)) & 0xff;
@@ -132,11 +137,12 @@ void adns__prefix_mask(int af, int len, union gen_addr *mask_r) {
   }
 }
 
-int adns__guess_prefix_length(int af, const union gen_addr *addr) {
+int adns__guess_prefix_length(const adns_sockaddr *sa) {
+  int af= sa->sa.sa_family;
   switch (af) {
   AF_CASES(af);
   af_inet: {
-    unsigned a= (ntohl(addr->v4.s_addr) >> 24) & 0xff;
+    unsigned a= (ntohl(sa->inet.sin_addr.s_addr) >> 24) & 0xff;
     if (a < 128) return 8;
     else if (a < 192) return 16;
     else if (a < 224) return 24;
@@ -150,69 +156,64 @@ int adns__guess_prefix_length(int af, const union gen_addr *addr) {
   }
 }
 
-int adns__addr_match_p(int addraf, const union gen_addr *addr,
-                      int netaf, const union gen_addr *base,
-                      const union gen_addr *mask)
+int adns__addr_matches(int af, const void *addr,
+                      const adns_sockaddr *base, const adns_sockaddr *mask)
 {
-  if (addraf != netaf) return 0;
-  switch (addraf) {
+  assert(base->sa.sa_family == mask->sa.sa_family);
+  if (af != base->sa.sa_family) return 0;
+  switch (af) {
   AF_CASES(af);
-  af_inet:
-    return (addr->v4.s_addr & mask->v4.s_addr) == base->v4.s_addr;
+  af_inet: {
+    const struct in_addr *v4 = addr;
+    return (v4->s_addr & mask->inet.sin_addr.s_addr)
+      == base->inet.sin_addr.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;
+    const char *a= addr;
+    const char *b= base->inet6.sin6_addr.s6_addr;
+    const char *m= mask->inet6.sin6_addr.s6_addr;
     for (i = 0; i < 16; i++)
       if ((a[i] & m[i]) != b[i]) return 0;
     return 1;
   } break;
   default:
-    unknown_af(addraf);
+    unknown_af(af);
     return -1;
   }
 }
 
-void adns__sockaddr_extract(const struct sockaddr *sa,
-                           union gen_addr *a_r, int *port_r) {
+const void *adns__sockaddr_addr(const struct sockaddr *sa) {
   switch (sa->sa_family) {
   AF_CASES(af);
   af_inet: {
     const struct sockaddr_in *sin = CSIN(sa);
-    if (port_r) *port_r= ntohs(sin->sin_port);
-    if (a_r) a_r->v4= sin->sin_addr;
-    break;
+    return &sin->sin_addr;
   }
   af_inet6: {
     const struct sockaddr_in6 *sin6 = CSIN6(sa);
-    if (port_r) *port_r= ntohs(sin6->sin6_port);
-    if (a_r) a_r->v6= sin6->sin6_addr;
-    break;
+    return &sin6->sin6_addr;
   }
   default:
     unknown_af(sa->sa_family);
   }
 }
 
-void adns__sockaddr_inject(const union gen_addr *a, int port,
-                          struct sockaddr *sa) {
-  switch (sa->sa_family) {
+void adns__addr_inject(const void *a, adns_sockaddr *sa) {
+  switch (sa->sa.sa_family) {
   AF_CASES(af);
   af_inet: {
-    struct sockaddr_in *sin = SIN(sa);
-    if (port != -1) sin->sin_port= htons(port);
-    if (a) sin->sin_addr= a->v4;
+    struct sockaddr_in *sin = &sa->inet;
+    memcpy(&sin->sin_addr, a, sizeof(sin->sin_addr));
     break;
   }
   af_inet6: {
-    struct sockaddr_in6 *sin6 = SIN6(sa);
-    if (port != -1) sin6->sin6_port= htons(port);
-    if (a) sin6->sin6_addr= a->v6;
+    struct sockaddr_in6 *sin6 = &sa->inet6;
+    memcpy(&sin6->sin6_addr, a, sizeof(sin6->sin6_addr));
     break;
   }
   default:
-    unknown_af(sa->sa_family);
+    unknown_af(sa->sa.sa_family);
   }
 }
 
@@ -536,9 +537,10 @@ static int inet_rev_parsecomp(const char *p, size_t n) {
   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 void inet_rev_mkaddr(adns_sockaddr *addr, const byte *ipv) {
+  struct in_addr *v4 = &addr->inet.sin_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) {
@@ -549,8 +551,9 @@ static int inet6_rev_parsecomp(const char *p, size_t n) {
   else return -1;
 }
 
-static void inet6_rev_mkaddr(union gen_addr *addr, const byte *ipv) {
-  unsigned char *a= addr->v6.s6_addr;
+static void inet6_rev_mkaddr(adns_sockaddr *addr, const byte *ipv) {
+  struct in6_addr *v6 = &addr->inet6.sin6_addr;
+  unsigned char *a= v6->s6_addr;
   int i;
 
   for (i=0; i<16; i++)
@@ -567,8 +570,8 @@ static const struct revparse_domain {
    * 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 */
+  void (*rev_mkaddr)(adns_sockaddr *addr, const byte *ipv);
+  /* write out the parsed protocol address from a vector of parsed components */
 
   const char *const tail[3];           /* tail label names */
 } revparse_domains[NREVDOMAINS] = {
@@ -613,7 +616,7 @@ int adns__revparse_label(struct revparse_state *rps, int labnum,
 }
 
 int adns__revparse_done(struct revparse_state *rps, int nlabels,
-                       adns_rrtype *rrtype_r, struct af_addr *addr_r) {
+                       adns_rrtype *rrtype_r, adns_sockaddr *addr_r) {
   unsigned f= REVDOMAIN_MAP(rps, nlabels);
   const struct revparse_domain *rpd;
   unsigned d;
@@ -630,7 +633,7 @@ int adns__revparse_done(struct revparse_state *rps, int nlabels,
 
   rpd= &revparse_domains[found];
   *rrtype_r= rpd->rrtype;
-  addr_r->af= rpd->af;
-  rpd->rev_mkaddr(&addr_r->addr, rps->ipv[found]);
+  addr_r->sa.sa_family= rpd->af;
+  rpd->rev_mkaddr(addr_r, rps->ipv[found]);
   return 0;
 }
index 21dca70..c26dbdc 100644 (file)
@@ -82,7 +82,9 @@ static void checkc_global(adns_state ads) {
 
   for (i=0; i<ads->nsortlist; i++) {
     sl= &ads->sortlist[i];
-    assert(adns__addr_match_p(sl->af,&sl->base, sl->af,&sl->base,&sl->mask));
+    assert(adns__addr_matches(sl->base.sa.sa_family,
+                             adns__sockaddr_addr(&sl->base.sa),
+                             &sl->base,&sl->mask));
   }
 
   assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers);
index 5b2b42d..ce5276f 100644 (file)
@@ -411,8 +411,8 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
        }
        for (serv= 0;
             serv < ads->nservers &&
-              !adns__sockaddr_equal_p(&udpaddr.sa,
-                                      &ads->servers[serv].addr.sa);
+              !adns__sockaddrs_equal(&udpaddr.sa,
+                                     &ads->servers[serv].addr.sa);
             serv++);
        if (serv >= ads->nservers) {
          adns__warn(ads,-1,0,"datagram received from unknown nameserver %s",
index 4144ec1..0b39418 100644 (file)
@@ -131,13 +131,6 @@ typedef struct {
   struct timeval now;
 } parseinfo;
 
-union gen_addr {
-  struct in_addr v4;
-  struct in6_addr v6;
-};
-
-struct af_addr { int af; union gen_addr addr; };
-
 #define NREVDOMAINS 2                  /* keep in sync with addrfam! */
 struct revparse_state {
   unsigned map;                                /* which domains are still live */
@@ -155,7 +148,7 @@ typedef struct {
   union {
     struct {
       adns_rrtype rev_rrtype;
-      struct af_addr addr;
+      adns_sockaddr addr;
     } ptr;
     struct {
       unsigned want, have;
@@ -399,8 +392,7 @@ struct adns__state {
   struct pollfd pollfds_buf[MAX_POLLFDS];
   adns_rr_addr servers[MAXSERVERS];
   struct sortlist {
-    int af;
-    union gen_addr base, mask;
+    adns_sockaddr base, mask;
   } sortlist[MAXSORTLIST];
   char **searchlist;
   unsigned short rand48xsubi[3];
@@ -408,21 +400,20 @@ struct adns__state {
 
 /* From addrfam.c: */
 
-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__addrs_equal_raw(const struct sockaddr *a,
+                                int bf, const void *b);
+/* Returns nonzero a's family is bf and a's protocol address field
+ * refers to the same protocol address as that stored at ba.
  */
 
-extern int adns__genaddr_equal_p(int af, const union gen_addr *a,
-                                int bf, const void *b);
-/* b should point to a `struct in_addr' or equivalent for the address family
- * bf.  Returns nonzero if the two addresses are equal.
+extern int adns__addrs_equal(const adns_sockaddr *a,
+                            const adns_sockaddr *b);
+/* Returns nonzero if the two refer to the same protocol address
+ * (disregarding port, IPv6 scope, etc).
  */
 
-extern int adns__sockaddr_equal_p(const struct sockaddr *sa,
-                                 const struct sockaddr *sb);
+extern int adns__sockaddrs_equal(const struct sockaddr *sa,
+                                const struct sockaddr *sb);
 /* Return nonzero if the two socket addresses are equal (in all significant
  * respects).
  */
@@ -430,39 +421,33 @@ extern int adns__sockaddr_equal_p(const struct sockaddr *sa,
 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 void adns__prefix_mask(adns_sockaddr *sa, int len);
+/* Stores in sa's protocol address field an address mask for address
+ * family af, whose first len bits are set and the remainder are
+ * clear.  On entry, sa's af field must be set.  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);
+extern int adns__guess_prefix_length(const adns_sockaddr *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.
+extern int adns__addr_matches(int af, const void *addr,
+                             const adns_sockaddr *base,
+                             const adns_sockaddr *mask);
+/* Return nonzero if the protocol address specified by af and addr
+ * lies within the network specified by base and mask.
  */
 
-extern void adns__sockaddr_extract(const struct sockaddr *sa,
-                                  union gen_addr *a_r, int *port_r);
-/* Extract fields from the socket address, filling in *a_r and *port_r with
- * the address and (integer, host byte-order) port number, respectively.
- * Either (or, pointlessly, both) of a_r and port_r may be null to mean
- * `don't care'.
+extern void adns__addr_inject(const void *a, adns_sockaddr *sa);
+/* Injects the protocol address *a into the socket adress sa.  Assumes
+ * that sa->sa_family is already set correctly.
  */
 
-extern void adns__sockaddr_inject(const union gen_addr *a, int port,
-                                 struct sockaddr *sa);
-/* Inject fields into the socket adress sa.  If a is not null, copy the
- * address in; if port is not -1, then copy the port (converting from host
- * byte-order).  Assumes that sa->sa_family is already set correctly.
+extern const void *adns__sockaddr_addr(const struct sockaddr *sa);
+/* Returns the address of the protocol address field in sa.
  */
 
 char *adns__sockaddr_ntoa(const struct sockaddr *sa, char *buf);
@@ -497,11 +482,12 @@ extern int adns__revparse_label(struct revparse_state *rps, int labnum,
  */
 
 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.
+                              adns_rrtype *rrtype_r, adns_sockaddr *addr_r);
+/* Finishes parsing a reverse-domain name, given the total number of
+ * labels in the name.  On success, fills in the af and protocol
+ * 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: */
index a082870..79e00e1 100644 (file)
@@ -47,7 +47,7 @@ static void addserver(adns_state ads, const struct sockaddr *sa, int n) {
   char buf[ADNS_ADDR2TEXT_BUFLEN];
   
   for (i=0; i<ads->nservers; i++) {
-    if (adns__sockaddr_equal_p(sa, &ads->servers[i].addr.sa)) {
+    if (adns__sockaddrs_equal(sa, &ads->servers[i].addr.sa)) {
       adns__debug(ads,-1,0,"duplicate nameserver %s ignored",
                  adns__sockaddr_ntoa(sa, buf));
       return;
@@ -165,17 +165,15 @@ static void ccf_search(adns_state ads, const char *fn,
   ads->searchlist= newptrs;
 }
 
-static int gen_pton(const char *text, int *af_io, union gen_addr *a) {
-  adns_rr_addr addr;
+static int gen_pton(const char *text, int want_af, adns_sockaddr *a) {
   int err;
+  int len;
 
-  addr.len= sizeof(addr.addr);
+  len= sizeof(*a);
   err= adns_text2addr(text,0, adns_qf_addrlit_scope_forbid,
-                     &addr.addr.sa, &addr.len);
+                     &a->sa, &len);
   if (err) { assert(err == EINVAL); return 0; }
-  if (*af_io == AF_UNSPEC) *af_io= addr.addr.sa.sa_family;
-  else if (*af_io != addr.addr.sa.sa_family) return 0;
-  adns__sockaddr_extract(&addr.addr.sa, a, 0);
+  if (want_af != AF_UNSPEC && a->sa.sa_family != want_af) return 0;
   return 1;
 }
 
@@ -186,7 +184,6 @@ static void ccf_sortlist(adns_state ads, const char *fn,
   const char *maskwhat;
   struct sortlist *sl;
   int l;
-  int af;
   int initial= -1;
 
   if (!buf) return;
@@ -209,8 +206,7 @@ static void ccf_sortlist(adns_state ads, const char *fn,
     if (slash) *slash++= 0;
 
     sl= &ads->sortlist[ads->nsortlist];
-    af= AF_UNSPEC;
-    if (!gen_pton(tbuf, &af, &sl->base)) {
+    if (!gen_pton(tbuf, AF_UNSPEC, &sl->base)) {
       configparseerr(ads,fn,lno,"invalid address `%s' in sortlist",tbuf);
       continue;
     }
@@ -218,32 +214,36 @@ static void ccf_sortlist(adns_state ads, const char *fn,
     if (slash) {
       if (slash[strspn(slash, "0123456789")]) {
        maskwhat = "mask";
-       if (!gen_pton(slash,&af,&sl->mask)) {
+       if (!gen_pton(slash, sl->base.sa.sa_family, &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>adns__addr_width(af)) {
+       if (*ep || initial>adns__addr_width(sl->base.sa.sa_family)) {
          configparseerr(ads,fn,lno,"mask length `%s' invalid",slash);
          continue;
        }
-       adns__prefix_mask(af, initial, &sl->mask);
+       sl->mask.sa.sa_family= sl->base.sa.sa_family;
+       adns__prefix_mask(&sl->mask, initial);
       }
     } else {
       maskwhat = "implied prefix length";
-      initial= adns__guess_prefix_length(af, &sl->base);
+      initial= adns__guess_prefix_length(&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;
       }
-      adns__prefix_mask(af, initial, &sl->mask);
+      sl->mask.sa.sa_family= sl->base.sa.sa_family;
+      adns__prefix_mask(&sl->mask, initial);
     }
 
-    if (!adns__addr_match_p(af,&sl->base, af,&sl->base,&sl->mask)) {
+    if (!adns__addr_matches(sl->base.sa.sa_family,
+                           adns__sockaddr_addr(&sl->base.sa),
+                           &sl->base,&sl->mask)) {
       if (initial >= 0) {
        configparseerr(ads,fn,lno, "%s %d in sortlist"
                       " overlaps address `%s'",maskwhat,initial,tbuf);
@@ -254,7 +254,6 @@ static void ccf_sortlist(adns_state ads, const char *fn,
       continue;
     }
 
-    sl->af= af;
     ads->nsortlist++;
   }
 }
index d53fe3e..8b9723e 100644 (file)
@@ -263,27 +263,26 @@ static adns_status pa_inaddr(const parseinfo *pai, int cbyte,
 
 static int search_sortlist(adns_state ads, int af, const void *ad) {
   const struct sortlist *slp;
-  const struct in6_addr *a6;
-  union gen_addr a;
+  struct in_addr a4;
   int i;
   int v6mappedp= 0;
 
   if (af == AF_INET6) {
-    a6= ad;
+    const struct in6_addr *a6= ad;
     if (IN6_IS_ADDR_V4MAPPED(a6)) {
-      a.v4.s_addr= htonl(((unsigned long)a6->s6_addr[12] << 24) |
-                        ((unsigned long)a6->s6_addr[13] << 16) |
-                        ((unsigned long)a6->s6_addr[14] <<  8) |
-                        ((unsigned long)a6->s6_addr[15] <<  0));
+      a4.s_addr= htonl(((unsigned long)a6->s6_addr[12] << 24) |
+                      ((unsigned long)a6->s6_addr[13] << 16) |
+                      ((unsigned long)a6->s6_addr[14] <<  8) |
+                      ((unsigned long)a6->s6_addr[15] <<  0));
       v6mappedp= 1;
     }
   }
 
   for (i=0, slp=ads->sortlist;
        i<ads->nsortlist &&
-        !adns__addr_match_p(af,ad, slp->af,&slp->base,&slp->mask) &&
+        !adns__addr_matches(af,ad, &slp->base,&slp->mask) &&
         !(v6mappedp &&
-          adns__addr_match_p(AF_INET,&a, slp->af,&slp->base,&slp->mask));
+          adns__addr_matches(AF_INET,&a4, &slp->base,&slp->mask));
        i++, slp++);
   return i;
 }
@@ -311,7 +310,7 @@ static adns_status csp_genaddr(vbuf *vb, int af, const void *p) {
 
   memset(&a, 0, sizeof(a));
   a.addr.sa.sa_family= af;
-  adns__sockaddr_inject(p, 0, &a.addr.sa);
+  adns__addr_inject(p, &a.addr);
   err= adns_addr2text(&a.addr.sa,0, buf,&len, 0); assert(!err);
   CSP_ADDSTR(buf);
   return adns_s_ok;
@@ -456,9 +455,8 @@ static adns_status pa_addr(const parseinfo *pai, int cbyte,
 }
 
 static int search_sortlist_sa(adns_state ads, const struct sockaddr *sa) {
-  union gen_addr a;
-  adns__sockaddr_extract(sa, &a, 0);
-  return search_sortlist(ads, sa->sa_family, &a);
+  const void *pa = adns__sockaddr_addr(sa);
+  return search_sortlist(ads, sa->sa_family, pa);
 }
 
 static int dip_sockaddr(adns_state ads,
@@ -1152,7 +1150,7 @@ static adns_status ckl_ptr(adns_state ads, adns_queryflags flags,
 
 static void icb_ptr(adns_query parent, adns_query child) {
   adns_answer *cans= child->answer;
-  const struct af_addr *queried;
+  const adns_sockaddr *queried;
   const unsigned char *found;
   adns_state ads= parent->ads;
   int i;
@@ -1167,8 +1165,8 @@ static void icb_ptr(adns_query parent, adns_query child) {
 
   queried= &parent->ctx.tinfo.ptr.addr;
   for (i=0, found=cans->rrs.bytes; i<cans->nrrs; i++, found+=cans->rrsz) {
-    if (adns__genaddr_equal_p(queried->af,&queried->addr,
-                             parent->ctx.tinfo.ptr.addr.af,found)) {
+    if (adns__addrs_equal_raw(&queried->sa,
+                         parent->ctx.tinfo.ptr.addr.sa.sa_family,found)) {
       if (!parent->children.head) {
        adns__query_done(parent);
        return;