summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Wooding <mdw@distorted.org.uk>2014-06-01 01:20:47 +0100
committerIan Jackson <ijackson@chiark.greenend.org.uk>2014-10-12 20:39:46 +0100
commitb0a32b1750b230df79eb2d515519197c133d7a16 (patch)
treecb6542cce6bba162950c3677a8269af98bfac998 /src
parentf7b93d15be71e4f18ae53763f93553a2e8ac0a45 (diff)
src/adns.h, src/types.c: Now adns_rr_addr can hold a sockaddr_in6.
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>
Diffstat (limited to 'src')
-rw-r--r--src/adns.h30
-rw-r--r--src/types.c37
2 files changed, 48 insertions, 19 deletions
diff --git a/src/adns.h b/src/adns.h
index 578545c..2c03416 100644
--- a/src/adns.h
+++ b/src/adns.h
@@ -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 */
diff --git a/src/types.c b/src/types.c
index f4a2539..606435b 100644
--- a/src/types.c
+++ b/src/types.c
@@ -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),