chiark / gitweb /
src/: Fix internals to carry around address families.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 3 Jun 2014 09:27:38 +0000 (10:27 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 13 Jun 2014 08:57:41 +0000 (09:57 +0100)
This is preparatory work for IPv6 support, but there isn't any yet.
The code still acts directly on address structures (having asserted that
the family is AF_INET); switching on the address family is for later.

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
src/check.c
src/event.c
src/general.c
src/internal.h
src/setup.c
src/transmit.c
src/types.c

index 41cdde5ff3592d09f86d3e0bd4b9d8abcc114896..44f52b909e31cd1792144dab8d3939c8556aa9ef 100644 (file)
@@ -75,12 +75,19 @@ static void checkc_notcpbuf(adns_state ads) {
 }
 
 static void checkc_global(adns_state ads) {
+  const struct sortlist *sl;
   int i;
   
   assert(ads->udpsocket >= 0);
 
-  for (i=0; i<ads->nsortlist; i++)
-    assert(!(ads->sortlist[i].base.s_addr & ~ads->sortlist[i].mask.s_addr));
+  for (i=0; i<ads->nsortlist; i++) {
+    assert(ads->sortlist[i].af==AF_INET);
+    assert(!(ads->sortlist[i].base.v4.s_addr &
+            ~ads->sortlist[i].mask.v4.s_addr));
+    sl= &ads->sortlist[i];
+    assert(sl->af==AF_INET);
+    assert(!(sl->base.v4.s_addr & ~sl->mask.v4.s_addr));
+  }
 
   assert(ads->tcpserver >= 0 && ads->tcpserver < ads->nservers);
   
index e22a8d1c8c768d06524c7102fee10a42499edfec..ee4e5f7a8553c6c1c2c3cee138f662988b4d412d 100644 (file)
@@ -96,7 +96,7 @@ static void tcp_broken_events(adns_state ads) {
 
 void adns__tcp_tryconnect(adns_state ads, struct timeval now) {
   int r, fd, tries;
-  struct sockaddr_in addr;
+  adns_rr_addr *addr;
   struct protoent *proto;
 
   for (tries=0; tries<ads->nservers; tries++) {
@@ -120,7 +120,8 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) {
       adns__diag(ads,-1,0,"unable to find protocol no. for TCP !");
       return;
     }
-    fd= socket(AF_INET,SOCK_STREAM,proto->p_proto);
+    addr = &ads->servers[ads->tcpserver];
+    fd= socket(addr->addr.sa.sa_family, SOCK_STREAM, proto->p_proto);
     if (fd<0) {
       adns__diag(ads,-1,0,"cannot create TCP socket: %s",strerror(errno));
       return;
@@ -132,11 +133,7 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) {
       close(fd);
       return;
     }
-    memset(&addr,0,sizeof(addr));
-    addr.sin_family= AF_INET;
-    addr.sin_port= htons(DNS_PORT);
-    addr.sin_addr= ads->servers[ads->tcpserver].addr;
-    r= connect(fd,(const struct sockaddr*)&addr,sizeof(addr));
+    r= connect(fd,&addr->addr.sa,addr->len);
     ads->tcpsocket= fd;
     ads->tcpstate= server_connecting;
     if (r==0) { tcp_connected(ads,now); return; }
@@ -418,7 +415,9 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) {
       }
       for (serv= 0;
           serv < ads->nservers &&
-            ads->servers[serv].addr.s_addr != udpaddr.sin_addr.s_addr;
+            (assert(ads->servers[serv].addr.sa.sa_family==AF_INET),
+             ads->servers[serv].addr.inet.sin_addr.s_addr !=
+               udpaddr.sin_addr.s_addr);
           serv++);
       if (serv >= ads->nservers) {
        adns__warn(ads,-1,0,"datagram received from unknown nameserver %s",
index 6ef2cb316213e17b2cf068f00659e459ea0c92c2..052c7e1556a77ad067b9b49b0fe13fd6cddd203e 100644 (file)
@@ -83,7 +83,9 @@ void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent,
   }
   
   if (serv>=0) {
-    adns__lprintf(ads,"%sNS=%s",bef,inet_ntoa(ads->servers[serv].addr));
+    assert(ads->servers[serv].addr.sa.sa_family==AF_INET);
+    adns__lprintf(ads,"%sNS=%s",bef,
+                 inet_ntoa(ads->servers[serv].addr.inet.sin_addr));
     bef=", "; aft=")\n";
   }
 
index 7ad6daa0d8a10612e4448155e4c405be29ae7e6f..97af49ec620ed7752445a7f11624b19365af9bef 100644 (file)
@@ -124,6 +124,13 @@ 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; };
+
 union checklabel_state {
   struct { byte ipv[4]; } ptr;
 };
@@ -134,7 +141,7 @@ typedef struct {
 
   union {
     struct {
-      struct in_addr addr;
+      struct af_addr addr;
     } ptr;
   } tinfo; /* type-specific state for the query itself: zero-init if you
            * don't know better. */
@@ -358,11 +365,10 @@ struct adns__state {
   struct sigaction stdsigpipe;
   sigset_t stdsigmask;
   struct pollfd pollfds_buf[MAX_POLLFDS];
-  struct server {
-    struct in_addr addr;
-  } servers[MAXSERVERS];
+  adns_rr_addr servers[MAXSERVERS];
   struct sortlist {
-    struct in_addr base, mask;
+    int af;
+    union gen_addr base, mask;
   } sortlist[MAXSORTLIST];
   char **searchlist;
   unsigned short rand48xsubi[3];
index f73926c9f0c0ee50230fd4db0e408407515444eb..ce440557a108f71dca58ee1f4d8f2e3cd61a8ea2 100644 (file)
 
 static void readconfig(adns_state ads, const char *filename, int warnmissing);
 
-static void addserver(adns_state ads, struct in_addr addr) {
+static void addserver(adns_state ads, const struct sockaddr *sa, int n) {
   int i;
-  struct server *ss;
+  adns_rr_addr *ss;
+  const struct sockaddr_in *sin;
+
+  assert(sa->sa_family==AF_INET); assert(n>=sizeof(*sin));
+  sin= (const void *)sa;
   
   for (i=0; i<ads->nservers; i++) {
-    if (ads->servers[i].addr.s_addr == addr.s_addr) {
-      adns__debug(ads,-1,0,"duplicate nameserver %s ignored",inet_ntoa(addr));
+    assert(ads->servers[i].addr.sa.sa_family==AF_INET);
+    if (ads->servers[i].addr.inet.sin_addr.s_addr == sin->sin_addr.s_addr) {
+      adns__debug(ads,-1,0,"duplicate nameserver %s ignored",
+                 inet_ntoa(sin->sin_addr));
       return;
     }
   }
   
   if (ads->nservers>=MAXSERVERS) {
-    adns__diag(ads,-1,0,"too many nameservers, ignoring %s",inet_ntoa(addr));
+    adns__diag(ads,-1,0,"too many nameservers, ignoring %s",
+              inet_ntoa(sin->sin_addr));
     return;
   }
 
   ss= ads->servers+ads->nservers;
-  ss->addr= addr;
+  assert(n <= sizeof(ss->addr));
+  ss->len = n;
+  memcpy(&ss->addr, sa, n);
   ads->nservers++;
 }
 
@@ -105,14 +114,17 @@ static int nextword(const char **bufp_io, const char **word_r, int *l_r) {
 
 static void ccf_nameserver(adns_state ads, const char *fn,
                           int lno, const char *buf) {
-  struct in_addr ia;
-  
-  if (!inet_aton(buf,&ia)) {
+  struct sockaddr_in sin;
+
+  memset(&sin,0,sizeof(sin));
+  sin.sin_family= AF_INET;
+  sin.sin_port= htons(DNS_PORT);
+  if (!inet_aton(buf,&sin.sin_addr)) {
     configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf);
     return;
   }
-  adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(ia));
-  addserver(ads,ia);
+  adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(sin.sin_addr));
+  addserver(ads,(const struct sockaddr *)&sin,sizeof(sin));
 }
 
 static void ccf_search(adns_state ads, const char *fn,
@@ -221,8 +233,9 @@ static void ccf_sortlist(adns_state ads, const char *fn,
       continue;
     }
 
-    ads->sortlist[ads->nsortlist].base= base;
-    ads->sortlist[ads->nsortlist].mask= mask;
+    ads->sortlist[ads->nsortlist].af= AF_INET;
+    ads->sortlist[ads->nsortlist].base.v4= base;
+    ads->sortlist[ads->nsortlist].mask.v4= mask;
     ads->nsortlist++;
   }
 }
@@ -548,17 +561,24 @@ static int init_begin(adns_state *ads_r, adns_initflags flags,
 }
 
 static int init_finish(adns_state ads) {
-  struct in_addr ia;
+  struct sockaddr_in sin;
   struct protoent *proto;
-  int r;
+  int i, r;
   
   if (!ads->nservers) {
     if (ads->logfn && ads->iflags & adns_if_debug)
-      adns__lprintf(ads,"adns: no nameservers, using localhost\n");
-    ia.s_addr= htonl(INADDR_LOOPBACK);
-    addserver(ads,ia);
+      adns__lprintf(ads,"adns: no nameservers, using IPv4 localhost\n");
+    memset(&sin, 0, sizeof(sin));
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(DNS_PORT);
+    sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    addserver(ads,(struct sockaddr *)&sin, sizeof(sin));
   }
 
+  /* we can't cope with multiple transport address families yet */
+  for (i=0; i<ads->nservers; i++)
+    assert(ads->servers[i].addr.sa.sa_family==AF_INET);
+
   proto= getprotobyname("udp"); if (!proto) { r= ENOPROTOOPT; goto x_free; }
   ads->udpsocket= socket(AF_INET,SOCK_DGRAM,proto->p_proto);
   if (ads->udpsocket<0) { r= errno; goto x_free; }
index 8839895511521c722f7775ca785e447c7668ef3c..67a55b42a4d4328a9d24daf3faf26eccb6dd3d05 100644 (file)
@@ -243,9 +243,9 @@ static void query_usetcp(adns_query qu, struct timeval now) {
 }
 
 void adns__query_send(adns_query qu, struct timeval now) {
-  struct sockaddr_in servaddr;
   int serv, r;
   adns_state ads;
+  adns_rr_addr *addr;
 
   assert(qu->state == query_tosend);
   if ((qu->flags & adns_qf_usevc) || (qu->query_dglen > DNS_MAXUDP)) {
@@ -258,16 +258,12 @@ void adns__query_send(adns_query qu, struct timeval now) {
     return;
   }
 
-  serv= qu->udpnextserver;
-  memset(&servaddr,0,sizeof(servaddr));
-
   ads= qu->ads;
-  servaddr.sin_family= AF_INET;
-  servaddr.sin_addr= ads->servers[serv].addr;
-  servaddr.sin_port= htons(DNS_PORT);
+  serv= qu->udpnextserver;
+  addr= &ads->servers[serv];
   
   r= sendto(ads->udpsocket,qu->query_dgram,qu->query_dglen,0,
-           (const struct sockaddr*)&servaddr,sizeof(servaddr));
+           &addr->addr.sa,addr->len);
   if (r<0 && errno == EMSGSIZE) {
     qu->retries= 0;
     query_usetcp(qu,now);
index 606435b96df769f4037eaf3a04d41088b63557db..431fe19a58a4f2eca133a05c09ef9ec1b5f75441 100644 (file)
@@ -47,8 +47,9 @@
  * _intstr                    (mf,csp,cs)
  * _manyistr                  (mf,cs)
  * _txt                       (pa)
- * _inaddr                    (pa,dip,di,cs +search_sortlist)
- * _addr                      (pa,di,div,csp,cs,gsz)
+ * _inaddr                    (pa,di,cs +search_sortlist, dip_genaddr)
+ * _addr                      (pa,di,div,csp,cs,gsz
+ *                             +search_sortlist_sa, dip_sockaddr)
  * _domain                    (pap,csp,cs)
  * _dom_raw                  (pa)
  * _host_raw                  (pa)
@@ -243,7 +244,7 @@ static adns_status cs_hinfo(vbuf *vb, const void *datap) {
 }
 
 /*
- * _inaddr   (pa,dip,di,cs +search_sortlist)
+ * _inaddr   (pa,di,cs +search_sortlist, dip_genaddr)
  */
 
 static adns_status pa_inaddr(const parseinfo *pai, int cbyte,
@@ -255,32 +256,34 @@ static adns_status pa_inaddr(const parseinfo *pai, int cbyte,
   return adns_s_ok;
 }
 
-static int search_sortlist(adns_state ads, struct in_addr ad) {
+static int search_sortlist(adns_state ads, int af, const void *ad) {
   const struct sortlist *slp;
+  const struct in_addr *a4;
   int i;
   
+  assert(af==AF_INET);
+  a4= ad;
   for (i=0, slp=ads->sortlist;
        i<ads->nsortlist &&
-        !((ad.s_addr & slp->mask.s_addr) == slp->base.s_addr);
+        (assert(slp->af==AF_INET),
+         !((a4->s_addr & slp->mask.v4.s_addr) == slp->base.v4.s_addr));
        i++, slp++);
   return i;
 }
 
-static int dip_inaddr(adns_state ads, struct in_addr a, struct in_addr b) {
+static int dip_genaddr(adns_state ads, int af, const void *a, const void *b) {
   int ai, bi;
   
   if (!ads->nsortlist) return 0;
 
-  ai= search_sortlist(ads,a);
-  bi= search_sortlist(ads,b);
+  ai= search_sortlist(ads,af,a);
+  bi= search_sortlist(ads,af,b);
   return bi<ai;
 }
 
 static int di_inaddr(adns_state ads,
                     const void *datap_a, const void *datap_b) {
-  const struct in_addr *ap= datap_a, *bp= datap_b;
-
-  return dip_inaddr(ads,*ap,*bp);
+  return dip_genaddr(ads,AF_INET,datap_a,datap_b);
 }
 
 static adns_status cs_inaddr(vbuf *vb, const void *datap) {
@@ -293,7 +296,7 @@ static adns_status cs_inaddr(vbuf *vb, const void *datap) {
 }
 
 /*
- * _addr   (pa,di,div,csp,cs,gsz)
+ * _addr   (pa,di,div,csp,cs,gsz +search_sortlist_sa, dip_sockaddr)
  */
 
 static adns_status pa_addr(const parseinfo *pai, int cbyte,
@@ -309,11 +312,21 @@ static adns_status pa_addr(const parseinfo *pai, int cbyte,
   return adns_s_ok;
 }
 
+static int search_sortlist_sa(adns_state ads, const struct sockaddr *sa) {
+  assert(sa->sa_family == AF_INET);
+  return search_sortlist(ads, sa->sa_family,
+                        &((const struct sockaddr_in *)sa)->sin_addr);
+}
+static int dip_sockaddr(adns_state ads,
+                       const struct sockaddr *sa,
+                       const struct sockaddr *sb) {
+  if (!ads->sortlist) return 0;
+  return search_sortlist_sa(ads, sa) > search_sortlist_sa(ads, sb);
+}
+
 static int di_addr(adns_state ads, const void *datap_a, const void *datap_b) {
   const adns_rr_addr *ap= datap_a, *bp= datap_b;
-
-  assert(ap->addr.sa.sa_family == AF_INET);
-  return dip_inaddr(ads, ap->addr.inet.sin_addr, bp->addr.inet.sin_addr);
+  return dip_sockaddr(ads, &ap->addr.sa, &bp->addr.sa);
 }
 
 static int div_addr(void *context, const void *datap_a, const void *datap_b) {
@@ -552,11 +565,7 @@ static int dip_hostaddr(adns_state ads,
   if (ap->astatus != bp->astatus) return ap->astatus;
   if (ap->astatus) return 0;
 
-  assert(ap->addrs[0].addr.sa.sa_family == AF_INET);
-  assert(bp->addrs[0].addr.sa.sa_family == AF_INET);
-  return dip_inaddr(ads,
-                   ap->addrs[0].addr.inet.sin_addr,
-                   bp->addrs[0].addr.inet.sin_addr);
+  return dip_sockaddr(ads, &ap->addrs[0].addr.sa, &bp->addrs[0].addr.sa);
 }
 
 static int di_hostaddr(adns_state ads,
@@ -739,7 +748,8 @@ static adns_status ckl_ptr(adns_state ads, adns_queryflags flags,
     if (lablen != l || memcmp(label, ed, l)) return adns_s_querydomainwrong;
   } else {
     if (lablen) return adns_s_querydomainwrong;
-    ctx->tinfo.ptr.addr.s_addr=
+    ctx->tinfo.ptr.addr.af= AF_INET;
+    ctx->tinfo.ptr.addr.addr.v4.s_addr=
       htonl((cls->ptr.ipv[0]<<24) | (cls->ptr.ipv[1]<<16) |
            (cls->ptr.ipv[2]<< 8) | (cls->ptr.ipv[3]));
   }
@@ -748,7 +758,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 in_addr *queried;
+  const struct af_addr *queried;
   const unsigned char *found;
   adns_state ads= parent->ads;
   int i;
@@ -762,8 +772,10 @@ static void icb_ptr(adns_query parent, adns_query child) {
   }
 
   queried= &parent->ctx.tinfo.ptr.addr;
+  assert(queried->af == AF_INET);
+  assert(cans->type == adns_r_a);
   for (i=0, found=cans->rrs.bytes; i<cans->nrrs; i++, found+=cans->rrsz) {
-    if (!memcmp(queried,found,cans->rrsz)) {
+    if (queried->addr.v4.s_addr == ((const struct in_addr *)found)->s_addr) {
       if (!parent->children.head) {
        adns__query_done(parent);
        return;