From f3e02bc511ecf71413b8a5729d1086df9c4b2f09 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Thu, 28 Dec 2017 18:07:11 +0000 Subject: [PATCH] Write networks to the database Signed-off-by: Michael Tremer --- src/loc/format.h | 8 +++++-- src/loc/network.h | 7 ++++++ src/network.c | 59 ++++++++++++++++++++++++++++++++++++++++------ src/test-network.c | 33 ++++++++++++++++++++++++++ src/writer.c | 39 ++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 9 deletions(-) diff --git a/src/loc/format.h b/src/loc/format.h index c4690d5..1f36aae 100644 --- a/src/loc/format.h +++ b/src/loc/format.h @@ -45,17 +45,21 @@ struct loc_database_header_v0 { uint32_t as_offset; uint32_t as_length; + // Tells us where the networks start + uint32_t networks_offset; + uint32_t networks_length; + // Tells us where the pool starts uint32_t pool_offset; uint32_t pool_length; }; -struct loc_database_network_v0 { +struct loc_database_network_node_v0 { uint32_t zero; uint32_t one; }; -struct loc_database_network_node_v0 { +struct loc_database_network_v0 { // The start address will be encoded in the tree uint8_t prefix; diff --git a/src/loc/network.h b/src/loc/network.h index cb95f1a..daf97d4 100644 --- a/src/loc/network.h +++ b/src/loc/network.h @@ -20,6 +20,7 @@ #include #include +#include struct loc_network; int loc_network_new(struct loc_ctx* ctx, struct loc_network** network, @@ -33,10 +34,16 @@ char* loc_network_str(struct loc_network* network); const char* loc_network_get_country_code(struct loc_network* network); int loc_network_set_country_code(struct loc_network* network, const char* country_code); +int loc_network_to_database_v0(struct loc_network* network, struct loc_database_network_v0* dbobj); + struct loc_network_tree; int loc_network_tree_new(struct loc_ctx* ctx, struct loc_network_tree** tree); struct loc_network_tree* loc_network_tree_unref(struct loc_network_tree* tree); +int loc_network_tree_walk(struct loc_network_tree* tree, + int(*filter_callback)(struct loc_network* network, void* data), + int(*callback)(struct loc_network* network, void* data), void* data); int loc_network_tree_dump(struct loc_network_tree* tree); int loc_network_tree_add_network(struct loc_network_tree* tree, struct loc_network* network); +size_t loc_network_tree_count_networks(struct loc_network_tree* tree); #endif diff --git a/src/network.c b/src/network.c index bf11f2a..bc359f6 100644 --- a/src/network.c +++ b/src/network.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -168,6 +169,24 @@ LOC_EXPORT int loc_network_set_country_code(struct loc_network* network, const c return 0; } +LOC_EXPORT int loc_network_to_database_v0(struct loc_network* network, struct loc_database_network_v0* dbobj) { + dbobj->prefix = htobe16(network->prefix); + + // Add country code + for (unsigned int i = 0; i < 2; i++) { + dbobj->country_code[i] = network->country_code ? network->country_code[i] : '\0'; + } + + // Add ASN + uint32_t asn = 0; + if (network->as) { + asn = loc_as_get_number(network->as); + } + dbobj->asn = htobe32(asn); + + return 0; +} + struct loc_network_tree { struct loc_ctx* ctx; int refcount; @@ -239,13 +258,14 @@ static struct loc_network_tree_node* loc_network_tree_get_path(struct loc_networ } static int __loc_network_tree_walk(struct loc_ctx* ctx, struct loc_network_tree_node* node, - int(*filter_callback)(struct loc_network* network), int(*callback)(struct loc_network* network)) { + int(*filter_callback)(struct loc_network* network, void* data), + int(*callback)(struct loc_network* network, void* data), void* data) { int r; // Finding a network ends the walk here if (node->network) { if (filter_callback) { - int f = filter_callback(node->network); + int f = filter_callback(node->network, data); if (f < 0) return f; @@ -254,21 +274,21 @@ static int __loc_network_tree_walk(struct loc_ctx* ctx, struct loc_network_tree_ return 0; } - r = callback(node->network); + r = callback(node->network, data); if (r) return r; } // Walk down on the left side of the tree first if (node->zero) { - r = __loc_network_tree_walk(ctx, node->zero, filter_callback, callback); + r = __loc_network_tree_walk(ctx, node->zero, filter_callback, callback, data); if (r) return r; } // Then walk on the other side if (node->one) { - r = __loc_network_tree_walk(ctx, node->one, filter_callback, callback); + r = __loc_network_tree_walk(ctx, node->one, filter_callback, callback, data); if (r) return r; } @@ -276,6 +296,12 @@ static int __loc_network_tree_walk(struct loc_ctx* ctx, struct loc_network_tree_ return 0; } +LOC_EXPORT int loc_network_tree_walk(struct loc_network_tree* tree, + int(*filter_callback)(struct loc_network* network, void* data), + int(*callback)(struct loc_network* network, void* data), void* data) { + return __loc_network_tree_walk(tree->ctx, tree->root, filter_callback, callback, data); +} + static void loc_network_tree_free_subtree(struct loc_network_tree_node* node) { if (node->network) loc_network_unref(node->network); @@ -306,7 +332,7 @@ LOC_EXPORT struct loc_network_tree* loc_network_tree_unref(struct loc_network_tr return NULL; } -int __loc_network_tree_dump(struct loc_network* network) { +int __loc_network_tree_dump(struct loc_network* network, void* data) { DEBUG(network->ctx, "Dumping network at %p\n", network); char* s = loc_network_str(network); @@ -322,7 +348,7 @@ int __loc_network_tree_dump(struct loc_network* network) { LOC_EXPORT int loc_network_tree_dump(struct loc_network_tree* tree) { DEBUG(tree->ctx, "Dumping network tree at %p\n", tree); - return __loc_network_tree_walk(tree->ctx, tree->root, NULL, __loc_network_tree_dump); + return loc_network_tree_walk(tree, NULL, __loc_network_tree_dump, NULL); } LOC_EXPORT int loc_network_tree_add_network(struct loc_network_tree* tree, struct loc_network* network) { @@ -345,3 +371,22 @@ LOC_EXPORT int loc_network_tree_add_network(struct loc_network_tree* tree, struc return 0; } + +static int __loc_network_tree_count(struct loc_network* network, void* data) { + size_t* counter = (size_t*)data; + + // Increase the counter for each network + counter++; + + return 0; +} + +LOC_EXPORT size_t loc_network_tree_count_networks(struct loc_network_tree* tree) { + size_t counter = 0; + + int r = loc_network_tree_walk(tree, NULL, __loc_network_tree_count, &counter); + if (r) + return r; + + return counter; +} diff --git a/src/test-network.c b/src/test-network.c index b64c004..b309d45 100644 --- a/src/test-network.c +++ b/src/test-network.c @@ -14,6 +14,7 @@ GNU General Public License for more details. */ +#include #include #include #include @@ -21,6 +22,7 @@ #include #include +#include int main(int argc, char** argv) { int err; @@ -65,6 +67,37 @@ int main(int argc, char** argv) { exit(EXIT_FAILURE); } + // Create a database + struct loc_writer* writer; + err = loc_writer_new(ctx, &writer); + if (err < 0) + exit(EXIT_FAILURE); + + struct loc_network* network2; + err = loc_writer_add_network(writer, &network2, "2001:db8:1::/48"); + if (err) { + fprintf(stderr, "Could not add network\n"); + exit(EXIT_FAILURE); + } + + // Set country code + loc_network_set_country_code(network2, "XX"); + + FILE* f = fopen("test.db", "w"); + if (!f) { + fprintf(stderr, "Could not open file for writing: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + err = loc_writer_write(writer, f); + if (err) { + fprintf(stderr, "Could not write database: %s\n", strerror(-err)); + exit(EXIT_FAILURE); + } + fclose(f); + + loc_writer_unref(writer); + loc_network_unref(network1); loc_network_tree_unref(tree); loc_unref(ctx); diff --git a/src/writer.c b/src/writer.c index 1e3e360..4c9bcf6 100644 --- a/src/writer.c +++ b/src/writer.c @@ -221,6 +221,38 @@ static int loc_database_write_as_section(struct loc_writer* writer, return 0; } +static int loc_database_write_network_section(struct loc_network* network, void* data) { + FILE* f = (FILE*)data; + + struct loc_database_network_v0 n; + + int r = loc_network_to_database_v0(network, &n); + if (r) + return r; + + fwrite(&n, 1, sizeof(n), f); + + return 0; +} + +static int loc_database_write_networks_section(struct loc_writer* writer, + struct loc_database_header_v0* header, off_t* offset, FILE* f) { + DEBUG(writer->ctx, "Networks section starts at %jd bytes\n", *offset); + header->networks_offset = htobe32(*offset); + + size_t networks_length = sizeof(struct loc_database_network_v0) + * loc_network_tree_count_networks(writer->networks); + offset += networks_length; + + int r = loc_network_tree_walk(writer->networks, NULL, loc_database_write_network_section, f); + if (r) + return r; + + header->networks_length = htobe32(networks_length); + + return 0; +} + LOC_EXPORT int loc_writer_write(struct loc_writer* writer, FILE* f) { struct loc_database_magic magic; make_magic(writer, &magic); @@ -261,6 +293,13 @@ LOC_EXPORT int loc_writer_write(struct loc_writer* writer, FILE* f) { align_page_boundary(&offset, f); + // Write all networks + r = loc_database_write_networks_section(writer, &header, &offset, f); + if (r) + return r; + + align_page_boundary(&offset, f); + // Write pool r = loc_database_write_pool(writer, &header, &offset, f); if (r) -- 2.39.2