X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Ftypes.c;h=754c237253d75f6628efac8c21029b20072546b2;hb=26e1c3d691b52d21a8bb52d9bf3f8e2b42ae6cfa;hp=5062c6a8a35964c6bbc712fc4d6831001d61523b;hpb=2140e71d5b1140845b45fbb2cb21f97d5e34c3dc;p=adns.git diff --git a/src/types.c b/src/types.c index 5062c6a..754c237 100644 --- a/src/types.c +++ b/src/types.c @@ -4,14 +4,14 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014 Ian Jackson * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology * (See the file INSTALL for full details.) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) + * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, @@ -20,8 +20,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program; if not, write to the Free Software Foundation. */ #include @@ -400,50 +399,46 @@ static unsigned addr_rrtypeflag(adns_rrtype type) { * adns__qf_addr_cname set so that we know that we're in the fixup state. */ -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; +static adns_status pap_addr(const parseinfo *pai, int in_rrty, size_t out_rrsz, + int *cbyte_io, int cbyte_max, adns_rr_addr *out) { + int in_addrlen; + int out_af, out_salen; struct in6_addr v6map; - const void *oaddr= dgram + *cbyte_io; - int avail= max - *cbyte_io; - int step= -1; - void *addrp= 0; - - 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; + + const void *use_addr= pai->dgram + *cbyte_io; + + switch (in_rrty) { + case adns_r_a: in_addrlen= 4; out_af= AF_INET; break; + case adns_r_aaaa: in_addrlen= 16; out_af= AF_INET6; break; + default: abort(); } - assert(addrp); - assert(offsetof(adns_rr_addr, addr) + salen <= rrsz); - if (addrlen < avail) return adns_s_invaliddata; - if (step < 0) step= addrlen; - *cbyte_io += step; - memset(&storeto->addr, 0, salen); - storeto->len= salen; - storeto->addr.sa.sa_family= af; - memcpy(addrp, oaddr, addrlen); + if ((*cbyte_io + in_addrlen) != cbyte_max) return adns_s_invaliddata; + if (out_af==AF_INET && + (pai->qu->flags & adns_qf_ipv6_mapv4) && + (pai->qu->answer->type & adns__qtf_bigaddr)) { + memset(v6map.s6_addr + 0, 0x00, 10); + memset(v6map.s6_addr + 10, 0xff, 2); + memcpy(v6map.s6_addr + 12, use_addr, 4); + use_addr= v6map.s6_addr; + out_af= AF_INET6; + } + + switch (out_af) { + case AF_INET: out_salen= sizeof(out->addr.inet); break; + case AF_INET6: out_salen= sizeof(out->addr.inet6); break; + default: abort(); + } + + assert(offsetof(adns_rr_addr, addr) + out_salen <= out_rrsz); + + memset(&out->addr, 0, out_salen); + out->len= out_salen; + out->addr.sa.sa_family= out_af; + adns__addr_inject(use_addr, &out->addr); + + *cbyte_io += in_addrlen; return adns_s_ok; } @@ -583,11 +578,11 @@ static adns_status addr_submit(adns_query parent, adns_query *query_r, * available record types. The memory management and callback rules are * the same as for adns__internal_submit. * - * Some differences: the query is linked onto the parent's children list - * before exit (though the parent's state is not changed, and it is not - * linked into the childw list queue); and we fiddle with the `tinfo' - * portion of the context structure (yes, modifying *ctx), since this is, - * in fact, the main purpose of this function. + * Some differences: the query is linked onto the parent's children + * list before exit (though the parent's state is not changed, and + * it is not linked into the childw list queue); and we set the + * `tinfo' portion of the context structure (yes, modifying *ctx), + * since this is, in fact, the main purpose of this function. */ adns_state ads= parent->ads; @@ -654,7 +649,7 @@ static void icb_addr(adns_query parent, adns_query child) { struct timeval now; adns_status err; adns_queryflags qf; - int id; + int id, r; propagate_ttl(parent, child); @@ -695,7 +690,7 @@ static void icb_addr(adns_query parent, adns_query child) { * settled on. */ adns__cancel_children(parent); - if (gettimeofday(&now, 0)) goto x_gtod; + r= gettimeofday(&now, 0); if (r) goto x_gtod; qf= adns__qf_addr_cname; if (!(parent->flags & adns_qf_cname_loose)) qf |= adns_qf_cname_forbid; addr_subqueries(parent, now, qf, child->vb.buf, child->vb.used); @@ -716,7 +711,7 @@ static void icb_addr(adns_query parent, adns_query child) { adns__cancel_children(parent); adns__free_interim(parent, pans->rrs.bytes); pans->rrs.bytes= 0; pans->nrrs= 0; - if (gettimeofday(&now, 0)) goto x_gtod; + r= gettimeofday(&now, 0); if (r) goto x_gtod; adns__search_next(ads, parent, now); return; } @@ -738,6 +733,9 @@ static void icb_addr(adns_query parent, adns_query child) { return; x_gtod: + /* We have our own error handling, because adns__must_gettimeofday + * handles errors by calling adns_globalsystemfailure, which would + * reenter the query processing logic. */ adns__diag(ads, -1, parent, "gettimeofday failed: %s", strerror(errno)); err= adns_s_systemfail; goto x_err;