diff options
author | Stuart Henderson <sthen@cvs.openbsd.org> | 2017-02-17 18:53:33 +0000 |
---|---|---|
committer | Stuart Henderson <sthen@cvs.openbsd.org> | 2017-02-17 18:53:33 +0000 |
commit | 3d7e55155dd0acaba23dc19920091ee5580ad180 (patch) | |
tree | 128498ff1499e8cde628b28e9707636bd4d161a5 /usr.sbin/unbound/iterator | |
parent | 57a7719d7ee152a16a7ac027d83bcce25a6a46ac (diff) |
Update to unbound-1.6.1rc3 - thanks millert@ and Brad for tests.
Diffstat (limited to 'usr.sbin/unbound/iterator')
-rw-r--r-- | usr.sbin/unbound/iterator/iter_delegpt.c | 200 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_delegpt.h | 108 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_donotq.h | 22 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_fwd.c | 10 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_fwd.h | 68 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_hints.c | 6 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_hints.h | 49 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_priv.h | 30 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_scrub.c | 4 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iter_utils.c | 36 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iterator.c | 166 | ||||
-rw-r--r-- | usr.sbin/unbound/iterator/iterator.h | 4 |
12 files changed, 519 insertions, 184 deletions
diff --git a/usr.sbin/unbound/iterator/iter_delegpt.c b/usr.sbin/unbound/iterator/iter_delegpt.c index f49048d5c26..ecf88b293da 100644 --- a/usr.sbin/unbound/iterator/iter_delegpt.c +++ b/usr.sbin/unbound/iterator/iter_delegpt.c @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -47,6 +47,8 @@ #include "util/data/packed_rrset.h" #include "util/data/msgreply.h" #include "util/net_help.h" +#include "sldns/rrdef.h" +#include "sldns/sbuffer.h" struct delegpt* delegpt_create(struct regional* region) @@ -70,8 +72,9 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) return NULL; copy->bogus = dp->bogus; copy->has_parent_side_NS = dp->has_parent_side_NS; + copy->ssl_upstream = dp->ssl_upstream; for(ns = dp->nslist; ns; ns = ns->next) { - if(!delegpt_add_ns(copy, region, ns->name, (int)ns->lame)) + if(!delegpt_add_ns(copy, region, ns->name, ns->lame)) return NULL; copy->nslist->resolved = ns->resolved; copy->nslist->got4 = ns->got4; @@ -90,6 +93,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) int delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name) { + log_assert(!dp->dp_type_mlc); dp->namelabs = dname_count_size_labels(name, &dp->namelen); dp->name = regional_alloc_init(region, name, dp->namelen); return dp->name != 0; @@ -97,11 +101,12 @@ delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name) int delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, - int lame) + uint8_t lame) { struct delegpt_ns* ns; size_t len; (void)dname_count_size_labels(name, &len); + log_assert(!dp->dp_type_mlc); /* slow check for duplicates to avoid counting failures when * adding the same server as a dependency twice */ if(delegpt_find_ns(dp, name, len)) @@ -117,10 +122,10 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, ns->resolved = 0; ns->got4 = 0; ns->got6 = 0; - ns->lame = (uint8_t)lame; + ns->lame = lame; ns->done_pside4 = 0; ns->done_pside6 = 0; - return 1; + return ns->name != 0; } struct delegpt_ns* @@ -143,7 +148,9 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, { struct delegpt_addr* p = dp->target_list; while(p) { - if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0) { + if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0 + && ((struct sockaddr_in*)addr)->sin_port == + ((struct sockaddr_in*)&p->addr)->sin_port) { return p; } p = p->next_target; @@ -154,9 +161,10 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, int delegpt_add_target(struct delegpt* dp, struct regional* region, uint8_t* name, size_t namelen, struct sockaddr_storage* addr, - socklen_t addrlen, int bogus, int lame) + socklen_t addrlen, uint8_t bogus, uint8_t lame) { struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); + log_assert(!dp->dp_type_mlc); if(!ns) { /* ignore it */ return 1; @@ -173,10 +181,11 @@ delegpt_add_target(struct delegpt* dp, struct regional* region, int delegpt_add_addr(struct delegpt* dp, struct regional* region, - struct sockaddr_storage* addr, socklen_t addrlen, int bogus, - int lame) + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, + uint8_t lame) { struct delegpt_addr* a; + log_assert(!dp->dp_type_mlc); /* check for duplicates */ if((a = delegpt_find_addr(dp, addr, addrlen))) { if(bogus) @@ -200,6 +209,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region, a->attempts = 0; a->bogus = bogus; a->lame = lame; + a->dnsseclame = 0; return 1; } @@ -372,17 +382,18 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region) int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ns_rrset, int lame) + struct ub_packed_rrset_key* ns_rrset, uint8_t lame) { struct packed_rrset_data* nsdata = (struct packed_rrset_data*) ns_rrset->entry.data; size_t i; + log_assert(!dp->dp_type_mlc); if(nsdata->security == sec_status_bogus) dp->bogus = 1; for(i=0; i<nsdata->count; i++) { if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */ if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) != - (size_t)ldns_read_uint16(nsdata->rr_data[i])) + (size_t)sldns_read_uint16(nsdata->rr_data[i])) continue; /* bad format */ /* add rdata of NS (= wirefmt dname), skip rdatalen bytes */ if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame)) @@ -393,12 +404,13 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, int delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ak, int lame) + struct ub_packed_rrset_key* ak, uint8_t lame) { struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; size_t i; struct sockaddr_in sa; socklen_t len = (socklen_t)sizeof(sa); + log_assert(!dp->dp_type_mlc); memset(&sa, 0, len); sa.sin_family = AF_INET; sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); @@ -416,12 +428,13 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* ak, int lame) + struct ub_packed_rrset_key* ak, uint8_t lame) { struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; size_t i; struct sockaddr_in6 sa; socklen_t len = (socklen_t)sizeof(sa); + log_assert(!dp->dp_type_mlc); memset(&sa, 0, len); sa.sin6_family = AF_INET6; sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); @@ -439,7 +452,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, int delegpt_add_rrset(struct delegpt* dp, struct regional* region, - struct ub_packed_rrset_key* rrset, int lame) + struct ub_packed_rrset_key* rrset, uint8_t lame) { if(!rrset) return 1; @@ -492,3 +505,144 @@ void delegpt_no_ipv4(struct delegpt* dp) ns->resolved = 1; } } + +struct delegpt* delegpt_create_mlc(uint8_t* name) +{ + struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp)); + if(!dp) + return NULL; + dp->dp_type_mlc = 1; + if(name) { + dp->namelabs = dname_count_size_labels(name, &dp->namelen); + dp->name = memdup(name, dp->namelen); + if(!dp->name) { + free(dp); + return NULL; + } + } + return dp; +} + +void delegpt_free_mlc(struct delegpt* dp) +{ + struct delegpt_ns* n, *nn; + struct delegpt_addr* a, *na; + if(!dp) return; + log_assert(dp->dp_type_mlc); + n = dp->nslist; + while(n) { + nn = n->next; + free(n->name); + free(n); + n = nn; + } + a = dp->target_list; + while(a) { + na = a->next_target; + free(a); + a = na; + } + free(dp->name); + free(dp); +} + +int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name) +{ + log_assert(dp->dp_type_mlc); + dp->namelabs = dname_count_size_labels(name, &dp->namelen); + dp->name = memdup(name, dp->namelen); + return (dp->name != NULL); +} + +int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame) +{ + struct delegpt_ns* ns; + size_t len; + (void)dname_count_size_labels(name, &len); + log_assert(dp->dp_type_mlc); + /* slow check for duplicates to avoid counting failures when + * adding the same server as a dependency twice */ + if(delegpt_find_ns(dp, name, len)) + return 1; + ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns)); + if(!ns) + return 0; + ns->namelen = len; + ns->name = memdup(name, ns->namelen); + if(!ns->name) { + free(ns); + return 0; + } + ns->next = dp->nslist; + dp->nslist = ns; + ns->resolved = 0; + ns->got4 = 0; + ns->got6 = 0; + ns->lame = (uint8_t)lame; + ns->done_pside4 = 0; + ns->done_pside6 = 0; + return 1; +} + +int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t bogus, uint8_t lame) +{ + struct delegpt_addr* a; + log_assert(dp->dp_type_mlc); + /* check for duplicates */ + if((a = delegpt_find_addr(dp, addr, addrlen))) { + if(bogus) + a->bogus = bogus; + if(!lame) + a->lame = 0; + return 1; + } + + a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr)); + if(!a) + return 0; + a->next_target = dp->target_list; + dp->target_list = a; + a->next_result = 0; + a->next_usable = dp->usable_list; + dp->usable_list = a; + memcpy(&a->addr, addr, addrlen); + a->addrlen = addrlen; + a->attempts = 0; + a->bogus = bogus; + a->lame = lame; + a->dnsseclame = 0; + return 1; +} + +int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, + uint8_t lame) +{ + struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); + log_assert(dp->dp_type_mlc); + if(!ns) { + /* ignore it */ + return 1; + } + if(!lame) { + if(addr_is_ip6(addr, addrlen)) + ns->got6 = 1; + else ns->got4 = 1; + if(ns->got4 && ns->got6) + ns->resolved = 1; + } + return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame); +} + +size_t delegpt_get_mem(struct delegpt* dp) +{ + struct delegpt_ns* ns; + size_t s; + if(!dp) return 0; + s = sizeof(*dp) + dp->namelen + + delegpt_count_targets(dp)*sizeof(struct delegpt_addr); + for(ns=dp->nslist; ns; ns=ns->next) + s += sizeof(*ns)+ns->namelen; + return s; +} diff --git a/usr.sbin/unbound/iterator/iter_delegpt.h b/usr.sbin/unbound/iterator/iter_delegpt.h index c4ca62dc44d..4bd79c81af0 100644 --- a/usr.sbin/unbound/iterator/iter_delegpt.h +++ b/usr.sbin/unbound/iterator/iter_delegpt.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -79,6 +79,10 @@ struct delegpt { * Also true if the delegationpoint was created from a delegation * message and thus contains the parent-side-info already. */ uint8_t has_parent_side_NS; + /** for assertions on type of delegpt */ + uint8_t dp_type_mlc; + /** use SSL for upstream query */ + uint8_t ssl_upstream; }; /** @@ -138,9 +142,13 @@ struct delegpt_addr { int sel_rtt; /** if true, the A or AAAA RR was bogus, so this address is bad. * Also check the dp->bogus to see if everything is bogus. */ - int bogus; + uint8_t bogus; /** if true, this address is dispreferred: it is a lame IP address */ - int lame; + uint8_t lame; + /** if the address is dnsseclame, but this cannot be cached, this + * option is useful to mark the address dnsseclame. + * This value is not copied in addr-copy and dp-copy. */ + uint8_t dnsseclame; }; /** @@ -177,7 +185,7 @@ int delegpt_set_name(struct delegpt* dp, struct regional* regional, * @return false on error. */ int delegpt_add_ns(struct delegpt* dp, struct regional* regional, - uint8_t* name, int lame); + uint8_t* name, uint8_t lame); /** * Add NS rrset; calls add_ns repeatedly. @@ -188,7 +196,7 @@ int delegpt_add_ns(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* ns_rrset, int lame); + struct ub_packed_rrset_key* ns_rrset, uint8_t lame); /** * Add target address to the delegation point. @@ -205,7 +213,7 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional, */ int delegpt_add_target(struct delegpt* dp, struct regional* regional, uint8_t* name, size_t namelen, struct sockaddr_storage* addr, - socklen_t addrlen, int bogus, int lame); + socklen_t addrlen, uint8_t bogus, uint8_t lame); /** * Add A RRset to delegpt. @@ -216,7 +224,7 @@ int delegpt_add_target(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, int lame); + struct ub_packed_rrset_key* rrset, uint8_t lame); /** * Add AAAA RRset to delegpt. @@ -227,7 +235,7 @@ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, int lame); + struct ub_packed_rrset_key* rrset, uint8_t lame); /** * Add any RRset to delegpt. @@ -239,7 +247,7 @@ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, * @return 0 on alloc error. */ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, - struct ub_packed_rrset_key* rrset, int lame); + struct ub_packed_rrset_key* rrset, uint8_t lame); /** * Add address to the delegation point. No servername is associated or checked. @@ -252,7 +260,8 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, * @return false on error. */ int delegpt_add_addr(struct delegpt* dp, struct regional* regional, - struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int lame); + struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t bogus, uint8_t lame); /** * Find NS record in name list of delegation point. @@ -346,4 +355,65 @@ void delegpt_no_ipv6(struct delegpt* dp); */ void delegpt_no_ipv4(struct delegpt* dp); +/** + * create malloced delegation point, with the given name + * @param name: uncompressed wireformat of delegpt name. + * @return NULL on alloc failure + */ +struct delegpt* delegpt_create_mlc(uint8_t* name); + +/** + * free malloced delegation point. + * @param dp: must have been created with delegpt_create_mlc, free'd. + */ +void delegpt_free_mlc(struct delegpt* dp); + +/** + * Set name of delegation point. + * @param dp: delegation point. malloced. + * @param name: name to use. + * @return false on error. + */ +int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name); + +/** + * add a name to malloced delegation point. + * @param dp: must have been created with delegpt_create_mlc. + * @param name: the name to add. + * @param lame: the name is lame, disprefer. + * @return false on error. + */ +int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame); + +/** + * add an address to a malloced delegation point. + * @param dp: must have been created with delegpt_create_mlc. + * @param addr: the address. + * @param addrlen: the length of addr. + * @param bogus: if address is bogus. + * @param lame: if address is lame. + * @return false on error. + */ +int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t bogus, uint8_t lame); + +/** + * Add target address to the delegation point. + * @param dp: must have been created with delegpt_create_mlc. + * @param name: name for which target was found (must be in nslist). + * This name is marked resolved. + * @param namelen: length of name. + * @param addr: the address. + * @param addrlen: the length of addr. + * @param bogus: security status for the address, pass true if bogus. + * @param lame: address is lame. + * @return false on error. + */ +int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, + struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, + uint8_t lame); + +/** get memory in use by dp */ +size_t delegpt_get_mem(struct delegpt* dp); + #endif /* ITERATOR_ITER_DELEGPT_H */ diff --git a/usr.sbin/unbound/iterator/iter_donotq.h b/usr.sbin/unbound/iterator/iter_donotq.h index 4c4fcb289dc..14105073aa3 100644 --- a/usr.sbin/unbound/iterator/iter_donotq.h +++ b/usr.sbin/unbound/iterator/iter_donotq.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -58,7 +58,7 @@ struct iter_donotq { * contents of type addr_tree_node. Each node is an address span * that must not be used to send queries to. */ - rbtree_t tree; + rbtree_type tree; }; /** diff --git a/usr.sbin/unbound/iterator/iter_fwd.c b/usr.sbin/unbound/iterator/iter_fwd.c index 3e580ca3551..0ba6c6ddfa9 100644 --- a/usr.sbin/unbound/iterator/iter_fwd.c +++ b/usr.sbin/unbound/iterator/iter_fwd.c @@ -82,7 +82,7 @@ static void fwd_zone_free(struct iter_forward_zone* n) free(n); } -static void delfwdnode(rbnode_t* n, void* ATTR_UNUSED(arg)) +static void delfwdnode(rbnode_type* n, void* ATTR_UNUSED(arg)) { struct iter_forward_zone* node = (struct iter_forward_zone*)n; fwd_zone_free(node); @@ -265,6 +265,8 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg) * last resort will ask for parent-side NS record and thus * fallback to the internet name servers on a failure */ dp->has_parent_side_NS = (uint8_t)!s->isfirst; + /* use SSL for queries to this forwarder */ + dp->ssl_upstream = (uint8_t)s->ssl_upstream; verbose(VERB_QUERY, "Forward zone server list:"); delegpt_log(VERB_QUERY, dp); if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp)) @@ -330,7 +332,7 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg) struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) { - rbnode_t* res = NULL; + rbnode_type* res = NULL; struct iter_forward_zone key; key.node.key = &key; key.dclass = qclass; @@ -345,7 +347,7 @@ struct delegpt* forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass) { /* lookup the forward zone in the tree */ - rbnode_t* res = NULL; + rbnode_type* res = NULL; struct iter_forward_zone *result; struct iter_forward_zone key; key.node.key = &key; @@ -386,7 +388,7 @@ int forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass) { struct iter_forward_zone key; - rbnode_t* n; + rbnode_type* n; struct iter_forward_zone* p; if(*dclass == 0) { /* first root item is first item in tree */ diff --git a/usr.sbin/unbound/iterator/iter_fwd.h b/usr.sbin/unbound/iterator/iter_fwd.h index 8f3bc1fa2f2..e90b74c16a5 100644 --- a/usr.sbin/unbound/iterator/iter_fwd.h +++ b/usr.sbin/unbound/iterator/iter_fwd.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -45,14 +45,11 @@ #include "util/rbtree.h" struct config_file; struct delegpt; -struct regional; /** * Iterator forward zones structure */ struct iter_forwards { - /** regional where forward zone server addresses are allocated */ - struct regional* region; /** * Zones are stored in this tree. Sort order is specially chosen. * first sorted on qclass. Then on dname in nsec-like order, so that @@ -60,7 +57,7 @@ struct iter_forwards { * match which gives the ancestor needed. * contents of type iter_forward_zone. */ - rbtree_t* tree; + rbtree_type* tree; }; /** @@ -68,7 +65,7 @@ struct iter_forwards { */ struct iter_forward_zone { /** redblacktree node, key is this structure: class and name */ - rbnode_t node; + rbnode_type node; /** name */ uint8_t* name; /** length of name */ @@ -77,7 +74,9 @@ struct iter_forward_zone { int namelabs; /** delegation point with forward server information for this zone. * If NULL then this forward entry is used to indicate that a - * stub-zone with the same name exists, and should be used. */ + * stub-zone with the same name exists, and should be used. + * This delegation point is malloced. + */ struct delegpt* dp; /** pointer to parent in tree (or NULL if none) */ struct iter_forward_zone* parent; @@ -106,6 +105,16 @@ void forwards_delete(struct iter_forwards* fwd); int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg); /** + * Find forward zone exactly by name + * @param fwd: forward storage. + * @param qname: The qname of the query. + * @param qclass: The qclass of the query. + * @return: A delegation point or null. + */ +struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname, + uint16_t qclass); + +/** * Find forward zone information * For this qname/qclass find forward zone information, returns delegation * point with server names and addresses, or NULL if no forwarding is needed. @@ -152,9 +161,7 @@ int fwd_cmp(const void* k1, const void* k2); * @param fwd: the forward data structure * @param c: class of zone * @param dp: delegation point with name and target nameservers for new - * forward zone. This delegation point and all its data must be - * malloced in the fwd->region. (then it is freed when the fwd is - * deleted). + * forward zone. malloced. * @return false on failure (out of memory); */ int forwards_add_zone(struct iter_forwards* fwd, uint16_t c, @@ -162,12 +169,31 @@ int forwards_add_zone(struct iter_forwards* fwd, uint16_t c, /** * Remove zone from forward structure. For external use since it - * recalcs the tree parents. Does not actually release any memory, the region - * is unchanged. + * recalcs the tree parents. * @param fwd: the forward data structure * @param c: class of zone * @param nm: name of zone (in uncompressed wireformat). */ void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm); +/** + * Add stub hole (empty entry in forward table, that makes resolution skip + * a forward-zone because the stub zone should override the forward zone). + * Does not add one if not necessary. + * @param fwd: the forward data structure + * @param c: class of zone + * @param nm: name of zone (in uncompressed wireformat). + * @return false on failure (out of memory); + */ +int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm); + +/** + * Remove stub hole, if one exists. + * @param fwd: the forward data structure + * @param c: class of zone + * @param nm: name of zone (in uncompressed wireformat). + */ +void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, + uint8_t* nm); + #endif /* ITERATOR_ITER_FWD_H */ diff --git a/usr.sbin/unbound/iterator/iter_hints.c b/usr.sbin/unbound/iterator/iter_hints.c index 217dfa2578b..74869d35547 100644 --- a/usr.sbin/unbound/iterator/iter_hints.c +++ b/usr.sbin/unbound/iterator/iter_hints.c @@ -67,7 +67,7 @@ static void hints_stub_free(struct iter_hints_stub* s) free(s); } -static void delhintnode(rbnode_t* n, void* ATTR_UNUSED(arg)) +static void delhintnode(rbnode_type* n, void* ATTR_UNUSED(arg)) { struct iter_hints_stub* node = (struct iter_hints_stub*)n; hints_stub_free(node); @@ -147,7 +147,9 @@ compile_time_root_prime(int do_ip4, int do_ip6) if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:84::b")) goto failed; if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed; if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed; + if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed; if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed; + if(!ah(dp, "G.ROOT-SERVERS.NET.", "2001:500:12::d0d")) goto failed; if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::53")) goto failed; if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed; if(!ah(dp, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) goto failed; @@ -274,6 +276,8 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg) * last resort will ask for parent-side NS record and thus * fallback to the internet name servers on a failure */ dp->has_parent_side_NS = (uint8_t)!s->isfirst; + /* ssl_upstream */ + dp->ssl_upstream = (uint8_t)s->ssl_upstream; delegpt_log(VERB_QUERY, dp); if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime)) return 0; diff --git a/usr.sbin/unbound/iterator/iter_hints.h b/usr.sbin/unbound/iterator/iter_hints.h index 4540971b0a4..06b4b9667d1 100644 --- a/usr.sbin/unbound/iterator/iter_hints.h +++ b/usr.sbin/unbound/iterator/iter_hints.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -46,14 +46,11 @@ struct iter_env; struct config_file; struct delegpt; -struct regional; /** * Iterator hints structure */ struct iter_hints { - /** regional where hints are allocated */ - struct regional* region; /** * Hints are stored in this tree. Sort order is specially chosen. * first sorted on qclass. Then on dname in nsec-like order, so that @@ -62,7 +59,7 @@ struct iter_hints { * contents of type iter_hints_stub. The class IN root is in here. * uses name_tree_node from dnstree.h. */ - rbtree_t tree; + rbtree_type tree; }; /** @@ -71,7 +68,7 @@ struct iter_hints { struct iter_hints_stub { /** tree sorted by name, class */ struct name_tree_node node; - /** delegation point with hint information for this stub. */ + /** delegation point with hint information for this stub. malloced. */ struct delegpt* dp; /** does the stub need to forego priming (like on other ports) */ uint8_t noprime; @@ -139,4 +136,26 @@ struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints, */ size_t hints_get_mem(struct iter_hints* hints); +/** + * Add stub to hints structure. For external use since it recalcs + * the tree parents. + * @param hints: the hints data structure + * @param c: class of zone + * @param dp: delegation point with name and target nameservers for new + * hints stub. malloced. + * @param noprime: set noprime option to true or false on new hint stub. + * @return false on failure (out of memory); + */ +int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp, + int noprime); + +/** + * Remove stub from hints structure. For external use since it + * recalcs the tree parents. + * @param hints: the hints data structure + * @param c: class of stub zone + * @param nm: name of stub zone (in uncompressed wireformat). + */ +void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm); + #endif /* ITERATOR_ITER_HINTS_H */ diff --git a/usr.sbin/unbound/iterator/iter_priv.h b/usr.sbin/unbound/iterator/iter_priv.h index f6264f8d0c9..0430d57e3e3 100644 --- a/usr.sbin/unbound/iterator/iter_priv.h +++ b/usr.sbin/unbound/iterator/iter_priv.h @@ -21,16 +21,16 @@ * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @@ -43,7 +43,7 @@ #ifndef ITERATOR_ITER_PRIV_H #define ITERATOR_ITER_PRIV_H #include "util/rbtree.h" -#include <ldns/buffer.h> +struct sldns_buffer; struct iter_env; struct config_file; struct regional; @@ -60,14 +60,14 @@ struct iter_priv { * contents of type addr_tree_node. * No further data need, only presence or absence. */ - rbtree_t a; + rbtree_type a; /** * Tree of the domains spans that are allowed to contain * the blocked address spans. * contents of type name_tree_node. * No further data need, only presence or absence. */ - rbtree_t n; + rbtree_type n; }; /** @@ -92,12 +92,14 @@ int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg); /** * See if rrset is bad. + * Will remove individual RRs that are bad (if possible) to + * sanitize the RRset without removing it completely. * @param priv: structure for private address storage. * @param pkt: packet to decompress rrset name in. * @param rrset: the rrset to examine, A or AAAA. * @return true if the rrset is bad and should be removed. */ -int priv_rrset_bad(struct iter_priv* priv, ldns_buffer* pkt, +int priv_rrset_bad(struct iter_priv* priv, struct sldns_buffer* pkt, struct rrset_parse* rrset); /** diff --git a/usr.sbin/unbound/iterator/iter_scrub.c b/usr.sbin/unbound/iterator/iter_scrub.c index 8a3fc170c05..1bee85c0b99 100644 --- a/usr.sbin/unbound/iterator/iter_scrub.c +++ b/usr.sbin/unbound/iterator/iter_scrub.c @@ -161,8 +161,8 @@ mark_additional_rrset(sldns_buffer* pkt, struct msg_parse* msg, for(rr = rrset->rr_first; rr; rr = rr->next) { if(get_additional_name(rrset, rr, &nm, &nmlen, pkt)) { /* mark A */ - hashvalue_t h = pkt_hash_rrset(pkt, nm, LDNS_RR_TYPE_A, - rrset->rrset_class, 0); + hashvalue_type h = pkt_hash_rrset(pkt, nm, + LDNS_RR_TYPE_A, rrset->rrset_class, 0); struct rrset_parse* r = msgparse_hashtable_lookup( msg, pkt, h, 0, nm, nmlen, LDNS_RR_TYPE_A, rrset->rrset_class); diff --git a/usr.sbin/unbound/iterator/iter_utils.c b/usr.sbin/unbound/iterator/iter_utils.c index a5aefa9602c..0b1b456113f 100644 --- a/usr.sbin/unbound/iterator/iter_utils.c +++ b/usr.sbin/unbound/iterator/iter_utils.c @@ -108,7 +108,7 @@ read_fetch_policy(struct iter_env* ie, const char* str) /** apply config caps whitelist items to name tree */ static int -caps_white_apply_cfg(rbtree_t* ntree, struct config_file* cfg) +caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg) { struct config_strlist* p; for(p=cfg->caps_whitelist; p; p=p->next) { @@ -360,6 +360,39 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env, } } *selected_rtt = low_rtt; + + if (env->cfg->prefer_ip6) { + int got_num6 = 0; + int low_rtt6 = 0; + int i; + prev = NULL; + a = dp->result_list; + for(i = 0; i < got_num; i++) { + swap_to_front = 0; + if(a->addr.ss_family == AF_INET6) { + got_num6++; + swap_to_front = 1; + if(low_rtt6 == 0 || a->sel_rtt < low_rtt6) { + low_rtt6 = a->sel_rtt; + } + } + /* swap to front if IPv6, or move to next result */ + if(swap_to_front && prev) { + n = a->next_result; + prev->next_result = n; + a->next_result = dp->result_list; + dp->result_list = a; + a = n; + } else { + prev = a; + a = a->next_result; + } + } + if(got_num6 > 0) { + got_num = got_num6; + *selected_rtt = low_rtt6; + } + } return got_num; } @@ -499,6 +532,7 @@ causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen, qinf.qname_len = namelen; qinf.qtype = t; qinf.qclass = c; + qinf.local_alias = NULL; fptr_ok(fptr_whitelist_modenv_detect_cycle( qstate->env->detect_cycle)); return (*qstate->env->detect_cycle)(qstate, &qinf, diff --git a/usr.sbin/unbound/iterator/iterator.c b/usr.sbin/unbound/iterator/iterator.c index 1f5132b8282..99ce96f384e 100644 --- a/usr.sbin/unbound/iterator/iterator.c +++ b/usr.sbin/unbound/iterator/iterator.c @@ -88,7 +88,7 @@ iter_init(struct module_env* env, int id) /** delete caps_whitelist element */ static void -caps_free(struct rbnode_t* n, void* ATTR_UNUSED(d)) +caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d)) { if(n) { free(((struct name_tree_node*)n)->name); @@ -230,9 +230,8 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super) return; } else { /* see if the failure did get (parent-lame) info */ - if(!cache_fill_missing(super->env, - super_iq->qchase.qclass, super->region, - super_iq->dp)) + if(!cache_fill_missing(super->env, super_iq->qchase.qclass, + super->region, super_iq->dp)) log_err("out of memory adding missing"); } dpns->resolved = 1; /* mark as failed */ @@ -278,27 +277,29 @@ error_response(struct module_qstate* qstate, int id, int rcode) static int error_response_cache(struct module_qstate* qstate, int id, int rcode) { - /* store in cache */ - struct reply_info err; - if(qstate->prefetch_leeway > NORR_TTL) { - verbose(VERB_ALGO, "error response for prefetch in cache"); - /* attempt to adjust the cache entry prefetch */ - if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo, - NORR_TTL, qstate->query_flags)) - return error_response(qstate, id, rcode); - /* if that fails (not in cache), fall through to store err */ - } - memset(&err, 0, sizeof(err)); - err.flags = (uint16_t)(BIT_QR | BIT_RA); - FLAGS_SET_RCODE(err.flags, rcode); - err.qdcount = 1; - err.ttl = NORR_TTL; - err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl); - /* do not waste time trying to validate this servfail */ - err.security = sec_status_indeterminate; - verbose(VERB_ALGO, "store error response in message cache"); - iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL, - qstate->query_flags); + if(!qstate->no_cache_store) { + /* store in cache */ + struct reply_info err; + if(qstate->prefetch_leeway > NORR_TTL) { + verbose(VERB_ALGO, "error response for prefetch in cache"); + /* attempt to adjust the cache entry prefetch */ + if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo, + NORR_TTL, qstate->query_flags)) + return error_response(qstate, id, rcode); + /* if that fails (not in cache), fall through to store err */ + } + memset(&err, 0, sizeof(err)); + err.flags = (uint16_t)(BIT_QR | BIT_RA); + FLAGS_SET_RCODE(err.flags, rcode); + err.qdcount = 1; + err.ttl = NORR_TTL; + err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl); + /* do not waste time trying to validate this servfail */ + err.security = sec_status_indeterminate; + verbose(VERB_ALGO, "store error response in message cache"); + iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL, + qstate->query_flags); + } return error_response(qstate, id, rcode); } @@ -551,6 +552,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, qinf.qname_len = qnamelen; qinf.qtype = qtype; qinf.qclass = qclass; + qinf.local_alias = NULL; /* RD should be set only when sending the query back through the INIT * state. */ @@ -968,7 +970,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, { uint8_t* delname; size_t delnamelen; - struct dns_msg* msg; + struct dns_msg* msg = NULL; log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo); /* check effort */ @@ -1008,13 +1010,13 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, * getting older results from cache is a bad idea, no cache */ verbose(VERB_ALGO, "cache blacklisted, going to the network"); msg = NULL; - } else { + } else if(!qstate->no_cache_lookup) { msg = dns_cache_lookup(qstate->env, iq->qchase.qname, iq->qchase.qname_len, iq->qchase.qtype, iq->qchase.qclass, qstate->query_flags, qstate->region, qstate->env->scratch); if(!msg && qstate->env->neg_cache) { - /* lookup in negative cache; may result in + /* lookup in negative cache; may result in * NOERROR/NODATA or NXDOMAIN answers that need validation */ msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase, qstate->region, qstate->env->rrset_cache, @@ -1700,10 +1702,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq, /* if this was a parent-side glue query itself, then store that * failure in cache. */ - if(iq->query_for_pside_glue && !iq->pside_glue) - iter_store_parentside_neg(qstate->env, &qstate->qinfo, - iq->deleg_msg?iq->deleg_msg->rep: - (iq->response?iq->response->rep:NULL)); + if(!qstate->no_cache_store && iq->query_for_pside_glue + && !iq->pside_glue) + iter_store_parentside_neg(qstate->env, &qstate->qinfo, + iq->deleg_msg?iq->deleg_msg->rep: + (iq->response?iq->response->rep:NULL)); verbose(VERB_QUERY, "out of query targets -- returning SERVFAIL"); /* fail -- no more targets, no more hope of targets, no hope @@ -1787,8 +1790,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, int tf_policy; struct delegpt_addr* target; struct outbound_entry* outq; - /* EDNS options to set on outgoing packet */ - struct edns_option* opt_list = NULL; /* NOTE: a request will encounter this state for each target it * needs to send a query to. That is, at least one per referral, @@ -2011,6 +2012,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->qinfo_out.qname_len = iq->dp->namelen; iq->qinfo_out.qtype = LDNS_RR_TYPE_A; iq->qinfo_out.qclass = iq->qchase.qclass; + iq->qinfo_out.local_alias = NULL; iq->minimise_count = 0; } @@ -2026,6 +2028,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->minimise_count++; iq->minimise_timeout_count = 0; + iter_dec_attempts(iq->dp, 1); + /* Limit number of iterations for QNAMEs with more * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB * labels of QNAME always individually. @@ -2066,7 +2070,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, || iq->qchase.qtype == LDNS_RR_TYPE_A))) /* Stop minimising this query, resolve "as usual" */ iq->minimisation_state = DONOT_MINIMISE_STATE; - else { + else if(!qstate->no_cache_lookup) { struct dns_msg* msg = dns_cache_lookup(qstate->env, iq->qinfo_out.qname, iq->qinfo_out.qname_len, iq->qinfo_out.qtype, iq->qinfo_out.qclass, @@ -2086,7 +2090,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* Do not increment qname, continue incrementing next * iteration */ iq->minimisation_state = MINIMISE_STATE; - else + else if(!qstate->env->cfg->qname_minimisation_strict) /* Too many time-outs detected for this QNAME and QTYPE. * We give up, disable QNAME minimisation. */ iq->minimisation_state = DONOT_MINIMISE_STATE; @@ -2104,9 +2108,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->dnssec_lame_query?" but lame_query anyway": ""); } fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query)); - outq = (*qstate->env->send_query)( - iq->qinfo_out.qname, iq->qinfo_out.qname_len, - iq->qinfo_out.qtype, iq->qinfo_out.qclass, + outq = (*qstate->env->send_query)(&iq->qinfo_out, iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), /* unset CD if to forwarder(RD set) and not dnssec retry * (blacklist nonempty) and no trust-anchors are configured @@ -2115,8 +2117,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, !qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env, &iq->qinfo_out)||target->attempts==1)?0:BIT_CD), iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( - ie, iq), opt_list, &target->addr, target->addrlen, - iq->dp->name, iq->dp->namelen, qstate); + ie, iq), &target->addr, target->addrlen, + iq->dp->name, iq->dp->namelen, + (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), qstate); if(!outq) { log_addr(VERB_DETAIL, "error sending query to auth server", &target->addr, target->addrlen); @@ -2257,10 +2260,11 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->num_target_queries = 0; return processDSNSFind(qstate, iq, id); } - iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, 0, qstate->prefetch_leeway, - iq->dp&&iq->dp->has_parent_side_NS, - qstate->region, qstate->query_flags); + if(!qstate->no_cache_store) + iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 0, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, + qstate->region, qstate->query_flags); /* close down outstanding requests to be discarded */ outbound_list_clear(&iq->outlist); iq->num_current_queries = 0; @@ -2273,12 +2277,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, &qstate->reply->addr, qstate->reply->addrlen, qstate->region); if(iq->minimisation_state != DONOT_MINIMISE_STATE) { - /* Best effort qname-minimisation. - * Stop minimising and send full query when RCODE - * is not NOERROR. */ if(FLAGS_GET_RCODE(iq->response->rep->flags) != - LDNS_RCODE_NOERROR) + LDNS_RCODE_NOERROR) { + if(qstate->env->cfg->qname_minimisation_strict) + return final_state(iq); + /* Best effort qname-minimisation. + * Stop minimising and send full query when + * RCODE is not NOERROR. */ iq->minimisation_state = DONOT_MINIMISE_STATE; + } if(FLAGS_GET_RCODE(iq->response->rep->flags) == LDNS_RCODE_NXDOMAIN) { /* Stop resolving when NXDOMAIN is DNSSEC @@ -2325,7 +2332,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, } /* if hardened, only store referral if we asked for it */ - if(!qstate->env->cfg->harden_referral_path || + if(!qstate->no_cache_store && + (!qstate->env->cfg->harden_referral_path || ( qstate->qinfo.qtype == LDNS_RR_TYPE_NS && (qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD) @@ -2340,7 +2348,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->qchase.qname, iq->qchase.qname_len, LDNS_RR_TYPE_NS, iq->qchase.qclass) ) - )) { + ))) { /* Store the referral under the current query */ /* no prefetch-leeway, since its not the answer */ iter_dns_store(qstate->env, &iq->response->qinfo, @@ -2353,16 +2361,17 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->response->rep, iq->dp->name); } /* store parent-side-in-zone-glue, if directly queried for */ - if(iq->query_for_pside_glue && !iq->pside_glue) { - iq->pside_glue = reply_find_rrset(iq->response->rep, - iq->qchase.qname, iq->qchase.qname_len, - iq->qchase.qtype, iq->qchase.qclass); - if(iq->pside_glue) { - log_rrset_key(VERB_ALGO, "found parent-side " - "glue", iq->pside_glue); - iter_store_parentside_rrset(qstate->env, - iq->pside_glue); - } + if(!qstate->no_cache_store && iq->query_for_pside_glue + && !iq->pside_glue) { + iq->pside_glue = reply_find_rrset(iq->response->rep, + iq->qchase.qname, iq->qchase.qname_len, + iq->qchase.qtype, iq->qchase.qclass); + if(iq->pside_glue) { + log_rrset_key(VERB_ALGO, "found parent-side " + "glue", iq->pside_glue); + iter_store_parentside_rrset(qstate->env, + iq->pside_glue); + } } /* Reset the event state, setting the current delegation @@ -2443,10 +2452,11 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* NOTE : set referral=1, so that rrsets get stored but not * the partial query answer (CNAME only). */ /* prefetchleeway applied because this updates answer parts */ - iter_dns_store(qstate->env, &iq->response->qinfo, - iq->response->rep, 1, qstate->prefetch_leeway, - iq->dp&&iq->dp->has_parent_side_NS, NULL, - qstate->query_flags); + if(!qstate->no_cache_store) + iter_dns_store(qstate->env, &iq->response->qinfo, + iq->response->rep, 1, qstate->prefetch_leeway, + iq->dp&&iq->dp->has_parent_side_NS, NULL, + qstate->query_flags); /* set the current request's qname to the new value. */ iq->qchase.qname = sname; iq->qchase.qname_len = snamelen; @@ -2525,7 +2535,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* LAME, THROWAWAY and "unknown" all end up here. * Recycle to the QUERYTARGETS state to hopefully try a * different target. */ - if (qstate->env->cfg->qname_minimisation) + if (qstate->env->cfg->qname_minimisation && + !qstate->env->cfg->qname_minimisation_strict) iq->minimisation_state = DONOT_MINIMISE_STATE; return next_state(iq, QUERYTARGETS_STATE); } @@ -2925,10 +2936,11 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, &qstate->qinfo); /* store negative cache element for parent side glue. */ - if(iq->query_for_pside_glue && !iq->pside_glue) - iter_store_parentside_neg(qstate->env, &qstate->qinfo, - iq->deleg_msg?iq->deleg_msg->rep: - (iq->response?iq->response->rep:NULL)); + if(!qstate->no_cache_store && iq->query_for_pside_glue + && !iq->pside_glue) + iter_store_parentside_neg(qstate->env, &qstate->qinfo, + iq->deleg_msg?iq->deleg_msg->rep: + (iq->response?iq->response->rep:NULL)); if(!iq->response) { verbose(VERB_ALGO, "No response is set, servfail"); return error_response(qstate, id, LDNS_RCODE_SERVFAIL); @@ -2964,7 +2976,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, /* store message with the finished prepended items, * but only if we did recursion. The nonrecursion referral * from cache does not need to be stored in the msg cache. */ - if(qstate->query_flags&BIT_RD) { + if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) { iter_dns_store(qstate->env, &qstate->qinfo, iq->response->rep, 0, qstate->prefetch_leeway, iq->dp&&iq->dp->has_parent_side_NS, @@ -3139,6 +3151,18 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, if(parse_extract_edns(prs, &edns, qstate->env->scratch) != LDNS_RCODE_NOERROR) goto handle_it; + + /* Copy the edns options we may got from the back end */ + if(edns.opt_list) { + qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list, + qstate->region); + if(!qstate->edns_opts_back_in) { + log_err("out of memory on incoming message"); + /* like packet got dropped */ + goto handle_it; + } + } + /* remove CD-bit, we asked for in case we handle validation ourself */ prs->flags &= ~BIT_CD; diff --git a/usr.sbin/unbound/iterator/iterator.h b/usr.sbin/unbound/iterator/iterator.h index 5585f578958..37b0ab0dc24 100644 --- a/usr.sbin/unbound/iterator/iterator.h +++ b/usr.sbin/unbound/iterator/iterator.h @@ -51,7 +51,7 @@ struct iter_forwards; struct iter_donotq; struct iter_prep_list; struct iter_priv; -struct rbtree_t; +struct rbtree_type; /** max number of targets spawned for a query and its subqueries */ #define MAX_TARGET_COUNT 64 @@ -115,7 +115,7 @@ struct iter_env { struct iter_priv* priv; /** whitelist for capsforid names */ - struct rbtree_t* caps_white; + struct rbtree_type* caps_white; /** The maximum dependency depth that this resolver will pursue. */ int max_dependency_depth; |