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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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; i<iter_env->max_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;
+}
+
--- /dev/null
+/*
+ * 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 */
#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
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;
}
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;
#define ITERATOR_ITERATOR_H
#include "services/outbound_list.h"
struct module_func_block;
+struct delegpt;
/**
* Global state for the iterator.
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;
};
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;
+}
*/
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 */