]> git.ipfire.org Git - people/ms/libloc.git/commitdiff
network-tree: Run deduplication once for each family
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 21 Feb 2024 14:45:43 +0000 (14:45 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 21 Feb 2024 14:45:43 +0000 (14:45 +0000)
This probably never becomes a real problem, but we did not clear the
stack properly once we switched family when iterating through the
entire tree in one go.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/network-tree.c

index d8442c9e9759842c31680bbef1aa025c544a581a..e6a4f85f5007dd96728956f9f60b6714864d1349 100644 (file)
@@ -479,7 +479,8 @@ ERROR:
 struct loc_network_tree_dedup_ctx {
        struct loc_network_tree* tree;
        struct loc_network_list* stack;
-       unsigned int removed;
+       unsigned int* removed;
+       int family;
 };
 
 static int loc_network_tree_dedup_step(struct loc_network* network, void* data) {
@@ -508,7 +509,7 @@ static int loc_network_tree_dedup_step(struct loc_network* network, void* data)
                                        return r;
 
                                // Count
-                               ctx->removed++;
+                               (*ctx->removed)++;
 
                                // Once we removed the subnet, we are done
                                goto END;
@@ -531,11 +532,20 @@ END:
        return r;
 }
 
-static int loc_network_tree_dedup(struct loc_network_tree* tree) {
+static int loc_network_tree_dedup_filter(struct loc_network* network, void* data) {
+       const struct loc_network_tree_dedup_ctx* ctx = data;
+
+       // Match address family
+       return ctx->family == loc_network_address_family(network);
+}
+
+static int loc_network_tree_dedup_one(struct loc_network_tree* tree,
+               const int family, unsigned int* removed) {
        struct loc_network_tree_dedup_ctx ctx = {
                .tree    = tree,
                .stack   = NULL,
-               .removed = 0,
+               .removed = removed,
+               .family  = family,
        };
        int r;
 
@@ -544,12 +554,11 @@ static int loc_network_tree_dedup(struct loc_network_tree* tree) {
                return r;
 
        // Walk through the entire tree
-       r = loc_network_tree_walk(tree, NULL, loc_network_tree_dedup_step, &ctx);
+       r = loc_network_tree_walk(tree,
+               loc_network_tree_dedup_filter, loc_network_tree_dedup_step, &ctx);
        if (r)
                goto ERROR;
 
-       DEBUG(tree->ctx, "%u network(s) have been removed\n", ctx.removed);
-
 ERROR:
        if (ctx.stack)
                loc_network_list_unref(ctx.stack);
@@ -557,6 +566,23 @@ ERROR:
        return r;
 }
 
+static int loc_network_tree_dedup(struct loc_network_tree* tree) {
+       unsigned int removed = 0;
+       int r;
+
+       r = loc_network_tree_dedup_one(tree, AF_INET6, &removed);
+       if (r)
+               return r;
+
+       r = loc_network_tree_dedup_one(tree, AF_INET, &removed);
+       if (r)
+               return r;
+
+       DEBUG(tree->ctx, "%u network(s) have been removed\n", removed);
+
+       return 0;
+}
+
 static int loc_network_tree_delete_node(struct loc_network_tree* tree,
                struct loc_network_tree_node** node) {
        struct loc_network_tree_node* n = *node;