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;
#include <netinet/in.h>
#include <loc/libloc.h>
+#include <loc/format.h>
struct loc_network;
int loc_network_new(struct loc_ctx* ctx, 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
#include <arpa/inet.h>
#include <assert.h>
+#include <endian.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
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;
}
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;
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;
}
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);
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);
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) {
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;
+}
GNU General Public License for more details.
*/
+#include <errno.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <loc/libloc.h>
#include <loc/network.h>
+#include <loc/writer.h>
int main(int argc, char** argv) {
int err;
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);
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);
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)