X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fnetwork.c;h=09f225e7138073204b444414eedbe659d6ee5a2e;hb=42f3ccd725ccc9d4479a3b20ea6338a431527684;hp=73a299fe29a604d9cc7d672bbb53d37da1e0226a;hpb=2a30e4de98bd3362868f2673fa679559c42a6fbe;p=people%2Fms%2Flibloc.git diff --git a/src/network.c b/src/network.c index 73a299f..09f225e 100644 --- a/src/network.c +++ b/src/network.c @@ -16,13 +16,18 @@ #include #include -#include #include #include #include #include +#ifdef HAVE_ENDIAN_H +# include +#endif + #include +#include +#include #include #include @@ -35,6 +40,7 @@ struct loc_network { char country_code[3]; uint32_t asn; + enum loc_network_flags flags; }; static int valid_prefix(struct in6_addr* address, unsigned int prefix) { @@ -59,7 +65,7 @@ static struct in6_addr prefix_to_bitmask(unsigned int prefix) { for (unsigned int i = 0; i < 16; i++) bitmask.s6_addr[i] = 0; - for (unsigned int i = prefix, j = 0; i > 0; i -= 8, j++) { + for (int i = prefix, j = 0; i > 0; i -= 8, j++) { if (i >= 8) bitmask.s6_addr[j] = 0xff; else @@ -86,7 +92,7 @@ static struct in6_addr make_last_address(const struct in6_addr* address, unsigne // Perform bitwise OR for (unsigned int i = 0; i < 4; i++) - a.s6_addr32[i] = address->s6_addr[i] | ~bitmask.s6_addr32[i]; + a.s6_addr32[i] = address->s6_addr32[i] | ~bitmask.s6_addr32[i]; return a; } @@ -94,25 +100,25 @@ static struct in6_addr make_last_address(const struct in6_addr* address, unsigne LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network, struct in6_addr* address, unsigned int prefix) { // Address cannot be unspecified - if (IN6_IS_ADDR_UNSPECIFIED(&address)) { + if (IN6_IS_ADDR_UNSPECIFIED(address)) { DEBUG(ctx, "Start address is unspecified\n"); return -EINVAL; } // Address cannot be loopback - if (IN6_IS_ADDR_LOOPBACK(&address)) { + if (IN6_IS_ADDR_LOOPBACK(address)) { DEBUG(ctx, "Start address is loopback address\n"); return -EINVAL; } // Address cannot be link-local - if (IN6_IS_ADDR_LINKLOCAL(&address)) { + if (IN6_IS_ADDR_LINKLOCAL(address)) { DEBUG(ctx, "Start address cannot be link-local\n"); return -EINVAL; } // Address cannot be site-local - if (IN6_IS_ADDR_SITELOCAL(&address)) { + if (IN6_IS_ADDR_SITELOCAL(address)) { DEBUG(ctx, "Start address cannot be site-local\n"); return -EINVAL; } @@ -209,17 +215,17 @@ LOC_EXPORT struct loc_network* loc_network_unref(struct loc_network* network) { return NULL; } -static int format_ipv6_address(struct loc_network* network, char* string, size_t length) { - const char* ret = inet_ntop(AF_INET6, &network->start_address, string, length); +static int format_ipv6_address(const struct in6_addr* address, char* string, size_t length) { + const char* ret = inet_ntop(AF_INET6, address, string, length); if (!ret) return -1; return 0; } -static int format_ipv4_address(struct loc_network* network, char* string, size_t length) { +static int format_ipv4_address(const struct in6_addr* address, char* string, size_t length) { struct in_addr ipv4_address; - ipv4_address.s_addr = network->start_address.s6_addr32[3]; + ipv4_address.s_addr = address->s6_addr32[3]; const char* ret = inet_ntop(AF_INET, &ipv4_address, string, length); if (!ret) @@ -241,11 +247,11 @@ LOC_EXPORT char* loc_network_str(struct loc_network* network) { int family = loc_network_address_family(network); switch (family) { case AF_INET6: - r = format_ipv6_address(network, string, length); + r = format_ipv6_address(&network->start_address, string, length); break; case AF_INET: - r = format_ipv4_address(network, string, length); + r = format_ipv4_address(&network->start_address, string, length); prefix -= 96; break; @@ -268,7 +274,7 @@ LOC_EXPORT char* loc_network_str(struct loc_network* network) { } LOC_EXPORT int loc_network_match_address(struct loc_network* network, const struct in6_addr* address) { - // Address must be larger then the start address + // Address must be larger than the start address if (in6_addr_cmp(&network->start_address, address) > 0) return 1; @@ -276,7 +282,7 @@ LOC_EXPORT int loc_network_match_address(struct loc_network* network, const stru struct in6_addr last_address = make_last_address(&network->start_address, network->prefix); // Address must be smaller than the last address - if (in6_addr_cmp(&last_address, address) > 0) + if (in6_addr_cmp(address, &last_address) > 0) return 1; // The address is inside this network @@ -288,17 +294,30 @@ LOC_EXPORT const char* loc_network_get_country_code(struct loc_network* network) } LOC_EXPORT int loc_network_set_country_code(struct loc_network* network, const char* country_code) { - // Country codes must be two characters - if (strlen(country_code) != 2) + // Set empty country code + if (!country_code || !*country_code) { + *network->country_code = '\0'; + return 0; + } + + // Check country code + if (!loc_country_code_is_valid(country_code)) return -EINVAL; - for (unsigned int i = 0; i < 3; i++) { - network->country_code[i] = country_code[i]; - } + loc_country_code_copy(network->country_code, country_code); return 0; } +LOC_EXPORT int loc_network_match_country_code(struct loc_network* network, const char* country_code) { + // Check country code + if (!loc_country_code_is_valid(country_code)) + return -EINVAL; + + return (network->country_code[0] == country_code[0]) + && (network->country_code[1] == country_code[1]); +} + LOC_EXPORT uint32_t loc_network_get_asn(struct loc_network* network) { return network->asn; } @@ -309,32 +328,47 @@ LOC_EXPORT int loc_network_set_asn(struct loc_network* network, uint32_t asn) { return 0; } -LOC_EXPORT int loc_network_to_database_v0(struct loc_network* network, struct loc_database_network_v0* dbobj) { - dbobj->prefix = network->prefix; +LOC_EXPORT int loc_network_match_asn(struct loc_network* network, uint32_t asn) { + return network->asn == asn; +} + +LOC_EXPORT int loc_network_has_flag(struct loc_network* network, uint32_t flag) { + return network->flags & flag; +} +LOC_EXPORT int loc_network_set_flag(struct loc_network* network, uint32_t flag) { + network->flags |= flag; + + return 0; +} + +LOC_EXPORT int loc_network_match_flag(struct loc_network* network, uint32_t flag) { + return loc_network_has_flag(network, flag); +} + +LOC_EXPORT int loc_network_to_database_v0(struct loc_network* network, struct loc_database_network_v0* dbobj) { // Add country code - for (unsigned int i = 0; i < 2; i++) { - dbobj->country_code[i] = network->country_code ? network->country_code[i] : '\0'; - } + loc_country_code_copy(dbobj->country_code, network->country_code); // Add ASN dbobj->asn = htobe32(network->asn); + // Flags + dbobj->flags = htobe16(network->flags); + return 0; } LOC_EXPORT int loc_network_new_from_database_v0(struct loc_ctx* ctx, struct loc_network** network, - struct in6_addr* address, const struct loc_database_network_v0* dbobj) { - int r = loc_network_new(ctx, network, address, dbobj->prefix); + struct in6_addr* address, unsigned int prefix, const struct loc_database_network_v0* dbobj) { + char country_code[3]; + + int r = loc_network_new(ctx, network, address, prefix); if (r) return r; // Import country code - char country_code[3]; - for (unsigned int i = 0; i < 2; i++) { - country_code[i] = dbobj->country_code[i]; - } - country_code[2] = '\0'; + loc_country_code_copy(country_code, dbobj->country_code); r = loc_network_set_country_code(*network, country_code); if (r) @@ -345,6 +379,11 @@ LOC_EXPORT int loc_network_new_from_database_v0(struct loc_ctx* ctx, struct loc_ if (r) return r; + // Import flags + r = loc_network_set_flag(*network, be16toh(dbobj->flags)); + if (r) + return r; + return 0; } @@ -407,10 +446,10 @@ static struct loc_network_tree_node* loc_network_tree_get_node(struct loc_networ return *n; } -static struct loc_network_tree_node* loc_network_tree_get_path(struct loc_network_tree* tree, const struct in6_addr* address) { +static struct loc_network_tree_node* loc_network_tree_get_path(struct loc_network_tree* tree, const struct in6_addr* address, unsigned int prefix) { struct loc_network_tree_node* node = tree->root; - for (unsigned int i = 0; i < 128; i++) { + for (unsigned int i = 0; i < prefix; i++) { // Check if the ith bit is one or zero node = loc_network_tree_get_node(node, in6_addr_get_bit(address, i)); } @@ -502,7 +541,8 @@ LOC_EXPORT int loc_network_tree_dump(struct loc_network_tree* tree) { LOC_EXPORT int loc_network_tree_add_network(struct loc_network_tree* tree, struct loc_network* network) { DEBUG(tree->ctx, "Adding network %p to tree %p\n", network, tree); - struct loc_network_tree_node* node = loc_network_tree_get_path(tree, &network->start_address); + struct loc_network_tree_node* node = loc_network_tree_get_path(tree, + &network->start_address, network->prefix); if (!node) { ERROR(tree->ctx, "Could not find a node\n"); return -ENOMEM; @@ -511,7 +551,7 @@ LOC_EXPORT int loc_network_tree_add_network(struct loc_network_tree* tree, struc // Check if node has not been set before if (node->network) { DEBUG(tree->ctx, "There is already a network at this path\n"); - return 1; + return -EBUSY; } // Point node to the network