chiark / gitweb /
src/adns.h, src/types.c: Now adns_rr_addr can hold a sockaddr_in6.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 1 Jun 2014 00:20:47 +0000 (01:20 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 12 Oct 2014 19:39:46 +0000 (20:39 +0100)
This uses the recently introduced variable-size record structure
machinery so that only clients compiled against the new header file see
the larger record structure.

Note that we don't even try to actually do lookups for IPv6 addresses.
That will come later on.  This is just about sorting out the binary
interface.

Arrange that regress/case-brokenmail.sys asks for the correct record
size, because otherwise the answers get printed out wrongly.

[ I have done git-grep sizeof on a version of the head of this series
and found no un-corrected uses of sizeof(adns_rr_addr) -iwj. ]

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
regress/case-brokenmail.sys
regress/case-rr_addr-binary-compat.err [new file with mode: 0644]
regress/case-rr_addr-binary-compat.out [new file with mode: 0644]
regress/case-rr_addr-binary-compat.sys [new file with mode: 0644]
regress/init-distorted.text [new file with mode: 0644]
src/adns.h
src/types.c

index 14f4575..706fa65 100644 (file)
@@ -1,5 +1,5 @@
 adnstest default
-:15,65551 broken-mail.test.iwj.relativity.greenend.org.uk. 256/broken-mail.test.iwj.relativity.greenend.org.uk. 0x104/broken-mail.test.iwj.relativity.greenend.org.uk.
+:15,16842767 broken-mail.test.iwj.relativity.greenend.org.uk. 256/broken-mail.test.iwj.relativity.greenend.org.uk. 0x104/broken-mail.test.iwj.relativity.greenend.org.uk.
  start 934726868.117908
  socket type=SOCK_DGRAM
  socket=4
diff --git a/regress/case-rr_addr-binary-compat.err b/regress/case-rr_addr-binary-compat.err
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/regress/case-rr_addr-binary-compat.out b/regress/case-rr_addr-binary-compat.out
new file mode 100644 (file)
index 0000000..89cccbb
--- /dev/null
@@ -0,0 +1,18 @@
+adns debug: using nameserver 172.29.199.224
+maddr.dnserr.distorted.org.uk flags 0 type 65537 A(addr) submitted
+maddr.dnserr.distorted.org.uk flags 0 type 65537 A(addr) submitted
+maddr.dnserr.distorted.org.uk flags 0 type A(addr): OK; nrrs=6; cname=$; owner=$; ttl=14400
+ INET 198.51.100.2
+ INET 198.51.100.1
+ INET 203.0.113.1
+ INET 203.0.113.2
+ INET 192.0.2.1
+ INET 192.0.2.2
+maddr.dnserr.distorted.org.uk flags 0 type A(addr): OK; nrrs=6; cname=$; owner=$; ttl=14400
+ INET 198.51.100.1
+ INET 198.51.100.2
+ INET 203.0.113.1
+ INET 203.0.113.2
+ INET 192.0.2.1
+ INET 192.0.2.2
+rc=0
diff --git a/regress/case-rr_addr-binary-compat.sys b/regress/case-rr_addr-binary-compat.sys
new file mode 100644 (file)
index 0000000..9fe95c8
--- /dev/null
@@ -0,0 +1,63 @@
+./adnstest distorted
+:16842753,65537 maddr.dnserr.distorted.org.uk
+ start 1402443258.469312
+ socket type=SOCK_DGRAM
+ socket=6
+ +0.000064
+ fcntl fd=6 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000035
+ fcntl fd=6 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000027
+ sendto fd=6 addr=172.29.199.224:53
+     31200100 00010000 00000000 056d6164 64720664 6e736572 72096469 73746f72
+     74656403 6f726702 756b0000 010001.
+ sendto=47
+ +0.000405
+ sendto fd=6 addr=172.29.199.224:53
+     31220100 00010000 00000000 056d6164 64720664 6e736572 72096469 73746f72
+     74656403 6f726702 756b0000 010001.
+ sendto=47
+ +0.000308
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999287
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.001781
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     31208580 00010006 00040008 056d6164 64720664 6e736572 72096469 73746f72
+     74656403 6f726702 756b0000 010001c0 0c000100 01000038 400004c6 336402c0
+     0c000100 01000038 400004cb 007101c0 0c000100 01000038 400004cb 007102c0
+     0c000100 01000038 400004c0 000201c0 0c000100 01000038 400004c0 000202c0
+     0c000100 01000038 400004c6 336401c0 12000200 01000038 40000c06 72616469
+     7573026e 73c012c0 12000200 01000038 40000a07 76616d70 697265c0 a2c01200
+     02000100 00384000 0d0a7465 6c656361 73746572 c0a2c012 00020001 00003840
+     000c0970 72656369 73696f6e c0a2c09b 00010001 00003840 00043e31 cc92c09b
+     001c0001 00003840 00102001 04701f09 1b980000 00000000 0002c0b3 00010001
+     00003840 00043e31 cc96c0b3 001c0001 00003840 00102001 04701f09 1b980000
+     00000000 0006c0e2 00010001 00003840 0004d40d c646c0e2 001c0001 00003840
+     00102001 0ba80000 01d90000 00000000 0006c0c9 00010001 00003840 0004d40d
+     c647c0c9 001c0001 00003840 00102001 0ba80000 01d90000 00000000 0007.
+ +0.000411
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     31228580 00010006 00040008 056d6164 64720664 6e736572 72096469 73746f72
+     74656403 6f726702 756b0000 010001c0 0c000100 01000038 400004cb 007101c0
+     0c000100 01000038 400004cb 007102c0 0c000100 01000038 400004c0 000201c0
+     0c000100 01000038 400004c0 000202c0 0c000100 01000038 400004c6 336401c0
+     0c000100 01000038 400004c6 336402c0 12000200 01000038 40000c06 72616469
+     7573026e 73c012c0 12000200 01000038 40000c09 70726563 6973696f 6ec0a2c0
+     12000200 01000038 40000a07 76616d70 697265c0 a2c01200 02000100 00384000
+     0d0a7465 6c656361 73746572 c0a2c09b 00010001 00003840 00043e31 cc92c09b
+     001c0001 00003840 00102001 04701f09 1b980000 00000000 0002c0cb 00010001
+     00003840 00043e31 cc96c0cb 001c0001 00003840 00102001 04701f09 1b980000
+     00000000 0006c0b3 00010001 00003840 0004d40d c646c0b3 001c0001 00003840
+     00102001 0ba80000 01d90000 00000000 0006c0e1 00010001 00003840 0004d40d
+     c647c0e1 001c0001 00003840 00102001 0ba80000 01d90000 00000000 0007.
+ +0.000482
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000103
+ close fd=6
+ close=OK
+ +0.001487
diff --git a/regress/init-distorted.text b/regress/init-distorted.text
new file mode 100644 (file)
index 0000000..3d99050
--- /dev/null
@@ -0,0 +1,3 @@
+nameserver 172.29.199.224
+sortlist 198.51.100.0/24 0/0
+search dnserr.distorted.org.uk distorted.org.uk
index 578545c..2c03416 100644 (file)
@@ -107,9 +107,14 @@ typedef enum { /* In general, or together the desired flags: */
 typedef enum {
  adns_rrt_typemask=  0x0ffff,
  adns_rrt_reprmask= 0xffffff,
- adns__qtf_deref=    0x10000,/* dereference domains; perhaps get extra data */
+ adns__qtf_deref_bit=0x10000,/* internal version of ..._deref below */
  adns__qtf_mail822=  0x20000,/* return mailboxes in RFC822 rcpt field fmt   */
 
+ adns__qtf_bigaddr=0x1000000,/* use the new larger sockaddr union */
+
+ adns__qtf_deref=    adns__qtf_deref_bit|adns__qtf_bigaddr
+                           ,/* dereference domains; perhaps get extra data */
+
  adns_r_unknown=     0x40000,
    /* To use this, ask for records of type   <rr-type-code>|adns_r_unknown.
     * adns will not process the RDATA - you'll get adns_rr_byteblocks,
@@ -283,15 +288,30 @@ typedef enum {
  
 } adns_status;
 
+typedef union {
+  struct sockaddr sa;
+  struct sockaddr_in inet;
+} adns_sockaddr_v4only;
+
+typedef union {
+  struct sockaddr sa;
+  struct sockaddr_in inet;
+  struct sockaddr_in6 inet6;
+} adns_sockaddr;
+
 typedef struct {
   int len;
-  union {
-    struct sockaddr sa;
-    struct sockaddr_in inet;
-  } addr;
+  adns_sockaddr addr;
 } adns_rr_addr;
 
 typedef struct {
+  /* the old v4-only structure; handy if you have complicated binary
+   * compatibility problems. */
+  int len;
+  adns_sockaddr_v4only addr;
+} adns_rr_addr_v4only;
+
+typedef struct {
   char *host;
   adns_status astatus;
   int naddrs; /* temp fail => -1, perm fail => 0, s_ok => >0 */
index f4a2539..606435b 100644 (file)
@@ -48,7 +48,7 @@
  * _manyistr                  (mf,cs)
  * _txt                       (pa)
  * _inaddr                    (pa,dip,di,cs +search_sortlist)
- * _addr                      (pa,di,div,csp,cs)
+ * _addr                      (pa,di,div,csp,cs,gsz)
  * _domain                    (pap,csp,cs)
  * _dom_raw                  (pa)
  * _host_raw                  (pa)
@@ -80,6 +80,7 @@
  *    mf_*
  *    csp_*
  *    cs_*
+ *    gsz_*
  *    postsort_*
  */
 
@@ -292,7 +293,7 @@ static adns_status cs_inaddr(vbuf *vb, const void *datap) {
 }
 
 /*
- * _addr   (pa,di,div,csp,cs)
+ * _addr   (pa,di,div,csp,cs,gsz)
  */
 
 static adns_status pa_addr(const parseinfo *pai, int cbyte,
@@ -345,6 +346,11 @@ static adns_status cs_addr(vbuf *vb, const void *datap) {
   return csp_addr(vb,rrp);
 }
 
+static int gsz_addr(const typeinfo *typei, adns_rrtype type) {
+  return type & adns__qtf_bigaddr ?
+    sizeof(adns_rr_addr) : sizeof(adns_rr_addr_v4only);
+}
+
 /*
  * _domain      (pap,csp,cs)
  * _dom_raw     (pa)
@@ -415,6 +421,7 @@ static adns_status pa_host_raw(const parseinfo *pai, int cbyte,
  */
 
 static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
+                                size_t addrsz,
                                 int *cbyte_io, int count, int dmstart) {
   int rri, naddrs;
   int type, class, rdlen, rdstart, ownermatched;
@@ -433,22 +440,21 @@ static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha,
     if (naddrs == -1) {
       naddrs= 0;
     }
-    if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*sizeof(adns_rr_addr)))
+    if (!adns__vbuf_ensure(&pai->qu->vb, (naddrs+1)*addrsz))
       R_NOMEM;
     adns__update_expires(pai->qu,ttl,pai->now);
-    st= pa_addr(pai, rdstart,rdstart+rdlen,
-               pai->qu->vb.buf + naddrs*sizeof(adns_rr_addr));
+    st= pa_addr(pai, rdstart,rdstart+rdlen, pai->qu->vb.buf + naddrs*addrsz);
     if (st) return st;
     naddrs++;
   }
   if (naddrs >= 0) {
-    ha->addrs= adns__alloc_interim(pai->qu, naddrs*sizeof(adns_rr_addr));
+    ha->addrs= adns__alloc_interim(pai->qu, naddrs*addrsz);
     if (!ha->addrs) R_NOMEM;
-    memcpy(ha->addrs, pai->qu->vb.buf, naddrs*sizeof(adns_rr_addr));
+    memcpy(ha->addrs, pai->qu->vb.buf, naddrs*addrsz);
     ha->naddrs= naddrs;
     ha->astatus= adns_s_ok;
 
-    adns__isort(ha->addrs, naddrs, sizeof(adns_rr_addr), pai->qu->vb.buf,
+    adns__isort(ha->addrs, naddrs, addrsz, pai->qu->vb.buf,
                div_addr, pai->ads);
   }
   return adns_s_ok;
@@ -459,13 +465,13 @@ static void icb_hostaddr(adns_query parent, adns_query child) {
   adns_rr_hostaddr *rrp= child->ctx.pinfo.hostaddr;
   adns_state ads= parent->ads;
   adns_status st;
+  size_t addrsz= gsz_addr(0, parent->answer->type);
 
   st= cans->status;
   rrp->astatus= st;
   rrp->naddrs= (st>0 && st<=adns_s_max_tempfail) ? -1 : cans->nrrs;
   rrp->addrs= cans->rrs.addr;
-  adns__transfer_interim(child, parent, rrp->addrs,
-                        rrp->naddrs*sizeof(adns_rr_addr));
+  adns__transfer_interim(child, parent, rrp->addrs, rrp->naddrs*addrsz);
 
   if (parent->children.head) {
     LIST_LINK_TAIL(ads->childw,parent);
@@ -482,6 +488,7 @@ static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
   int id;
   adns_query nqu;
   adns_queryflags nflags;
+  size_t addrsz= gsz_addr(0, pai->qu->answer->type);
 
   dmstart= cbyte= *cbyte_io;
   st= pap_domain(pai, &cbyte, max, &rrp->host,
@@ -495,11 +502,11 @@ static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
 
   cbyte= pai->nsstart;
 
-  st= pap_findaddrs(pai, rrp, &cbyte, pai->nscount, dmstart);
+  st= pap_findaddrs(pai, rrp,addrsz, &cbyte, pai->nscount, dmstart);
   if (st) return st;
   if (rrp->naddrs != -1) return adns_s_ok;
 
-  st= pap_findaddrs(pai, rrp, &cbyte, pai->arcount, dmstart);
+  st= pap_findaddrs(pai, rrp,addrsz, &cbyte, pai->arcount, dmstart);
   if (st) return st;
   if (rrp->naddrs != -1) return adns_s_ok;
 
@@ -561,10 +568,11 @@ static int di_hostaddr(adns_state ads,
 
 static void mfp_hostaddr(adns_query qu, adns_rr_hostaddr *rrp) {
   void *tablev;
+  size_t addrsz= gsz_addr(0, qu->answer->type);
 
   adns__makefinal_str(qu,&rrp->host);
   tablev= rrp->addrs;
-  adns__makefinal_block(qu, &tablev, rrp->naddrs*sizeof(*rrp->addrs));
+  adns__makefinal_block(qu, &tablev, rrp->naddrs*addrsz);
   rrp->addrs= tablev;
 }
 
@@ -1251,7 +1259,8 @@ DEEP_TYPE(rp_raw, "RP",   "raw",strpair,   rp,      0,     rp              ),
 DEEP_TYPE(srv_raw,"SRV",  "raw",srvraw ,   srvraw,  srv,   srvraw,
                              .checklabel= ckl_srv, .postsort= postsort_srv),
 
-FLAT_TYPE(addr,   "A",  "addr", addr,      addr,    addr,  addr            ),
+FLAT_TYPE(addr,   "A",  "addr", addr,      addr,    addr,  addr,
+                                                        .getrrsz= gsz_addr),
 DEEP_TYPE(ns,     "NS", "+addr",hostaddr,  hostaddr,hostaddr,hostaddr      ),
 DEEP_TYPE(ptr,    "PTR","checked",str,     ptr,     0,     domain,
                                                       .checklabel= ckl_ptr),