]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix #1397: Recursive DS lookups for AS112 zones names should recurse.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 7 Aug 2017 07:42:45 +0000 (07:42 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 7 Aug 2017 07:42:45 +0000 (07:42 +0000)
git-svn-id: file:///svn/unbound/trunk@4294 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/localzone.c
services/localzone.h
testdata/local_ds.rpl [new file with mode: 0644]
testdata/local_nodefault.rpl

index bacc3bfd3e22db6a8950d12389ad70814195cadd..11dc2701c70a4060fdbb804a3ce1cc3dd55f5f12 100644 (file)
@@ -1,3 +1,6 @@
+7 August 2017: Wouter
+       - Fix #1397: Recursive DS lookups for AS112 zones names should recurse.
+
 3 August 2017: Ralph
        - Remove unused iter_env member (ip6arpa_dname)
        - Do not reset rrset.bogus stats when called using stats_noreset.
index 1215f27d53cc828622d7acac8570c8db552752eb..6bde432e8d0973ca4ef3e21843b4c7cad2cd1180 100644 (file)
@@ -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 */
 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];
        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);
        *dclass = sldns_wirerr_get_class(rr, len, dname_len);
+       *dtype = sldns_wirerr_get_type(rr, len, dname_len);
        if(!*nm) {
                log_err("out of memory");
                return 0;
@@ -522,18 +524,18 @@ static int
 lz_enter_rr_str(struct local_zones* zones, const char* rr)
 {
        uint8_t* rr_name;
-       uint16_t rr_class;
+       uint16_t rr_class, rr_type;
        size_t len;
        int labs;
        struct local_zone* z;
        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);
                return 0;
        }
        labs = dname_count_size_labels(rr_name, &len);
        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) {
                lock_rw_unlock(&zones->lock);
                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() */
        for(p = cfg->local_data; p; p = p->next) {
                uint8_t* rr_name;
-               uint16_t rr_class;
+               uint16_t rr_class, rr_type;
                size_t len;
                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);
                        return 0;
                }
                labs = dname_count_size_labels(rr_name, &len);
                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) {
                                dclass = rr_class;
                                nm = rr_name;
@@ -1051,21 +1054,26 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
 
 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)
 {
        return local_zones_tags_lookup(zones, name, len, labs,
-               dclass, NULL, 0, 1);
+               dclass, dtype, NULL, 0, 1);
 }
 
 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)
 {
        rbnode_type* res = NULL;
        struct local_zone *result;
        struct local_zone key;
        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.dclass = dclass;
        key.name = name;
@@ -1581,7 +1589,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
                if(view->local_zones &&
                        (z = local_zones_lookup(view->local_zones,
                        qinfo->qname, qinfo->qname_len, labs,
-                       qinfo->qclass))) {
+                       qinfo->qclass, qinfo->qtype))) {
                        verbose(VERB_ALGO, 
                                "using localzone from view: %s", 
                                view->name);
@@ -1598,8 +1606,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
                /* try global local_zones tree */
                lock_rw_rdlock(&zones->lock);
                if(!(z = local_zones_tags_lookup(zones, qinfo->qname,
-                       qinfo->qname_len, labs, qinfo->qclass, taglist,
-                       taglen, 0))) {
+                       qinfo->qname_len, labs, qinfo->qclass, qinfo->qtype,
+                       taglist, taglen, 0))) {
                        lock_rw_unlock(&zones->lock);
                        return 0;
                }
@@ -1754,19 +1762,19 @@ int
 local_zones_add_RR(struct local_zones* zones, const char* rr)
 {
        uint8_t* rr_name;
-       uint16_t rr_class;
+       uint16_t rr_class, rr_type;
        size_t len;
        int labs;
        struct local_zone* z;
        int r;
-       if(!get_rr_nameclass(rr, &rr_name, &rr_class)) {
+       if(!get_rr_nameclass(rr, &rr_name, &rr_class, &rr_type)) {
                return 0;
        }
        labs = dname_count_size_labels(rr_name, &len);
        /* could first try readlock then get writelock if zone does not exist,
         * but we do not add enough RRs (from multiple threads) to optimize */
        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) {
                z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
                        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, 
        uint8_t* name, size_t len, int labs, uint16_t dclass)
 {
        /* find zone */
        struct local_zone* z;
        struct local_data* d;
+
+       /* remove DS */
+       lock_rw_rdlock(&zones->lock);
+       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);
+       z = local_zones_lookup(zones, name, len, labs, dclass, 0);
        if(!z) {
                /* no such zone, we're done */
                lock_rw_unlock(&zones->lock);
index fcdad41666d2c9074824c8f269c86cad6a159353..0a8759268bb295a8513abda92c113906b1bbedaf 100644 (file)
@@ -235,6 +235,7 @@ void local_zone_delete(struct local_zone* z);
  * @param len: length of name.
  * @param labs: labelcount of name.
  * @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 taglen: lenth of taglist.
  * @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.
  */
 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);
 
 /**
@@ -253,10 +254,12 @@ struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
  * @param len: length of name.
  * @param labs: labelcount of name.
  * @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.
  */
 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 
diff --git a/testdata/local_ds.rpl b/testdata/local_ds.rpl
new file mode 100644 (file)
index 0000000..58b3e22
--- /dev/null
@@ -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
index 91243d19fb6db8d13395d4f2c9578b6580a5552a..79419624482933b0f7a6360d5f08f1c7b55fc848 100644 (file)
@@ -30,7 +30,7 @@ MATCH opcode qtype qname
 ADJUST copy_id
 REPLY QR AA NXDOMAIN
 SECTION QUESTION
-40.30.20.10.in-addr-arpa. IN PTR
+40.30.20.10.in-addr.arpa. IN PTR
 SECTION ANSWER
 SECTION AUTHORITY
 . IN SOA invalid. invalid. 1 2 3 4 5
@@ -41,7 +41,7 @@ STEP 1 QUERY
 ENTRY_BEGIN
 REPLY RD DO
 SECTION QUESTION
-40.30.20.10.in-addr-arpa. IN PTR
+40.30.20.10.in-addr.arpa. IN PTR
 ENTRY_END
 ; not blocked!
 
@@ -51,7 +51,7 @@ ENTRY_BEGIN
 MATCH all
 REPLY QR RD RA DO NXDOMAIN
 SECTION QUESTION
-40.30.20.10.in-addr-arpa. IN PTR
+40.30.20.10.in-addr.arpa. IN PTR
 SECTION ANSWER
 SECTION AUTHORITY
 . IN SOA invalid. invalid. 1 2 3 4 5