From a82ce8bc4f6cd6b9b62650b17fbff23bac9a6b68 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Tue, 2 Jan 2018 17:38:21 +0000 Subject: [PATCH] network: Always use the first address of a network Signed-off-by: Michael Tremer --- src/network.c | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/network.c b/src/network.c index fe5654e..d34f881 100644 --- a/src/network.c +++ b/src/network.c @@ -53,34 +53,61 @@ static int valid_prefix(struct in6_addr* address, unsigned int prefix) { return 0; } +static struct in6_addr prefix_to_bitmask(unsigned int prefix) { + struct in6_addr bitmask; + + 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++) { + if (i >= 8) + bitmask.s6_addr[j] = 0xff; + else + bitmask.s6_addr[j] = 0xff << (8 - i); + } + + return bitmask; +} + +static struct in6_addr make_start_address(struct in6_addr* address, unsigned int prefix) { + struct in6_addr a; + struct in6_addr bitmask = prefix_to_bitmask(prefix); + + // Perform bitwise AND + for (unsigned int i = 0; i < 4; i++) + a.s6_addr32[i] = address->s6_addr32[i] & bitmask.s6_addr32[i]; + + return a; +} + LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network, - struct in6_addr start_address, unsigned int prefix) { + struct in6_addr address, unsigned int prefix) { // Address cannot be unspecified - if (IN6_IS_ADDR_UNSPECIFIED(&start_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(&start_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(&start_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(&start_address)) { + if (IN6_IS_ADDR_SITELOCAL(&address)) { DEBUG(ctx, "Start address cannot be site-local\n"); return -EINVAL; } // Validate the prefix - if (valid_prefix(&start_address, prefix) != 0) { + if (valid_prefix(&address, prefix) != 0) { DEBUG(ctx, "Invalid prefix: %u\n", prefix); return -EINVAL; } @@ -92,7 +119,8 @@ LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network n->ctx = loc_ref(ctx); n->refcount = 1; - n->start_address = start_address; + // Store the first address in the network + n->start_address = make_start_address(&address, prefix); n->prefix = prefix; DEBUG(n->ctx, "Network allocated at %p\n", n); -- 2.39.2