From 472e96622cbf81c733c2e7736501eb334db1142d Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 23 May 2007 09:34:01 +0000 Subject: [PATCH] setup of state; delegation point setup. git-svn-id: file:///svn/unbound/trunk@334 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 2 + iterator/iter_delegpt.c | 54 +++++++++++++++++ iterator/iter_delegpt.h | 112 +++++++++++++++++++++++++++++++++++ iterator/iter_utils.c | 80 +++++++++++++++++++++++++ iterator/iter_utils.h | 57 ++++++++++++++++++ iterator/iterator.c | 53 ++--------------- iterator/iterator.h | 127 +++++++++++++++++++++++++++++++++++++++- util/net_help.c | 31 ++++++++++ util/net_help.h | 10 ++++ 9 files changed, 477 insertions(+), 49 deletions(-) create mode 100644 iterator/iter_delegpt.c create mode 100644 iterator/iter_delegpt.h create mode 100644 iterator/iter_utils.c create mode 100644 iterator/iter_utils.h diff --git a/doc/Changelog b/doc/Changelog index e1fa1339b..e196dd365 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,8 @@ 23 May 2007: Wouter - outside network does precise timers for roundtrip estimates for rtt and for setting timeout for UDP. Pending_udp takes milliseconds. + - cleaner iterator sockaddr conversion of forwarder address. + - iterator/iter_utils and iter_delegpt setup. 22 May 2007: Wouter - outbound query list for modules and support to callback with the diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c new file mode 100644 index 000000000..5f2ef0ef1 --- /dev/null +++ b/iterator/iter_delegpt.c @@ -0,0 +1,54 @@ +/* + * iterator/iter_delegpt.c - delegation point with NS and address information. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * 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. + */ + +/** + * \file + * + * This file implements the Delegation Point. It contains a list of name servers + * and their addresses if known. + */ +#include "config.h" +#include "iterator/iter_delegpt.h" +#include "util/region-allocator.h" + +struct delegpt* +delegpt_create(struct region* region) +{ + struct delegpt* dp=(struct delegpt*)region_alloc(region, sizeof(*dp)); + if(!dp) + return NULL; + memset(dp, 0, sizeof(*dp)); + return dp; +} diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h new file mode 100644 index 000000000..0e2ffed38 --- /dev/null +++ b/iterator/iter_delegpt.h @@ -0,0 +1,112 @@ +/* + * iterator/iter_delegpt.h - delegation point with NS and address information. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * 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. + */ + +/** + * \file + * + * This file implements the Delegation Point. It contains a list of name servers + * and their addresses if known. + */ + +#ifndef ITERATOR_ITER_DELEGPT_H +#define ITERATOR_ITER_DELEGPT_H +struct region; +struct delegpt_ns; +struct delegpt_addr; + +/** + * Delegation Point. + * For a domain name, the NS rrset, and the A and AAAA records for those. + */ +struct delegpt { + /** the domain name of the delegation point. */ + uint8_t* name; + /** length of the delegation point name */ + size_t namelen; + /** number of labels in delegation point */ + int namelabs; + + /** the nameservers, names from the NS RRset rdata. */ + struct delegpt_ns* nslist; + /** the target addresses for delegation */ + struct delegpt_addr* target_list; + /** the list of usable targets; subset of target_list */ + struct delegpt_addr* usable_list; + /** the list of returned targets; subset of target_list */ + struct delegpt_addr* result_list; +}; + +/** + * Nameservers for a delegation point. + */ +struct delegpt_ns { + /** next in list */ + struct delegpt_ns* next; + /** name of nameserver */ + uint8_t* name; + /** length of name */ + size_t namelen; + /** + * If the name has been resolved. false if not queried for yet. + * true if the address is known, or marked true if failed. + */ + int resolved; +}; + +/** + * Address of target nameserver in delegation point. + */ +struct delegpt_addr { + /** next delegation point in results */ + struct delegpt_addr* next_result; + /** next delegation point in usable list */ + struct delegpt_addr* next_usable; + /** next delegation point in all targets list */ + struct delegpt_addr* next_target; + + /** delegation point address */ + struct sockaddr_storage addr; + /** length of addr */ + socklen_t addrlen; +}; + +/** + * Create new delegation point. + * @param region: where to allocate it. + * @return new delegation point or NULL on error. + */ +struct delegpt* delegpt_create(struct region* region); + +#endif /* ITERATOR_ITER_DELEGPT_H */ diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c new file mode 100644 index 000000000..5af8317af --- /dev/null +++ b/iterator/iter_utils.c @@ -0,0 +1,80 @@ +/* + * iterator/iter_utils.c - iterative resolver module utility functions. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * 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. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Configuration options. Forward zones. + */ +#include "config.h" +#include "iterator/iter_utils.h" +#include "iterator/iterator.h" +#include "util/net_help.h" +#include "util/log.h" +#include "util/config_file.h" + +int +iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) +{ + int i; + /* target fetch policy */ + iter_env->max_dependency_depth = 4; + iter_env->target_fetch_policy = (int*)calloc( + (size_t)iter_env->max_dependency_depth+1, sizeof(int)); + if(iter_env->max_dependency_depth >= 1) + iter_env->target_fetch_policy[1] = 3; + if(iter_env->max_dependency_depth >= 2) + iter_env->target_fetch_policy[2] = 1; + /* TODO read setting from config */ + if(!iter_env->target_fetch_policy) + return 0; + for(i=0; imax_dependency_depth+1; i++) + verbose(VERB_DETAIL, "target fetch policy for level %d is %d", + i, iter_env->target_fetch_policy[i]); + + /* forwarder address */ + if(cfg->fwd_address && cfg->fwd_address[0]) { + if(!ipstrtoaddr(cfg->fwd_address, cfg->fwd_port, + &iter_env->fwd_addr, &iter_env->fwd_addrlen)) { + log_err("iterator: could not set forwarder address"); + return 0; + } + verbose(VERB_ALGO, "iterator: fwd queries to: %s %d", + cfg->fwd_address, cfg->fwd_port); + } + return 1; +} + diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h new file mode 100644 index 000000000..b3e6d77a1 --- /dev/null +++ b/iterator/iter_utils.h @@ -0,0 +1,57 @@ +/* + * iterator/iter_utils.h - iterative resolver module utility functions. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * 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. + */ + +/** + * \file + * + * This file contains functions to assist the iterator module. + * Configuration options. Forward zones. + */ + +#ifndef ITERATOR_ITER_UTILS_H +#define ITERATOR_ITER_UTILS_H +struct iter_env; +struct config_file; + +/** + * Process config options and set iterator module state. + * Sets default values if no config is found. + * @param iter_env: iterator module state. + * @param cfg: config options. + * @return 0 on error. + */ +int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg); + +#endif /* ITERATOR_ITER_UTILS_H */ diff --git a/iterator/iterator.c b/iterator/iterator.c index 07c16e37b..5867276f0 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -44,51 +44,11 @@ #include "iterator/iterator.h" #include "util/module.h" #include "util/netevent.h" -#include "util/config_file.h" #include "util/net_help.h" #include "util/storage/slabhash.h" #include "util/region-allocator.h" #include "services/cache/rrset.h" - -/** - * Set forwarder address - * @param ie: iterator global state. - * @param ip: the server name. - * @param port: port on server or NULL for default 53. - * @return: false on error. - */ -static int -iter_set_fwd(struct iter_env* ie, const char* ip, int port) -{ - uint16_t p; - log_assert(ie && ip); - p = (uint16_t) port; - if(str_is_ip6(ip)) { - struct sockaddr_in6* sa = - (struct sockaddr_in6*)&ie->fwd_addr; - ie->fwd_addrlen = (socklen_t)sizeof(struct sockaddr_in6); - memset(sa, 0, ie->fwd_addrlen); - sa->sin6_family = AF_INET6; - sa->sin6_port = (in_port_t)htons(p); - if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { - log_err("Bad ip6 address %s", ip); - return 0; - } - } else { /* ip4 */ - struct sockaddr_in* sa = - (struct sockaddr_in*)&ie->fwd_addr; - ie->fwd_addrlen = (socklen_t)sizeof(struct sockaddr_in); - memset(sa, 0, ie->fwd_addrlen); - sa->sin_family = AF_INET; - sa->sin_port = (in_port_t)htons(p); - if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { - log_err("Bad ip4 address %s", ip); - return 0; - } - } - verbose(VERB_ALGO, "iterator: fwd queries to: %s %d", ip, p); - return 1; -} +#include "iterator/iter_utils.h" /** iterator init */ static int @@ -101,13 +61,9 @@ iter_init(struct module_env* env, int id) return 0; } env->modinfo[id] = (void*)iter_env; - /* set forwarder address */ - if(env->cfg->fwd_address && env->cfg->fwd_address[0]) { - if(!iter_set_fwd(iter_env, env->cfg->fwd_address, - env->cfg->fwd_port)) { - log_err("iterator: could not set forwarder address"); - return 0; - } + if(!iter_apply_cfg(iter_env, env->cfg)) { + log_err("iterator: could not apply configuration settings."); + return 0; } return 1; } @@ -177,6 +133,7 @@ iter_new(struct module_qstate* qstate, int id) qstate->minfo[id] = iq; if(!iq) return 0; + memset(iq, 0, sizeof(*iq)); outbound_list_init(&iq->outlist); if(qstate->qinfo.has_cd) flags |= BIT_CD; diff --git a/iterator/iterator.h b/iterator/iterator.h index 5a075e663..981579bee 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -44,6 +44,7 @@ #define ITERATOR_ITERATOR_H #include "services/outbound_list.h" struct module_func_block; +struct delegpt; /** * Global state for the iterator. @@ -51,14 +52,138 @@ struct module_func_block; struct iter_env { /** address to forward to */ struct sockaddr_storage fwd_addr; - /** length of fwd_addr */ + /** length of fwd_addr, if not 0, forward mode is used */ socklen_t fwd_addrlen; + + /** + * The hints -- these aren't stored in the cache because they don't + * expire. The hints are always used to "prime" the cache. Note + * that both root hints and stub zone "hints" are stored in this + * data structure. + */ + /* struct hints* hints TODO */ + + /** A flag to indicate whether or not we have an IPv6 route */ + int supports_ipv6; + + /** Mapping of forwarding zones to targets. */ + /* struct fwds fwd_map TODO */ + + /** A set of inetaddrs that should never be queried. */ + /* struct bla donotquery_addrs TODO */ + + /** The maximum dependency depth that this resolver will pursue. */ + int max_dependency_depth; + + /** + * The target fetch policy for each dependency level. This is + * described as a simple number (per dependency level): + * negative numbers (usually just -1) mean fetch-all, + * 0 means only fetch on demand, and + * positive numbers mean to fetch at most that many targets. + * array of max_dependency_depth+1 size. + */ + int* target_fetch_policy; +}; + +/** + * State of the iterator for a query. + */ +enum iter_state { + /** + * Externally generated queries start at this state. Query restarts are + * reset to this state. + */ + INIT_REQUEST_STATE = 0, + + /** + * Root priming events reactivate here, most other events pass + * through this naturally as the 2nd part of the INIT_REQUEST_STATE. + */ + INIT_REQUEST_2_STATE, + + /** + * Stub priming events reactivate here, most other events pass + * through this naturally as the 3rd part of the INIT_REQUEST_STATE. + */ + INIT_REQUEST_3_STATE, + + /** + * Each time a delegation point changes for a given query or a + * query times out and/or wakes up, this state is (re)visited. + * This state is reponsible for iterating through a list of + * nameserver targets. + */ + QUERYTARGETS_STATE, + + /** + * Responses to queries start at this state. This state handles + * the decision tree associated with handling responses. + */ + QUERY_RESP_STATE, + + /** Responses to priming queries finish at this state. */ + PRIME_RESP_STATE, + + /** Responses to target queries start at this state. */ + TARGET_RESP_STATE, + + /** Responses that are to be returned upstream end at this state. */ + FINISHED_STATE }; /** * Per query state for the iterator module. */ struct iter_qstate { + /** state of the iterator module + * This is the state that event is in or should sent to -- all + * requests should start with the INIT_REQUEST_STATE. All + * responses should start with QUERY_RESP_STATE. Subsequent + * processing of the event will change this state. + */ + enum iter_state state; + + /** final state for the iterator module + * This is the state that responses should be routed to once the + * response is final. For externally initiated queries, this + * will be FINISHED_STATE, locally initiated queries will have + * different final states. + */ + enum iter_state final_state; + + /** + * This is a list of RRsets that must be prepended to the + * ANSWER section of a response before being sent upstream. + */ + /* TODO list of struct rrsets or something */ + + /** + * This is the current delegation point for an in-progress query. This + * object retains state as to which delegation targets need to be + * (sub)queried for vs which ones have already been visited. + */ + struct delegpt* dp; + + /** number of outstanding target sub queries */ + int num_target_queries; + + /** outstanding direct queries */ + int num_current_queries; + + /** the number of times this query has been restarted. */ + int query_restart_count; + + /** the number of times this query as followed a referral. */ + int referral_count; + + /** + * This is flag that, if true, means that this event is + * representing a stub priming query. It is meaningless unless + * the finalState is the PRIMING_RESP_STATE. + */ + int priming_stub; + /** list of pending queries to authoritative servers. */ struct outbound_list outlist; }; diff --git a/util/net_help.c b/util/net_help.c index 6041c0aaf..1cb52f0d0 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -145,3 +145,34 @@ log_addr(struct sockaddr_storage* addr, socklen_t addrlen) verbose(VERB_DETAIL, "addr fam=%s port=%d dest=%s len=%d", family, (int)port, dest, (int)addrlen); } + +int +ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, + socklen_t* addrlen) +{ + uint16_t p; + if(!ip) return 0; + p = (uint16_t) port; + if(str_is_ip6(ip)) { + struct sockaddr_in6* sa = (struct sockaddr_in6*)addr; + *addrlen = (socklen_t)sizeof(struct sockaddr_in6); + memset(sa, 0, *addrlen); + sa->sin6_family = AF_INET6; + sa->sin6_port = (in_port_t)htons(p); + if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { + log_err("Bad ip6 address %s", ip); + return 0; + } + } else { /* ip4 */ + struct sockaddr_in* sa = (struct sockaddr_in*)addr; + *addrlen = (socklen_t)sizeof(struct sockaddr_in); + memset(sa, 0, *addrlen); + sa->sin_family = AF_INET; + sa->sin_port = (in_port_t)htons(p); + if(inet_pton((int)sa->sin_family, ip, &sa->sin_addr) <= 0) { + log_err("Bad ip4 address %s", ip); + return 0; + } + } + return 1; +} diff --git a/util/net_help.h b/util/net_help.h index e123d8593..7b1c78f78 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -117,5 +117,15 @@ void* memdup(void* data, size_t len); */ void log_addr(struct sockaddr_storage* addr, socklen_t addrlen); +/** + * Convert ip address string and port to sockaddr. + * @param ip: ip4 or ip6 address string. + * @param port: port number, host format. + * @param addr: where to store sockaddr. + * @param addrlen: length of stored sockaddr is returned. + * @return 0 on error. + */ +int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, + socklen_t* addrlen); #endif /* NET_HELP_H */ -- 2.47.2