root hints.

git-svn-id: file:///svn/unbound/trunk@335 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-05-23 14:05:36 +00:00
parent 472e96622c
commit 42312206c9
14 changed files with 602 additions and 17 deletions

View file

@ -3,6 +3,7 @@
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

View file

@ -42,6 +42,8 @@
#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)
@ -52,3 +54,85 @@ 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);
}
}

View file

@ -109,4 +109,43 @@ struct delegpt_addr {
*/
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 */

237
iterator/iter_hints.c Normal file
View file

@ -0,0 +1,237 @@
/*
* 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;
}

115
iterator/iter_hints.h Normal file
View file

@ -0,0 +1,115 @@
/*
* 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 */

View file

@ -42,6 +42,7 @@
#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"
@ -65,6 +66,14 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
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]) {
if(!ipstrtoaddr(cfg->fwd_address, cfg->fwd_port,

View file

@ -49,6 +49,7 @@
#include "util/region-allocator.h"
#include "services/cache/rrset.h"
#include "iterator/iter_utils.h"
#include "iterator/iter_hints.h"
/** iterator init */
static int
@ -76,6 +77,8 @@ iter_deinit(struct module_env* env, int id)
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);
}
@ -135,6 +138,7 @@ iter_new(struct module_qstate* qstate, int id)
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,
@ -232,3 +236,29 @@ iter_get_funcblock()
{
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";
}
}

View file

@ -45,6 +45,8 @@
#include "services/outbound_list.h"
struct module_func_block;
struct delegpt;
struct packed_rrset_list;
struct iter_hints;
/**
* Global state for the iterator.
@ -61,7 +63,7 @@ struct iter_env {
* 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;
@ -156,7 +158,7 @@ struct iter_qstate {
* 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
@ -193,4 +195,11 @@ struct iter_qstate {
*/
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 */

View file

@ -180,14 +180,14 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt)
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;
}
@ -252,8 +252,8 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error,
/* 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;
}
}

View file

@ -471,3 +471,41 @@ dname_buffer_write(ldns_buffer* pkt, uint8_t* dname)
}
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;
}

View file

@ -127,13 +127,6 @@ void dname_pkt_copy(ldns_buffer* pkt, uint8_t* to, uint8_t* dname);
*/
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.
@ -161,4 +154,22 @@ int dname_count_size_labels(uint8_t* dname, size_t* size);
*/
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 */

View file

@ -218,6 +218,16 @@ struct packed_rrset {
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.

View file

@ -123,7 +123,7 @@ memdup(void* data, size_t len)
}
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";
@ -142,8 +142,8 @@ log_addr(struct sockaddr_storage* addr, socklen_t addrlen)
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

View file

@ -112,10 +112,12 @@ void* memdup(void* data, size_t len);
/**
* 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.