mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- Fix #1397: Recursive DS lookups for AS112 zones names should recurse.
git-svn-id: file:///svn/unbound/trunk@4294 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
3de694be05
commit
1159e53618
5 changed files with 172 additions and 22 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
7 August 2017: Wouter
|
||||||
|
- Fix #1397: Recursive DS lookups for AS112 zones names should recurse.
|
||||||
|
|
||||||
3 August 2017: Ralph
|
3 August 2017: Ralph
|
||||||
- Remove unused iter_env member (ip6arpa_dname)
|
- Remove unused iter_env member (ip6arpa_dname)
|
||||||
- Do not reset rrset.bogus stats when called using stats_noreset.
|
- Do not reset rrset.bogus stats when called using stats_noreset.
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,8 @@ rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
|
||||||
|
|
||||||
/** return name and class of rr; parses string */
|
/** return name and class of rr; parses string */
|
||||||
static int
|
static int
|
||||||
get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass)
|
get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass,
|
||||||
|
uint16_t* dtype)
|
||||||
{
|
{
|
||||||
uint8_t rr[LDNS_RR_BUF_SIZE];
|
uint8_t rr[LDNS_RR_BUF_SIZE];
|
||||||
size_t len = sizeof(rr), dname_len = 0;
|
size_t len = sizeof(rr), dname_len = 0;
|
||||||
|
|
@ -274,6 +275,7 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass)
|
||||||
}
|
}
|
||||||
*nm = memdup(rr, dname_len);
|
*nm = memdup(rr, dname_len);
|
||||||
*dclass = sldns_wirerr_get_class(rr, len, dname_len);
|
*dclass = sldns_wirerr_get_class(rr, len, dname_len);
|
||||||
|
*dtype = sldns_wirerr_get_type(rr, len, dname_len);
|
||||||
if(!*nm) {
|
if(!*nm) {
|
||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -522,18 +524,18 @@ static int
|
||||||
lz_enter_rr_str(struct local_zones* zones, const char* rr)
|
lz_enter_rr_str(struct local_zones* zones, const char* rr)
|
||||||
{
|
{
|
||||||
uint8_t* rr_name;
|
uint8_t* rr_name;
|
||||||
uint16_t rr_class;
|
uint16_t rr_class, rr_type;
|
||||||
size_t len;
|
size_t len;
|
||||||
int labs;
|
int labs;
|
||||||
struct local_zone* z;
|
struct local_zone* z;
|
||||||
int r;
|
int r;
|
||||||
if(!get_rr_nameclass(rr, &rr_name, &rr_class)) {
|
if(!get_rr_nameclass(rr, &rr_name, &rr_class, &rr_type)) {
|
||||||
log_err("bad rr %s", rr);
|
log_err("bad rr %s", rr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
labs = dname_count_size_labels(rr_name, &len);
|
labs = dname_count_size_labels(rr_name, &len);
|
||||||
lock_rw_rdlock(&zones->lock);
|
lock_rw_rdlock(&zones->lock);
|
||||||
z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
|
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
|
||||||
if(!z) {
|
if(!z) {
|
||||||
lock_rw_unlock(&zones->lock);
|
lock_rw_unlock(&zones->lock);
|
||||||
fatal_exit("internal error: no zone for rr %s", rr);
|
fatal_exit("internal error: no zone for rr %s", rr);
|
||||||
|
|
@ -911,16 +913,17 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
|
||||||
init_parents(zones); /* to enable local_zones_lookup() */
|
init_parents(zones); /* to enable local_zones_lookup() */
|
||||||
for(p = cfg->local_data; p; p = p->next) {
|
for(p = cfg->local_data; p; p = p->next) {
|
||||||
uint8_t* rr_name;
|
uint8_t* rr_name;
|
||||||
uint16_t rr_class;
|
uint16_t rr_class, rr_type;
|
||||||
size_t len;
|
size_t len;
|
||||||
int labs;
|
int labs;
|
||||||
if(!get_rr_nameclass(p->str, &rr_name, &rr_class)) {
|
if(!get_rr_nameclass(p->str, &rr_name, &rr_class, &rr_type)) {
|
||||||
log_err("Bad local-data RR %s", p->str);
|
log_err("Bad local-data RR %s", p->str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
labs = dname_count_size_labels(rr_name, &len);
|
labs = dname_count_size_labels(rr_name, &len);
|
||||||
lock_rw_rdlock(&zones->lock);
|
lock_rw_rdlock(&zones->lock);
|
||||||
if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) {
|
if(!local_zones_lookup(zones, rr_name, len, labs, rr_class,
|
||||||
|
rr_type)) {
|
||||||
if(!have_name) {
|
if(!have_name) {
|
||||||
dclass = rr_class;
|
dclass = rr_class;
|
||||||
nm = rr_name;
|
nm = rr_name;
|
||||||
|
|
@ -1051,21 +1054,26 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
|
||||||
|
|
||||||
struct local_zone*
|
struct local_zone*
|
||||||
local_zones_lookup(struct local_zones* zones,
|
local_zones_lookup(struct local_zones* zones,
|
||||||
uint8_t* name, size_t len, int labs, uint16_t dclass)
|
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype)
|
||||||
{
|
{
|
||||||
return local_zones_tags_lookup(zones, name, len, labs,
|
return local_zones_tags_lookup(zones, name, len, labs,
|
||||||
dclass, NULL, 0, 1);
|
dclass, dtype, NULL, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct local_zone*
|
struct local_zone*
|
||||||
local_zones_tags_lookup(struct local_zones* zones,
|
local_zones_tags_lookup(struct local_zones* zones,
|
||||||
uint8_t* name, size_t len, int labs, uint16_t dclass,
|
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
|
||||||
uint8_t* taglist, size_t taglen, int ignoretags)
|
uint8_t* taglist, size_t taglen, int ignoretags)
|
||||||
{
|
{
|
||||||
rbnode_type* res = NULL;
|
rbnode_type* res = NULL;
|
||||||
struct local_zone *result;
|
struct local_zone *result;
|
||||||
struct local_zone key;
|
struct local_zone key;
|
||||||
int m;
|
int m;
|
||||||
|
/* for type DS use a zone higher when on a zonecut */
|
||||||
|
if(dtype == LDNS_RR_TYPE_DS && !dname_is_root(name)) {
|
||||||
|
dname_remove_label(&name, &len);
|
||||||
|
labs--;
|
||||||
|
}
|
||||||
key.node.key = &key;
|
key.node.key = &key;
|
||||||
key.dclass = dclass;
|
key.dclass = dclass;
|
||||||
key.name = name;
|
key.name = name;
|
||||||
|
|
@ -1581,7 +1589,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||||
if(view->local_zones &&
|
if(view->local_zones &&
|
||||||
(z = local_zones_lookup(view->local_zones,
|
(z = local_zones_lookup(view->local_zones,
|
||||||
qinfo->qname, qinfo->qname_len, labs,
|
qinfo->qname, qinfo->qname_len, labs,
|
||||||
qinfo->qclass))) {
|
qinfo->qclass, qinfo->qtype))) {
|
||||||
verbose(VERB_ALGO,
|
verbose(VERB_ALGO,
|
||||||
"using localzone from view: %s",
|
"using localzone from view: %s",
|
||||||
view->name);
|
view->name);
|
||||||
|
|
@ -1598,8 +1606,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||||
/* try global local_zones tree */
|
/* try global local_zones tree */
|
||||||
lock_rw_rdlock(&zones->lock);
|
lock_rw_rdlock(&zones->lock);
|
||||||
if(!(z = local_zones_tags_lookup(zones, qinfo->qname,
|
if(!(z = local_zones_tags_lookup(zones, qinfo->qname,
|
||||||
qinfo->qname_len, labs, qinfo->qclass, taglist,
|
qinfo->qname_len, labs, qinfo->qclass, qinfo->qtype,
|
||||||
taglen, 0))) {
|
taglist, taglen, 0))) {
|
||||||
lock_rw_unlock(&zones->lock);
|
lock_rw_unlock(&zones->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1754,19 +1762,19 @@ int
|
||||||
local_zones_add_RR(struct local_zones* zones, const char* rr)
|
local_zones_add_RR(struct local_zones* zones, const char* rr)
|
||||||
{
|
{
|
||||||
uint8_t* rr_name;
|
uint8_t* rr_name;
|
||||||
uint16_t rr_class;
|
uint16_t rr_class, rr_type;
|
||||||
size_t len;
|
size_t len;
|
||||||
int labs;
|
int labs;
|
||||||
struct local_zone* z;
|
struct local_zone* z;
|
||||||
int r;
|
int r;
|
||||||
if(!get_rr_nameclass(rr, &rr_name, &rr_class)) {
|
if(!get_rr_nameclass(rr, &rr_name, &rr_class, &rr_type)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
labs = dname_count_size_labels(rr_name, &len);
|
labs = dname_count_size_labels(rr_name, &len);
|
||||||
/* could first try readlock then get writelock if zone does not exist,
|
/* could first try readlock then get writelock if zone does not exist,
|
||||||
* but we do not add enough RRs (from multiple threads) to optimize */
|
* but we do not add enough RRs (from multiple threads) to optimize */
|
||||||
lock_rw_wrlock(&zones->lock);
|
lock_rw_wrlock(&zones->lock);
|
||||||
z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
|
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
|
||||||
if(!z) {
|
if(!z) {
|
||||||
z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
|
z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
|
||||||
local_zone_transparent);
|
local_zone_transparent);
|
||||||
|
|
@ -1818,14 +1826,47 @@ del_empty_term(struct local_zone* z, struct local_data* d,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** find and remove type from list in domain struct */
|
||||||
|
static void
|
||||||
|
del_local_rrset(struct local_data* d, uint16_t dtype)
|
||||||
|
{
|
||||||
|
struct local_rrset* prev=NULL, *p=d->rrsets;
|
||||||
|
while(p && ntohs(p->rrset->rk.type) != dtype) {
|
||||||
|
prev = p;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
if(!p)
|
||||||
|
return; /* rrset type not found */
|
||||||
|
/* unlink it */
|
||||||
|
if(prev) prev->next = p->next;
|
||||||
|
else d->rrsets = p->next;
|
||||||
|
/* no memory recycling for zone deletions ... */
|
||||||
|
}
|
||||||
|
|
||||||
void local_zones_del_data(struct local_zones* zones,
|
void local_zones_del_data(struct local_zones* zones,
|
||||||
uint8_t* name, size_t len, int labs, uint16_t dclass)
|
uint8_t* name, size_t len, int labs, uint16_t dclass)
|
||||||
{
|
{
|
||||||
/* find zone */
|
/* find zone */
|
||||||
struct local_zone* z;
|
struct local_zone* z;
|
||||||
struct local_data* d;
|
struct local_data* d;
|
||||||
|
|
||||||
|
/* remove DS */
|
||||||
lock_rw_rdlock(&zones->lock);
|
lock_rw_rdlock(&zones->lock);
|
||||||
z = local_zones_lookup(zones, name, len, labs, dclass);
|
z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS);
|
||||||
|
if(z) {
|
||||||
|
lock_rw_wrlock(&z->lock);
|
||||||
|
d = lz_find_node(z, name, len, labs);
|
||||||
|
if(d) {
|
||||||
|
del_local_rrset(d, LDNS_RR_TYPE_DS);
|
||||||
|
del_empty_term(z, d, name, len, labs);
|
||||||
|
}
|
||||||
|
lock_rw_unlock(&z->lock);
|
||||||
|
}
|
||||||
|
lock_rw_unlock(&zones->lock);
|
||||||
|
|
||||||
|
/* remove other types */
|
||||||
|
lock_rw_rdlock(&zones->lock);
|
||||||
|
z = local_zones_lookup(zones, name, len, labs, dclass, 0);
|
||||||
if(!z) {
|
if(!z) {
|
||||||
/* no such zone, we're done */
|
/* no such zone, we're done */
|
||||||
lock_rw_unlock(&zones->lock);
|
lock_rw_unlock(&zones->lock);
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,7 @@ void local_zone_delete(struct local_zone* z);
|
||||||
* @param len: length of name.
|
* @param len: length of name.
|
||||||
* @param labs: labelcount of name.
|
* @param labs: labelcount of name.
|
||||||
* @param dclass: class to lookup.
|
* @param dclass: class to lookup.
|
||||||
|
* @param dtype: type to lookup, if type DS a zone higher is used for zonecuts.
|
||||||
* @param taglist: taglist to lookup.
|
* @param taglist: taglist to lookup.
|
||||||
* @param taglen: lenth of taglist.
|
* @param taglen: lenth of taglist.
|
||||||
* @param ignoretags: lookup zone by name and class, regardless the
|
* @param ignoretags: lookup zone by name and class, regardless the
|
||||||
|
|
@ -242,7 +243,7 @@ void local_zone_delete(struct local_zone* z);
|
||||||
* @return closest local_zone or NULL if no covering zone is found.
|
* @return closest local_zone or NULL if no covering zone is found.
|
||||||
*/
|
*/
|
||||||
struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
|
struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
|
||||||
uint8_t* name, size_t len, int labs, uint16_t dclass,
|
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
|
||||||
uint8_t* taglist, size_t taglen, int ignoretags);
|
uint8_t* taglist, size_t taglen, int ignoretags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -253,10 +254,12 @@ struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
|
||||||
* @param len: length of name.
|
* @param len: length of name.
|
||||||
* @param labs: labelcount of name.
|
* @param labs: labelcount of name.
|
||||||
* @param dclass: class to lookup.
|
* @param dclass: class to lookup.
|
||||||
|
* @param dtype: type of the record, if type DS then a zone higher up is found
|
||||||
|
* pass 0 to just plain find a zone for a name.
|
||||||
* @return closest local_zone or NULL if no covering zone is found.
|
* @return closest local_zone or NULL if no covering zone is found.
|
||||||
*/
|
*/
|
||||||
struct local_zone* local_zones_lookup(struct local_zones* zones,
|
struct local_zone* local_zones_lookup(struct local_zones* zones,
|
||||||
uint8_t* name, size_t len, int labs, uint16_t dclass);
|
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug helper. Print all zones
|
* Debug helper. Print all zones
|
||||||
|
|
|
||||||
103
testdata/local_ds.rpl
vendored
Normal file
103
testdata/local_ds.rpl
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
; config options
|
||||||
|
; The island of trust is at example.com
|
||||||
|
server:
|
||||||
|
|
||||||
|
stub-zone:
|
||||||
|
name: "."
|
||||||
|
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||||
|
CONFIG_END
|
||||||
|
|
||||||
|
SCENARIO_BEGIN Test local data for as112 zone with DS lookup.
|
||||||
|
|
||||||
|
; K.ROOT-SERVERS.NET.
|
||||||
|
RANGE_BEGIN 0 100
|
||||||
|
ADDRESS 193.0.14.129
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
. IN NS
|
||||||
|
SECTION ANSWER
|
||||||
|
. IN NS K.ROOT-SERVERS.NET.
|
||||||
|
SECTION ADDITIONAL
|
||||||
|
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
arpa. IN NS
|
||||||
|
SECTION ANSWER
|
||||||
|
SECTION AUTHORITY
|
||||||
|
. IN NS K.ROOT-SERVERS.NET.
|
||||||
|
SECTION ADDITIONAL
|
||||||
|
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
in-addr.arpa. IN NS
|
||||||
|
SECTION ANSWER
|
||||||
|
SECTION AUTHORITY
|
||||||
|
. IN NS K.ROOT-SERVERS.NET.
|
||||||
|
SECTION ADDITIONAL
|
||||||
|
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH opcode qtype qname
|
||||||
|
ADJUST copy_id
|
||||||
|
REPLY QR AA NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
10.in-addr.arpa. IN DS
|
||||||
|
SECTION ANSWER
|
||||||
|
SECTION AUTHORITY
|
||||||
|
10.in-addr.arpa. IN NSEC 11.in-addr.arpa NSEC RRSIG
|
||||||
|
. IN SOA invalid. invalid. 1 2 3 4 5
|
||||||
|
ENTRY_END
|
||||||
|
RANGE_END
|
||||||
|
|
||||||
|
STEP 1 QUERY
|
||||||
|
ENTRY_BEGIN
|
||||||
|
REPLY RD DO
|
||||||
|
SECTION QUESTION
|
||||||
|
40.30.20.10.in-addr.arpa. IN PTR
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
STEP 10 CHECK_ANSWER
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH all
|
||||||
|
REPLY QR RD RA AA DO NXDOMAIN
|
||||||
|
SECTION QUESTION
|
||||||
|
40.30.20.10.in-addr.arpa. IN PTR
|
||||||
|
SECTION ANSWER
|
||||||
|
SECTION AUTHORITY
|
||||||
|
10.in-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
STEP 20 QUERY
|
||||||
|
ENTRY_BEGIN
|
||||||
|
REPLY RD DO
|
||||||
|
SECTION QUESTION
|
||||||
|
10.in-addr.arpa. IN DS
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
STEP 30 CHECK_ANSWER
|
||||||
|
ENTRY_BEGIN
|
||||||
|
MATCH all
|
||||||
|
REPLY QR RD RA DO NOERROR
|
||||||
|
SECTION QUESTION
|
||||||
|
10.in-addr.arpa. IN DS
|
||||||
|
SECTION ANSWER
|
||||||
|
SECTION AUTHORITY
|
||||||
|
10.in-addr.arpa. IN NSEC 11.in-addr.arpa NSEC RRSIG
|
||||||
|
. IN SOA invalid. invalid. 1 2 3 4 5
|
||||||
|
ENTRY_END
|
||||||
|
|
||||||
|
SCENARIO_END
|
||||||
6
testdata/local_nodefault.rpl
vendored
6
testdata/local_nodefault.rpl
vendored
|
|
@ -30,7 +30,7 @@ MATCH opcode qtype qname
|
||||||
ADJUST copy_id
|
ADJUST copy_id
|
||||||
REPLY QR AA NXDOMAIN
|
REPLY QR AA NXDOMAIN
|
||||||
SECTION QUESTION
|
SECTION QUESTION
|
||||||
40.30.20.10.in-addr-arpa. IN PTR
|
40.30.20.10.in-addr.arpa. IN PTR
|
||||||
SECTION ANSWER
|
SECTION ANSWER
|
||||||
SECTION AUTHORITY
|
SECTION AUTHORITY
|
||||||
. IN SOA invalid. invalid. 1 2 3 4 5
|
. IN SOA invalid. invalid. 1 2 3 4 5
|
||||||
|
|
@ -41,7 +41,7 @@ STEP 1 QUERY
|
||||||
ENTRY_BEGIN
|
ENTRY_BEGIN
|
||||||
REPLY RD DO
|
REPLY RD DO
|
||||||
SECTION QUESTION
|
SECTION QUESTION
|
||||||
40.30.20.10.in-addr-arpa. IN PTR
|
40.30.20.10.in-addr.arpa. IN PTR
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
; not blocked!
|
; not blocked!
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ ENTRY_BEGIN
|
||||||
MATCH all
|
MATCH all
|
||||||
REPLY QR RD RA DO NXDOMAIN
|
REPLY QR RD RA DO NXDOMAIN
|
||||||
SECTION QUESTION
|
SECTION QUESTION
|
||||||
40.30.20.10.in-addr-arpa. IN PTR
|
40.30.20.10.in-addr.arpa. IN PTR
|
||||||
SECTION ANSWER
|
SECTION ANSWER
|
||||||
SECTION AUTHORITY
|
SECTION AUTHORITY
|
||||||
. IN SOA invalid. invalid. 1 2 3 4 5
|
. IN SOA invalid. invalid. 1 2 3 4 5
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue