]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
references to parent nodes so deleting will be easier later on
authorYuri Schaeffer <yuri@nlnetlabs.nl>
Fri, 11 Oct 2013 14:08:05 +0000 (14:08 +0000)
committerYuri Schaeffer <yuri@nlnetlabs.nl>
Fri, 11 Oct 2013 14:08:05 +0000 (14:08 +0000)
git-svn-id: file:///svn/unbound/branches/edns-subnet@2976 be551aaa-1e26-0410-a405-d3ace91eadb9

edns-subnet/addrtree.c
edns-subnet/addrtree.h
testdata/subnet_val_positive_client.crpl

index fb98d785c4ec8963f9e9667fb3c9f8a4c669fdb9..d19d7baf0e3c20e99041d380bae910bd5fdb1aab 100644 (file)
@@ -20,8 +20,9 @@
  * @param addrlen: length of relevant part of key for this node
  * @return new addredge or NULL on failure
  */
-static struct addredge* 
-edge_create(struct addrnode* node, const addrkey_t* addr, addrlen_t addrlen)
+static struct addredge * 
+edge_create(struct addrnode *node, const addrkey_t *addr, 
+       addrlen_t addrlen, struct addrnode *parent_node, int parent_index)
 {
        size_t n;
        struct addredge* edge = (struct addredge*)malloc( sizeof (*edge) );
@@ -29,6 +30,8 @@ edge_create(struct addrnode* node, const addrkey_t* addr, addrlen_t addrlen)
                return NULL;
        edge->node = node;
        edge->len = addrlen;
+       edge->parent_index = parent_index;
+       edge->parent_node = parent_node;
        n = (size_t)((addrlen / KEYWIDTH) + ((addrlen % KEYWIDTH != 0)?1:0)); /*ceil()*/
        edge->str = (addrkey_t*)calloc(n, sizeof (addrkey_t));
        if (!edge->str) {
@@ -36,6 +39,9 @@ edge_create(struct addrnode* node, const addrkey_t* addr, addrlen_t addrlen)
                return NULL;
        }
        memcpy(edge->str, addr, n * sizeof (addrkey_t));
+       /* Only manipulate other objects after successful alloc */
+       node->parent_edge = edge;
+       parent_node->edge[parent_index] = edge;
        return edge;
 }
 
@@ -60,6 +66,7 @@ node_create(struct addrtree *tree, void* elem, addrlen_t scope,
        node->ttl = ttl;
        node->edge[0] = NULL;
        node->edge[1] = NULL;
+       node->parent_edge = NULL;
        return node;
 }
 
@@ -132,26 +139,27 @@ clean_node(struct addrtree* tree, struct addrnode* node)
  * free'd.
  * @param tree: Tree the node lives in.
  * @param node: Node to be freed
- * @param parentnode: parent of node, may be NULL if node is rootnode.
- * @param parentedge: edge between parentnode and node. May be NULL iff
- *        parentnode is NULL
  */
 static void
-purge_node(struct addrtree* tree, struct addrnode* node, 
-       struct addrnode* parentnode, struct addredge* parentedge)
+purge_node(struct addrtree *tree, struct addrnode *node)
 {
-       struct addredge *child_edge = NULL;
-       int childcount = (node->edge[0] != NULL) + (node->edge[1] != NULL);
+       struct addredge *parent_edge, *child_edge = NULL;
+       int index;
+       int keep = node->edge[0] && node->edge[1];
+       
        clean_node(tree, node);
-       if (childcount == 2 || !parentnode)
-               return;
-       log_assert(parentedge); /* parent node implies parent edge */
-       if (childcount == 1) { /* Fix reference */
-               child_edge = node->edge[!node->edge[0]];
+       parent_edge = node->parent_edge;
+       if (keep || !parent_edge) return;
+       index = parent_edge->parent_index;
+       child_edge = node->edge[!node->edge[0]];
+       if (child_edge) {
+               child_edge->parent_node  = parent_edge->parent_node;
+               child_edge->parent_index = index;
        }
-       parentnode->edge[parentedge != parentnode->edge[0]] = child_edge;
-       free(parentedge->str);
-       free(parentedge);
+       parent_edge->parent_node->edge[index] = child_edge;
+       free(parent_edge->str);
+       free(parent_edge);
+       free(node);
 }
 
 /** 
@@ -289,15 +297,18 @@ addrtree_insert(struct addrtree* tree, const addrkey_t* addr,
                        /* Purge all expired nodes on path */
                        if (!edge->node->elem || edge->node->ttl >= now)
                                break;
-                       purge_node(tree, edge->node, node, edge);
+                       purge_node(tree, edge->node);
                        edge = node->edge[index];
                }
                /* Case 2: New leafnode */
                if (!edge) {
                        newnode = node_create(tree, elem, scope, ttl);
-                       node->edge[index] = edge_create(newnode, addr, sourcemask);
-                       if (!node->edge[index])
+                       if (!newnode) return;
+                       if (!edge_create(newnode, addr, sourcemask, node, index)) {
+                               clean_node(tree, newnode);
                                free(newnode);
+                               return;
+                       }
                        return;
                }
                /* Case 3: Traverse edge */
@@ -314,14 +325,16 @@ addrtree_insert(struct addrtree* tree, const addrkey_t* addr,
                /* Case 4: split. */
                if (!(newnode = node_create(tree, NULL, 0, 0)))
                        return;
-               if (!(newedge = edge_create(newnode, addr, common))) {
+               if (!edge_create(newnode, addr, common, node, index)) {
                        clean_node(tree, newnode);
                        free(newnode);
                        return;
-               }               
-               node->edge[index] = newedge;
+               }
+               /** connect existing child to our new node */
                index = (uint8_t)getbit(edge->str, edge->len, common);
                newnode->edge[index] = edge;
+               edge->parent_node = newnode;
+               edge->parent_index = index;
                
                if (common == sourcemask) {
                        /* Data is stored in the node */
@@ -332,7 +345,11 @@ addrtree_insert(struct addrtree* tree, const addrkey_t* addr,
                        /* Data is stored in other leafnode */
                        node = newnode;
                        newnode = node_create(tree, elem, scope, ttl);
-                       node->edge[index^1] = edge_create(newnode, addr, sourcemask);
+                       if (!edge_create(newnode, addr, sourcemask, node, index^1)) {
+                               clean_node(tree, newnode);
+                               free(newnode);
+                               return;
+                       }
                }
                return;
        }
index 94db90388c4c651b924a08de0af4e7c88787e58c..b909f156ff241b6dfaf1518dea99e94d2171ddb3 100644 (file)
@@ -57,6 +57,8 @@ struct addrnode {
        addrlen_t scope;
        /** A node can have 0-2 edges, set to NULL for unused */
        struct addredge* edge[2];
+       /** edge between this node and parent */
+       struct addredge* parent_edge;
 };
 
 struct addredge {
@@ -66,6 +68,9 @@ struct addredge {
        addrlen_t len;
        /** child node this edge is connected to */
        struct addrnode* node;
+       /** Ptr in parent node to self */
+       struct addrnode* parent_node;
+       int parent_index;
 };
 
 /**
index 6d69233c1fa430ae27271c7885ba049f4d3432d5..ea0f6fa9d433341ef6aeddbf44a9874e894676f1 100644 (file)
@@ -37,7 +37,7 @@ RANGE_BEGIN 0 100
        ENTRY_END
 
        ENTRY_BEGIN
-               MATCH opcode qtype qname ednsdata
+               MATCH opcode qtype qname
                ADJUST copy_id
                REPLY QR NOERROR
                SECTION QUESTION
@@ -45,14 +45,6 @@ RANGE_BEGIN 0 100
                SECTION AUTHORITY
                        com.    IN NS   a.gtld-servers.net.
                SECTION ADDITIONAL
-                       HEX_EDNSDATA_BEGIN
-                                                       ; client is 127.0.0.1
-                               50 fa           ; OPC
-                               00 07           ; option length
-                               00 01           ; Family
-                               11 00           ; source mask, scopemask
-                               7f 00 00        ; address
-                       HEX_EDNSDATA_END
                        a.gtld-servers.net.     IN      A       192.5.6.30
        ENTRY_END
 RANGE_END
@@ -76,7 +68,7 @@ RANGE_BEGIN 0 100
        ENTRY_END
 
        ENTRY_BEGIN
-               MATCH opcode qtype qname ednsdata
+               MATCH opcode qtype qname
                ADJUST copy_id
                REPLY QR NOERROR
                SECTION QUESTION
@@ -84,14 +76,6 @@ RANGE_BEGIN 0 100
                SECTION AUTHORITY
                        example.com.    IN NS   ns.example.com.
                SECTION ADDITIONAL
-                       HEX_EDNSDATA_BEGIN
-                                                       ; client is 127.0.0.1
-                               50 fa           ; OPC
-                               00 07           ; option length
-                               00 01           ; Family
-                               11 00           ; source mask, scopemask
-                               7f 00 00        ; address
-                       HEX_EDNSDATA_END
                        ns.example.com.         IN      A       1.2.3.4
        ENTRY_END
 RANGE_END
@@ -167,10 +151,16 @@ RANGE_END
 STEP 1 QUERY
 ENTRY_BEGIN
        HEX_ANSWER_BEGIN;
-               00 00 01 00 00 01 00 00 00 00 00 01 03 77 77 77
-               07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00
-               01 00 00 29 10 00 00 00 80 00 00 0b 50 fa 00 07
-               00 01 11 00 7f 00 00
+               00 00 01 00 00 01 00 00         ;ID 0
+               00 00 00 01 03 77 77 77         ; www.example.com A? (DO)
+               07 65 78 61 6d 70 6c 65 
+               03 63 6f 6d 00 00 01 00
+               01 00 00 29 10 00 00 00 
+               80 00 00 0b
+               
+               50 fa 00 07                                     ; OPC, optlen
+               00 01 11 00                                     ; ip4, scope 17, source 0
+               7f 00 00                                        ;127.0.0.0/17
        HEX_ANSWER_END
 ENTRY_END