and for setting timeout for UDP. Pending_udp takes milliseconds.
- cleaner iterator sockaddr conversion of forwarder address.
- iterator/iter_utils and iter_delegpt setup.
+ - root hints.
22 May 2007: Wouter
- outbound query list for modules and support to callback with the
#include "config.h"
#include "iterator/iter_delegpt.h"
#include "util/region-allocator.h"
+#include "util/data/dname.h"
+#include "util/net_help.h"
struct delegpt*
delegpt_create(struct region* region)
memset(dp, 0, sizeof(*dp));
return dp;
}
+
+int
+delegpt_set_name(struct delegpt* dp, struct region* region, uint8_t* name)
+{
+ dp->namelabs = dname_count_size_labels(name, &dp->namelen);
+ dp->name = region_alloc_init(region, name, dp->namelen);
+ return dp->name != 0;
+}
+
+int
+delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name)
+{
+ struct delegpt_ns* ns = (struct delegpt_ns*)region_alloc(region,
+ sizeof(struct delegpt_ns));
+ if(!ns)
+ return 0;
+ ns->next = dp->nslist;
+ dp->nslist = ns;
+ (void)dname_count_size_labels(name, &ns->namelen);
+ ns->name = region_alloc_init(region, name, ns->namelen);
+ ns->resolved = 0;
+ return 1;
+}
+
+/** find name in deleg list */
+static struct delegpt_ns*
+delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen)
+{
+ struct delegpt_ns* p = dp->nslist;
+ while(p) {
+ if(namelen == p->namelen &&
+ memcmp(name, p->name, namelen) == 0) {
+ return p;
+ }
+ p = p->next;
+ }
+ return NULL;
+}
+
+int
+delegpt_add_target(struct delegpt* dp, struct region* region,
+ uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
+ socklen_t addrlen)
+{
+ struct delegpt_addr* a;
+ struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
+ if(!ns) {
+ /* ignore it */
+ return 1;
+ }
+ ns->resolved = 1;
+
+ a = (struct delegpt_addr*)region_alloc(region,
+ 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;
+ return 1;
+
+}
+
+void delegpt_log(struct delegpt* dp)
+{
+ char buf[LDNS_MAX_DOMAINLEN+1];
+ struct delegpt_ns* ns;
+ struct delegpt_addr* a;
+ dname_str(dp->name, buf);
+ log_info("DelegationPoint<%s>:", buf);
+ for(ns = dp->nslist; ns; ns = ns->next) {
+ dname_str(ns->name, buf);
+ log_info(" %s%s", buf, (ns->resolved?"*":""));
+ }
+ for(a = dp->target_list; a; a = a->next_target) {
+ log_addr(" ", &a->addr, a->addrlen);
+ }
+}
*/
struct delegpt* delegpt_create(struct region* region);
+/**
+ * Set name of delegation point.
+ * @param dp: delegation point.
+ * @param region: where to allocate the name copy.
+ * @param name: name to use.
+ * @return false on error.
+ */
+int delegpt_set_name(struct delegpt* dp, struct region* region, uint8_t* name);
+
+/**
+ * Add a name to the delegation point.
+ * @param dp: delegation point.
+ * @param region: where to allocate the info.
+ * @param name: domain name in wire format.
+ * @return false on error.
+ */
+int delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name);
+
+/**
+ * Add address to the delegation point.
+ * @param dp: delegation point.
+ * @param region: where to allocate the info.
+ * @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.
+ * @return false on error.
+ */
+int delegpt_add_target(struct delegpt* dp, struct region* region,
+ uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
+ socklen_t addrlen);
+
+/**
+ * Print the delegation point to the log. For debugging.
+ * @param dp: delegation point.
+ */
+void delegpt_log(struct delegpt* dp);
+
#endif /* ITERATOR_ITER_DELEGPT_H */
--- /dev/null
+/*
+ * iterator/iter_hints.c - iterative resolver module stub and root hints.
+ *
+ * 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.
+ * Keep track of stub and root hints, and read those from config.
+ */
+#include "config.h"
+#include "iterator/iter_hints.h"
+#include "iterator/iter_delegpt.h"
+#include "util/region-allocator.h"
+#include "util/log.h"
+#include "util/net_help.h"
+#include "util/data/dname.h"
+
+/** compare two hint entries */
+static int
+stub_cmp(const void* k1, const void* k2)
+{
+ int m;
+ struct iter_hints_stub* n1 = (struct iter_hints_stub*)k1;
+ struct iter_hints_stub* n2 = (struct iter_hints_stub*)k2;
+ if(n1->hint_class != n2->hint_class) {
+ if(n1->hint_class < n2->hint_class)
+ return -1;
+ return 1;
+ }
+ return dname_lab_cmp(n1->name, n1->namelabs, n2->name, n2->namelabs,
+ &m);
+}
+
+struct iter_hints*
+hints_create()
+{
+ struct iter_hints* hints = (struct iter_hints*)calloc(1,
+ sizeof(struct iter_hints));
+ if(!hints)
+ return NULL;
+ hints->region = region_create(malloc, free);
+ if(!hints->region) {
+ hints_delete(hints);
+ return NULL;
+ }
+ return hints;
+}
+
+void
+hints_delete(struct iter_hints* hints)
+{
+ if(!hints)
+ return;
+ region_destroy(hints->region);
+ free(hints->tree);
+ free(hints);
+}
+
+/** add hint to delegation hints */
+static int
+ah(struct delegpt* dp, struct region* r, const char* sv, const char* ip)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ ldns_rdf* rdf = ldns_dname_new_frm_str(sv);
+ if(!rdf) {
+ log_err("could not parse %s", sv);
+ return 0;
+ }
+ if(!delegpt_add_ns(dp, r, ldns_rdf_data(rdf)) ||
+ !ipstrtoaddr(ip, UNBOUND_DNS_PORT, &addr, &addrlen) ||
+ !delegpt_add_target(dp, r, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
+ &addr, addrlen)) {
+ ldns_rdf_deep_free(rdf);
+ return 0;
+ }
+ ldns_rdf_deep_free(rdf);
+ return 1;
+}
+
+/** obtain compiletime provided root hints */
+static struct delegpt*
+compile_time_root_prime(struct region* r)
+{
+ /* from:
+ ; This file is made available by InterNIC
+ ; under anonymous FTP as
+ ; file /domain/named.cache
+ ; on server FTP.INTERNIC.NET
+ ; -OR- RS.INTERNIC.NET
+ ;
+ ; last update: Jan 29, 2004
+ ; related version of root zone: 2004012900
+ */
+ struct delegpt* dp = delegpt_create(r);
+ if(!dp)
+ return NULL;
+ if(!delegpt_set_name(dp, r, (uint8_t*)"\000"))
+ return NULL;
+ if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
+ if(!ah(dp, r, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
+ if(!ah(dp, r, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
+ if(!ah(dp, r, "D.ROOT-SERVERS.NET.", "128.8.10.90")) return 0;
+ if(!ah(dp, r, "E.ROOT-SERVERS.NET.", "192.203.230.10")) return 0;
+ if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "192.5.5.241")) return 0;
+ if(!ah(dp, r, "G.ROOT-SERVERS.NET.", "192.112.36.4")) return 0;
+ if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "128.63.2.53")) return 0;
+ if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
+ if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
+ if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
+ if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "198.32.64.12")) return 0;
+ if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
+ return dp;
+}
+
+/** insert new hint info into hint structure */
+static int
+hints_insert(struct iter_hints* hints, uint16_t c, uint8_t* name,
+ size_t namelen, int namelabs, struct delegpt* dp)
+{
+ struct iter_hints_stub* node = region_alloc(hints->region,
+ sizeof(struct iter_hints_stub));
+ if(!node)
+ return 0;
+ node->node.key = node;
+ node->hint_class = c;
+ node->name = region_alloc_init(hints->region, name, namelen);
+ if(!node->name)
+ return 0;
+ node->namelen = namelen;
+ node->namelabs = namelabs;
+ node->dp = dp;
+ if(!rbtree_insert(hints->tree, &node->node)) {
+ log_err("second hints ignored.");
+ }
+ return 1;
+}
+
+/** initialise parent pointers in the tree */
+static void
+init_parents(struct iter_hints* hints)
+{
+ struct iter_hints_stub* node, *prev = NULL, *p;
+ int m;
+ RBTREE_FOR(node, struct iter_hints_stub*, hints->tree) {
+ node->parent = NULL;
+ if(!prev || prev->hint_class != node->hint_class) {
+ prev = node;
+ continue;
+ }
+ (void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
+ node->namelabs, &m); /* we know prev is smaller */
+ /* sort order like: . com. bla.com. zwb.com. net. */
+ /* find the previous, or parent-parent-parent */
+ for(p = prev; p; p = p->parent)
+ /* looking for name with few labels, a parent */
+ if(p->namelabs <= m) {
+ /* ==: since prev matched m, this is closest*/
+ /* <: prev matches more, but is not a parent,
+ * this one is a (grand)parent */
+ node->parent = p;
+ break;
+ }
+ prev = node;
+ }
+}
+
+int
+hints_apply_cfg(struct iter_hints* hints, struct config_file* ATTR_UNUSED(cfg))
+{
+ struct delegpt* dp;
+ free(hints->tree);
+ hints->tree = rbtree_create(stub_cmp);
+ if(!hints->tree)
+ return 0;
+ /* TODO: read hints from file named in cfg */
+
+ /* use fallback compiletime root hints */
+ dp = compile_time_root_prime(hints->region);
+ if(!dp)
+ return 0;
+ if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp->name, dp->namelen,
+ dp->namelabs, dp))
+ return 0;
+ delegpt_log(dp);
+
+ init_parents(hints);
+ return 1;
+}
+
+struct delegpt*
+hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
+{
+ uint8_t rootlab = 0;
+ struct iter_hints_stub key, *stub;
+ key.node.key = &key;
+ key.hint_class = qclass;
+ key.name = &rootlab;
+ key.namelen = 1;
+ key.namelabs = 1;
+ stub = (struct iter_hints_stub*)rbtree_search(hints->tree, &key);
+ if(!stub)
+ return NULL;
+ return stub->dp;
+}
--- /dev/null
+/*
+ * iterator/iter_hints.h - iterative resolver module stub and root hints.
+ *
+ * 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.
+ * Keep track of stub and root hints, and read those from config.
+ */
+
+#ifndef ITERATOR_ITER_HINTS_H
+#define ITERATOR_ITER_HINTS_H
+#include "util/rbtree.h"
+struct iter_env;
+struct config_file;
+struct delegpt;
+struct region;
+
+/**
+ * Iterator hints structure
+ */
+struct iter_hints {
+ /** region where hints are allocated */
+ struct region* region;
+ /**
+ * Hints are stored in this tree. Sort order is specially chosen.
+ * first sorted on qtype. Then on dname in nsec-like order, so that
+ * a lookup on class, name will return an exact match or the closest
+ * match which gives the ancestor needed.
+ * contents of type iter_hints_stub. The class IN root is in here.
+ */
+ rbtree_t* tree;
+};
+
+/**
+ * Iterator hints for a particular stub.
+ */
+struct iter_hints_stub {
+ /** redblacktree node, key is this structure: class and name */
+ rbnode_t node;
+ /** name */
+ uint8_t* name;
+ /** length of name */
+ size_t namelen;
+ /** number of labels in name */
+ int namelabs;
+ /** delegation point with hint information for this stub. */
+ struct delegpt* dp;
+ /** pointer to parent in stub hint tree (or NULL if none) */
+ struct iter_hints_stub* parent;
+ /** class of hints. host order. */
+ uint16_t hint_class;
+};
+
+/**
+ * Create hints
+ * @return new hints or NULL on error.
+ */
+struct iter_hints* hints_create();
+
+/**
+ * Delete hints.
+ * @param hints: to delete.
+ */
+void hints_delete(struct iter_hints* hints);
+
+/**
+ * Process hints config. Sets default values for root hints if no config.
+ * @param hints: where to store.
+ * @param cfg: config options.
+ * @return 0 on error.
+ */
+int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
+
+/**
+ * Find root hints for the given class.
+ * @param hints: hint storage.
+ * @param qclass: class for which root hints are requested. host order.
+ * @return: NULL if no hints, or a ptr to stored hints.
+ */
+struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
+
+#endif /* ITERATOR_ITER_HINTS_H */
#include "config.h"
#include "iterator/iter_utils.h"
#include "iterator/iterator.h"
+#include "iterator/iter_hints.h"
#include "util/net_help.h"
#include "util/log.h"
#include "util/config_file.h"
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]);
+
+ if(!iter_env->hints)
+ iter_env->hints = hints_create();
+ if(!iter_env->hints || !hints_apply_cfg(iter_env->hints, cfg)) {
+ log_err("Could not set root or stub hints");
+ return 0;
+ }
+
/* forwarder address */
if(cfg->fwd_address && cfg->fwd_address[0]) {
#include "util/region-allocator.h"
#include "services/cache/rrset.h"
#include "iterator/iter_utils.h"
+#include "iterator/iter_hints.h"
/** iterator init */
static int
if(!env || !env->modinfo)
return;
iter_env = (struct iter_env*)env->modinfo[id];
+ free(iter_env->target_fetch_policy);
+ hints_delete(iter_env->hints);
if(iter_env)
free(iter_env);
}
return 0;
memset(iq, 0, sizeof(*iq));
outbound_list_init(&iq->outlist);
+ iq->num_target_queries = -1; /* default our targetQueries counter. */
if(qstate->qinfo.has_cd)
flags |= BIT_CD;
e = (*env->send_query)(qstate->qinfo.qname, qstate->qinfo.qnamesize,
{
return &iter_block;
}
+
+const char*
+iter_state_to_string(enum iter_state state)
+{
+ switch (state)
+ {
+ case INIT_REQUEST_STATE :
+ return "INIT REQUEST STATE";
+ case INIT_REQUEST_2_STATE :
+ return "INIT REQUEST STATE (stage 2)";
+ case INIT_REQUEST_3_STATE:
+ return "INIT REQUEST STATE (stage 3)";
+ case QUERYTARGETS_STATE :
+ return "QUERY TARGETS STATE";
+ case PRIME_RESP_STATE :
+ return "PRIME RESPONSE STATE";
+ case QUERY_RESP_STATE :
+ return "QUERY RESPONSE STATE";
+ case TARGET_RESP_STATE :
+ return "TARGET RESPONSE STATE";
+ case FINISHED_STATE :
+ return "FINISHED RESPONSE STATE";
+ default :
+ return "UNKNOWN ITER STATE";
+ }
+}
#include "services/outbound_list.h"
struct module_func_block;
struct delegpt;
+struct packed_rrset_list;
+struct iter_hints;
/**
* Global state for the iterator.
* that both root hints and stub zone "hints" are stored in this
* data structure.
*/
- /* struct hints* hints TODO */
+ struct iter_hints* hints;
/** A flag to indicate whether or not we have an IPv6 route */
int supports_ipv6;
* 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 */
+ struct packed_rrset_list* prepend_list;
/**
* This is the current delegation point for an in-progress query. This
*/
struct module_func_block* iter_get_funcblock();
+/**
+ * Get iterator state as a string
+ * @param state: to convert
+ * @return constant string that is printable.
+ */
+const char* iter_state_to_string(enum iter_state state);
+
#endif /* ITERATOR_ITERATOR_H */
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(s == -1) {
log_err("outgoing tcp: socket: %s", strerror(errno));
- log_addr(&w->addr, w->addrlen);
+ log_addr("failed address", &w->addr, w->addrlen);
return 0;
}
fd_set_nonblock(s);
if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) {
if(errno != EINPROGRESS) {
log_err("outgoing tcp: connect: %s", strerror(errno));
- log_addr(&w->addr, w->addrlen);
+ log_addr("failed address", &w->addr, w->addrlen);
close(s);
return 0;
}
/* check ID */
if(ldns_buffer_limit(c->buffer) < sizeof(uint16_t) ||
LDNS_ID_WIRE(ldns_buffer_begin(c->buffer))!=pend->id) {
- log_info("outnettcp: bad ID in reply, from:");
- log_addr(&pend->query->addr, pend->query->addrlen);
+ log_addr("outnettcp: bad ID in reply, from:",
+ &pend->query->addr, pend->query->addrlen);
error = NETEVENT_CLOSED;
}
}
}
return 1;
}
+
+void dname_str(uint8_t* dname, char* str)
+{
+ size_t len = 0;
+ uint8_t lablen = 0;
+ char* s = str;
+ if(!dname || !*dname) {
+ *s++ = '.';
+ *s = 0;
+ return;
+ }
+ lablen = *dname++;
+ while(lablen) {
+ if(lablen > LDNS_MAX_LABELLEN) {
+ *s++ = '#';
+ *s = 0;
+ return;
+ }
+ len += lablen+1;
+ if(len >= LDNS_MAX_DOMAINLEN-1) {
+ *s++ = '&';
+ *s = 0;
+ return;
+ }
+ while(lablen--) {
+ if(isalnum((int)*dname)
+ || *dname == '-' || *dname == '_')
+ *s++ = *(char*)dname++;
+ else {
+ *s++ = '?';
+ dname++;
+ }
+ }
+ *s++ = '.';
+ lablen = *dname++;
+ }
+ *s = 0;
+}
*/
int dname_buffer_write(ldns_buffer* pkt, uint8_t* dname);
-/** debug helper. Print wireformat dname to output.
- * @param out: like stdout or a file.
- * @param pkt: if not NULL, the packet for resolving compression ptrs.
- * @param dname: pointer to (start of) dname.
- */
-void dname_print(FILE* out, ldns_buffer* pkt, uint8_t* dname);
-
/**
* Count the number of labels in an uncompressed dname in memory.
* @param dname: pointer to uncompressed dname.
*/
int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
+/**
+ * Debug helper. Print wireformat dname to output.
+ * @param out: like stdout or a file.
+ * @param pkt: if not NULL, the packet for resolving compression ptrs.
+ * @param dname: pointer to (start of) dname.
+ */
+void dname_print(FILE* out, ldns_buffer* pkt, uint8_t* dname);
+
+/**
+ * Debug helper. Print dname to given string buffer (string buffer must
+ * be at least 255 chars + 1 for the 0, in printable form.
+ * This may lose information (? for nonprintable characters, or & if
+ * the name is too long, # for a bad label length).
+ * @param dname: uncompressed wireformat.
+ * @param str: buffer of 255+1 length.
+ */
+void dname_str(uint8_t* dname, char* str);
+
#endif /* UTIL_DATA_DNAME_H */
struct packed_rrset_data* d;
};
+/**
+ * list of packed rrsets
+ */
+struct packed_rrset_list {
+ /** next in list */
+ struct packed_rrset_list* next;
+ /** rrset key and data */
+ struct packed_rrset rrset;
+};
+
/**
* Delete packed rrset key and data, not entered in hashtables yet.
* Used during parsing.
}
void
-log_addr(struct sockaddr_storage* addr, socklen_t addrlen)
+log_addr(const char* str, struct sockaddr_storage* addr, socklen_t addrlen)
{
uint16_t port;
const char* family = "unknown";
strncpy(dest, "(inet_ntop error)", sizeof(dest));
}
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
- verbose(VERB_DETAIL, "addr fam=%s port=%d dest=%s len=%d",
- family, (int)port, dest, (int)addrlen);
+ verbose(VERB_DETAIL, "%s %s %s:%d (len %d)",
+ str, family, dest, (int)port, (int)addrlen);
}
int
/**
* Prints the sockaddr in readable format with log_info. Debug helper.
+ * @param str: descriptive string printed with it.
* @param addr: the sockaddr to print. Can be ip4 or ip6.
* @param addrlen: length of addr.
*/
-void log_addr(struct sockaddr_storage* addr, socklen_t addrlen);
+void log_addr(const char* str, struct sockaddr_storage* addr,
+ socklen_t addrlen);
/**
* Convert ip address string and port to sockaddr.