Commit f39c751d authored by Michael Tremer's avatar Michael Tremer

addresses: Implement subtraction for IPv4

Signed-off-by: default avatarMichael Tremer <michael.tremer@ipfire.org>
parent b074be0b
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#ifdef LIBLOC_PRIVATE #ifdef LIBLOC_PRIVATE
#include <errno.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
...@@ -151,10 +152,8 @@ static inline struct in6_addr loc_address_or( ...@@ -151,10 +152,8 @@ static inline struct in6_addr loc_address_or(
return a; return a;
} }
static inline struct in6_addr loc_address_sub( static inline int __loc_address6_sub(struct in6_addr* result,
const struct in6_addr* address1, const struct in6_addr* address2) { const struct in6_addr* address1, const struct in6_addr* address2) {
struct in6_addr a;
int remainder = 0; int remainder = 0;
for (int octet = 15; octet >= 0; octet--) { for (int octet = 15; octet >= 0; octet--) {
...@@ -163,10 +162,56 @@ static inline struct in6_addr loc_address_sub( ...@@ -163,10 +162,56 @@ static inline struct in6_addr loc_address_sub(
// Store remainder for the next iteration // Store remainder for the next iteration
remainder = (x >> 8); remainder = (x >> 8);
a.s6_addr[octet] = x & 0xff; result->s6_addr[octet] = x & 0xff;
} }
return a; return 0;
}
static inline int __loc_address4_sub(struct in6_addr* result,
const struct in6_addr* address1, const struct in6_addr* address2) {
int remainder = 0;
for (int octet = 4; octet >= 0; octet--) {
int x = address1->s6_addr[octet] - address2->s6_addr[octet] + remainder;
// Store remainder for the next iteration
remainder = (x >> 8);
result->s6_addr[octet] = x & 0xff;
}
return 0;
}
static inline int loc_address_sub(struct in6_addr* result,
const struct in6_addr* address1, const struct in6_addr* address2) {
// XXX should be using loc_address_family
int family1 = IN6_IS_ADDR_V4MAPPED(address1) ? AF_INET : AF_INET6;
int family2 = IN6_IS_ADDR_V4MAPPED(address2) ? AF_INET : AF_INET6;
// Address family must match
if (family1 != family2) {
errno = EINVAL;
return 1;
}
// Clear result
int r = loc_address_reset(result, family1);
if (r)
return r;
switch (family1) {
case AF_INET6:
return __loc_address6_sub(result, address1, address2);
case AF_INET:
return __loc_address4_sub(result, address1, address2);
default:
errno = ENOTSUP;
return 1;
}
} }
static inline void hexdump(struct loc_ctx* ctx, const void* addr, size_t len) { static inline void hexdump(struct loc_ctx* ctx, const void* addr, size_t len) {
......
...@@ -327,12 +327,17 @@ int loc_network_list_summarize(struct loc_ctx* ctx, ...@@ -327,12 +327,17 @@ int loc_network_list_summarize(struct loc_ctx* ctx,
struct in6_addr start = *first; struct in6_addr start = *first;
while (in6_addr_cmp(&start, last) <= 0) { while (in6_addr_cmp(&start, last) <= 0) {
struct in6_addr num;
// Find the number of trailing zeroes of the start address // Find the number of trailing zeroes of the start address
int bits1 = loc_address_count_trailing_zero_bits(&start); int bits1 = loc_address_count_trailing_zero_bits(&start);
// Subtract the start address from the last address and add one // Subtract the start address from the last address and add one
// (i.e. how many addresses are in this network?) // (i.e. how many addresses are in this network?)
struct in6_addr num = loc_address_sub(last, &start); r = loc_address_sub(&num, last, &start);
if (r)
return r;
num = address_increment(&num); num = address_increment(&num);
// How many bits do we need to represent this address? // How many bits do we need to represent this address?
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment