summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Wooding <mdw@distorted.org.uk>2014-06-11 00:33:00 +0100
committerIan Jackson <ijackson@chiark.greenend.org.uk>2014-10-19 21:09:57 +0100
commitcdf51ff0be2d71b61dec430d08c985f20cc5dffd (patch)
treeaaa00c0aa8ac078d770fa20aa1b08745c6b30b87 /src
parent2ca5496dfc95d6e40596d9f1d83929cc5a3bc495 (diff)
Support v6-mapping IPv4 addresses found doing addr lookups.
Not available if the client doesn't have the larger adns_rr_addr structure. Signed-off-by: Mark Wooding <mdw@distorted.org.uk> Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Diffstat (limited to 'src')
-rw-r--r--src/adns.h1
-rw-r--r--src/types.c19
2 files changed, 19 insertions, 1 deletions
diff --git a/src/adns.h b/src/adns.h
index 2458333..7d78bf7 100644
--- a/src/adns.h
+++ b/src/adns.h
@@ -102,6 +102,7 @@ typedef enum { /* In general, or together the desired flags: */
adns_qf_quotefail_cname=0x00000080,/* refuse if quote-req chars in CNAME we go via */
adns_qf_cname_loose= 0x00000100,/* allow refs to CNAMEs - without, get _s_cname */
adns_qf_cname_forbid= 0x00000200,/* don't follow CNAMEs, instead give _s_cname */
+ adns_qf_ipv6_mapv4= 0x00001000,/* ... return IPv4 addresses as v6-mapped */
adns_qf_addrlit_scope_forbid=0x00002000,/* forbid %<scope> in IPv6 literals */
adns_qf_addrlit_scope_numeric=0x00004000,/* %<scope> may only be numeric */
adns_qf_addrlit_ipv4_quadonly=0x00008000,/* reject non-dotted-quad ipv4 */
diff --git a/src/types.c b/src/types.c
index 29e16ad..d4693c2 100644
--- a/src/types.c
+++ b/src/types.c
@@ -382,6 +382,7 @@ static adns_status pap_addr(const parseinfo *pai, int rrty, size_t rrsz,
int *cbyte_io, int max, adns_rr_addr *storeto) {
const byte *dgram= pai->dgram;
int af, addrlen, salen;
+ struct in6_addr v6map;
const void *oaddr= dgram + *cbyte_io;
int avail= max - *cbyte_io;
int step= -1;
@@ -389,10 +390,26 @@ static adns_status pap_addr(const parseinfo *pai, int rrty, size_t rrsz,
switch (rrty) {
case adns_r_a:
+ if ((pai->qu->flags & adns_qf_ipv6_mapv4) &&
+ (pai->qu->answer->type & adns__qtf_bigaddr)) {
+ if (avail < 4) return adns_s_invaliddata;
+ memset(v6map.s6_addr + 0, 0x00, 10);
+ memset(v6map.s6_addr + 10, 0xff, 2);
+ memcpy(v6map.s6_addr + 12, oaddr, 4);
+ oaddr= v6map.s6_addr; avail= sizeof(v6map.s6_addr);
+ if (step < 0) step= 4;
+ goto aaaa;
+ }
af= AF_INET; addrlen= 4;
addrp= &storeto->addr.inet.sin_addr;
salen= sizeof(storeto->addr.inet);
break;
+ case adns_r_aaaa:
+ aaaa:
+ af= AF_INET6; addrlen= 16;
+ addrp= storeto->addr.inet6.sin6_addr.s6_addr;
+ salen= sizeof(storeto->addr.inet6);
+ break;
}
assert(addrp);
@@ -842,7 +859,7 @@ static adns_status pap_hostaddr(const parseinfo *pai, int *cbyte_io,
ctx.callback= icb_hostaddr;
ctx.pinfo.hostaddr= rrp;
- nflags= adns_qf_quoteok_query;
+ nflags= adns_qf_quoteok_query | (pai->qu->flags & adns_qf_ipv6_mapv4);
if (!(pai->qu->flags & adns_qf_cname_loose)) nflags |= adns_qf_cname_forbid;
st= addr_submit(pai->qu, &nqu, &pai->qu->vb, id, want,