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])
}
}
-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;
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;
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);
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:
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
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));