]> git.ipfire.org Git - people/ms/libloc.git/commitdiff
network: Pass prefix in native length
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 7 Mar 2022 12:22:14 +0000 (12:22 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 7 Mar 2022 12:22:14 +0000 (12:22 +0000)
When creating an IPv4 subnet, the prefix had to be mapped to the mapped
syntax (i.e. add 96). This doesn't seem too intuitive to me.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libloc/address.h
src/network-list.c
src/network.c

index 57540bbcc021bbeb5d0defb66391170cb03dc2eb..692ed12281984a4ed423dbea7d58c9d05cddd838 100644 (file)
@@ -33,6 +33,34 @@ static inline int loc_address_family(const struct in6_addr* address) {
                return AF_INET6;
 }
 
+static inline unsigned int loc_address_family_bit_length(const int family) {
+       switch (family) {
+               case AF_INET6:
+                       return 128;
+
+               case AF_INET:
+                       return 32;
+
+               default:
+                       return 0;
+       }
+}
+
+/*
+       Checks whether prefix is valid for the given address
+*/
+static inline int loc_address_valid_prefix(const struct in6_addr* address, unsigned int prefix) {
+       const int family = loc_address_family(address);
+
+       // What is the largest possible prefix?
+       const unsigned int bit_length = loc_address_family_bit_length(family);
+
+       if (prefix <= bit_length)
+               return 1;
+
+       return 0;
+}
+
 static inline int loc_address_cmp(const struct in6_addr* a1, const struct in6_addr* a2) {
        for (unsigned int i = 0; i < 16; i++) {
                if (a1->s6_addr[i] > a2->s6_addr[i])
@@ -247,19 +275,6 @@ static inline void loc_address_decrement(struct in6_addr* address) {
        }
 }
 
-static inline int loc_address_family_bit_length(const int family) {
-       switch (family) {
-               case AF_INET6:
-                       return 128;
-
-               case AF_INET:
-                       return 32;
-
-               default:
-                       return -1;
-       }
-}
-
 static inline int loc_address_all_zeroes(const struct in6_addr* address) {
        struct in6_addr all_zeroes = IN6ADDR_ANY_INIT;
 
index 2765cec04b96d06f553294771ee1c48ee0dea133..095d82f8988dbe98e43f2430af3b03d4daa364ab 100644 (file)
@@ -358,7 +358,7 @@ int loc_network_list_summarize(struct loc_ctx* ctx,
                int bits = (bits1 > bits2) ? bits2 : bits1;
 
                // Create a network
-               r = loc_network_new(ctx, &network, &start, 128 - bits);
+               r = loc_network_new(ctx, &network, &start, family_bit_length - bits);
                if (r)
                        return r;
 
index 3967e29e2ff41cb3b0831744b1c4c1227dc2dd5f..445f1efafd623b5d996982fd98d444309f254e5c 100644 (file)
@@ -47,22 +47,10 @@ struct loc_network {
        enum loc_network_flags flags;
 };
 
-static int valid_prefix(struct in6_addr* address, unsigned int prefix) {
-       // The prefix cannot be larger than 128 bits
-       if (prefix > 128)
-               return 1;
-
-       // For IPv4-mapped addresses the prefix has to be 96 or lager
-       if (IN6_IS_ADDR_V4MAPPED(address) && prefix <= 96)
-               return 1;
-
-       return 0;
-}
-
 LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network,
                struct in6_addr* address, unsigned int prefix) {
        // Validate the prefix
-       if (valid_prefix(address, prefix) != 0) {
+       if (!loc_address_valid_prefix(address, prefix)) {
                ERROR(ctx, "Invalid prefix: %u\n", prefix);
                errno = EINVAL;
                return 1;
@@ -78,7 +66,10 @@ LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network
        n->refcount = 1;
 
        // Store the prefix
-       n->prefix = prefix;
+       if (IN6_IS_ADDR_V4MAPPED(address))
+               n->prefix = prefix + 96;
+       else
+               n->prefix = prefix;
 
        // Convert the prefix into a bitmask
        struct in6_addr bitmask = loc_prefix_to_bitmask(n->prefix);
@@ -129,10 +120,6 @@ LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_netwo
                        DEBUG(ctx, "The prefix was not parsable: %s\n", prefix_string);
                        goto FAIL;
                }
-
-               // Map the prefix to IPv6 if needed
-               if (IN6_IS_ADDR_V4MAPPED(&first_address))
-                       prefix += 96;
        }
 
 FAIL:
@@ -425,7 +412,7 @@ LOC_EXPORT int loc_network_subnets(struct loc_network* network,
        unsigned int prefix = network->prefix + 1;
 
        // Check if the new prefix is valid
-       if (valid_prefix(&network->first_address, prefix))
+       if (!loc_address_valid_prefix(&network->first_address, prefix))
                return -1;
 
        // Create the first half of the network
@@ -685,6 +672,10 @@ int loc_network_new_from_database_v1(struct loc_ctx* ctx, struct loc_network** n
                struct in6_addr* address, unsigned int prefix, const struct loc_database_network_v1* dbobj) {
        char country_code[3] = "\0\0";
 
+       // Adjust prefix for IPv4
+       if (IN6_IS_ADDR_V4MAPPED(address))
+               prefix -= 96;
+
        int r = loc_network_new(ctx, network, address, prefix);
        if (r) {
                ERROR(ctx, "Could not allocate a new network: %s", strerror(-r));