mirror of
https://github.com/systemd/systemd.git
synced 2024-10-31 16:21:26 +03:00
Merge pull request #18653 from yuwata/in-addr-prefix-nth
in-addr-util: fix in_addr_prefix_nth() and use the function to get ip address range in firewall-util
This commit is contained in:
commit
50fc7d7036
@ -189,8 +189,8 @@ int in_addr_prefix_intersect(
|
|||||||
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) {
|
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) {
|
||||||
assert(u);
|
assert(u);
|
||||||
|
|
||||||
/* Increases the network part of an address by one. Returns
|
/* Increases the network part of an address by one. Returns 0 if that succeeds, or -ERANGE if
|
||||||
* positive if that succeeds, or -ERANGE if this overflows. */
|
* this overflows. */
|
||||||
|
|
||||||
return in_addr_prefix_nth(family, u, prefixlen, 1);
|
return in_addr_prefix_nth(family, u, prefixlen, 1);
|
||||||
}
|
}
|
||||||
@ -198,19 +198,17 @@ int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen)
|
|||||||
/*
|
/*
|
||||||
* Calculates the nth prefix of size prefixlen starting from the address denoted by u.
|
* Calculates the nth prefix of size prefixlen starting from the address denoted by u.
|
||||||
*
|
*
|
||||||
* On success 1 will be returned and the calculated prefix will be available in
|
* On success 0 will be returned and the calculated prefix will be available in
|
||||||
* u. In the case nth == 0 the input will be left unchanged and 1 will be returned.
|
* u. In case the calculation cannot be performed (invalid prefix length,
|
||||||
* In case the calculation cannot be performed (invalid prefix length,
|
|
||||||
* overflows would occur) -ERANGE is returned. If the address family given isn't
|
* overflows would occur) -ERANGE is returned. If the address family given isn't
|
||||||
* supported -EAFNOSUPPORT will be returned.
|
* supported -EAFNOSUPPORT will be returned.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* Examples:
|
* Examples:
|
||||||
* - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 2), returns 1, writes 192.168.2.0 to u
|
* - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 2), returns 0, writes 192.168.2.0 to u
|
||||||
* - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 0), returns 1, no data written
|
* - in_addr_prefix_nth(AF_INET, 192.168.0.0, 24, 0), returns 0, no data written
|
||||||
* - in_addr_prefix_nth(AF_INET, 255.255.255.0, 24, 1), returns -ERANGE, no data written
|
* - in_addr_prefix_nth(AF_INET, 255.255.255.0, 24, 1), returns -ERANGE, no data written
|
||||||
* - in_addr_prefix_nth(AF_INET, 255.255.255.0, 0, 1), returns -ERANGE, no data written
|
* - in_addr_prefix_nth(AF_INET, 255.255.255.0, 0, 1), returns -ERANGE, no data written
|
||||||
* - in_addr_prefix_nth(AF_INET6, 2001:db8, 64, 0xff00) returns 1, writes 2001:0db8:0000:ff00:: to u
|
* - in_addr_prefix_nth(AF_INET6, 2001:db8, 64, 0xff00) returns 0, writes 2001:0db8:0000:ff00:: to u
|
||||||
*/
|
*/
|
||||||
int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth) {
|
int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth) {
|
||||||
assert(u);
|
assert(u);
|
||||||
@ -218,13 +216,11 @@ int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, u
|
|||||||
if (prefixlen <= 0)
|
if (prefixlen <= 0)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
if (nth == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (family == AF_INET) {
|
if (family == AF_INET) {
|
||||||
uint32_t c, n, t;
|
uint32_t c, n, t;
|
||||||
|
|
||||||
if (prefixlen > 32)
|
if (prefixlen > 32)
|
||||||
prefixlen = 32;
|
return -ERANGE;
|
||||||
|
|
||||||
c = be32toh(u->in.s_addr);
|
c = be32toh(u->in.s_addr);
|
||||||
|
|
||||||
@ -238,44 +234,40 @@ int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, u
|
|||||||
|
|
||||||
n &= UINT32_C(0xFFFFFFFF) << (32 - prefixlen);
|
n &= UINT32_C(0xFFFFFFFF) << (32 - prefixlen);
|
||||||
u->in.s_addr = htobe32(n);
|
u->in.s_addr = htobe32(n);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (family == AF_INET6) {
|
if (family == AF_INET6) {
|
||||||
struct in6_addr result = {};
|
bool overflow = false;
|
||||||
uint8_t overflow = 0;
|
|
||||||
uint64_t delta; /* this assumes that we only ever have to up to 1<<64 subnets */
|
|
||||||
unsigned start_byte = (prefixlen - 1) / 8;
|
|
||||||
|
|
||||||
if (prefixlen > 128)
|
if (prefixlen > 128)
|
||||||
prefixlen = 128;
|
|
||||||
|
|
||||||
/* First calculate what we have to add */
|
|
||||||
delta = nth << ((128 - prefixlen) % 8);
|
|
||||||
|
|
||||||
for (unsigned i = 16; i > 0; i--) {
|
|
||||||
unsigned j = i - 1;
|
|
||||||
unsigned d = 0;
|
|
||||||
|
|
||||||
if (j <= start_byte) {
|
|
||||||
int16_t t;
|
|
||||||
|
|
||||||
d = delta & 0xFF;
|
|
||||||
delta >>= 8;
|
|
||||||
|
|
||||||
t = u->in6.s6_addr[j] + d + overflow;
|
|
||||||
overflow = t > UINT8_MAX ? t - UINT8_MAX : 0;
|
|
||||||
|
|
||||||
result.s6_addr[j] = (uint8_t)t;
|
|
||||||
} else
|
|
||||||
result.s6_addr[j] = u->in6.s6_addr[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overflow || delta != 0)
|
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
u->in6 = result;
|
for (unsigned i = 16; i > 0; i--) {
|
||||||
return 1;
|
unsigned t, j = i - 1, p = j * 8;
|
||||||
|
|
||||||
|
if (p >= prefixlen) {
|
||||||
|
u->in6.s6_addr[j] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixlen - p < 8) {
|
||||||
|
u->in6.s6_addr[j] &= 0xff << (8 - (prefixlen - p));
|
||||||
|
t = u->in6.s6_addr[j] + ((nth & 0xff) << (8 - (prefixlen - p)));
|
||||||
|
nth >>= prefixlen - p;
|
||||||
|
} else {
|
||||||
|
t = u->in6.s6_addr[j] + (nth & 0xff) + overflow;
|
||||||
|
nth >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
overflow = t > UINT8_MAX;
|
||||||
|
u->in6.s6_addr[j] = (uint8_t) (t & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overflow || nth != 0)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EAFNOSUPPORT;
|
return -EAFNOSUPPORT;
|
||||||
@ -358,6 +350,43 @@ int in_addr_random_prefix(
|
|||||||
return -EAFNOSUPPORT;
|
return -EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int in_addr_prefix_range(
|
||||||
|
int family,
|
||||||
|
const union in_addr_union *in,
|
||||||
|
unsigned prefixlen,
|
||||||
|
union in_addr_union *ret_start,
|
||||||
|
union in_addr_union *ret_end) {
|
||||||
|
|
||||||
|
union in_addr_union start, end;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(in);
|
||||||
|
|
||||||
|
if (!IN_SET(family, AF_INET, AF_INET6))
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
|
||||||
|
if (ret_start) {
|
||||||
|
start = *in;
|
||||||
|
r = in_addr_prefix_nth(family, &start, prefixlen, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret_end) {
|
||||||
|
end = *in;
|
||||||
|
r = in_addr_prefix_nth(family, &end, prefixlen, 1);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret_start)
|
||||||
|
*ret_start = start;
|
||||||
|
if (ret_end)
|
||||||
|
*ret_end = end;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
|
int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
|
||||||
_cleanup_free_ char *x = NULL;
|
_cleanup_free_ char *x = NULL;
|
||||||
size_t l;
|
size_t l;
|
||||||
|
@ -41,6 +41,12 @@ int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned
|
|||||||
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
|
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
|
||||||
int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth);
|
int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth);
|
||||||
int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
|
int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
|
||||||
|
int in_addr_prefix_range(
|
||||||
|
int family,
|
||||||
|
const union in_addr_union *in,
|
||||||
|
unsigned prefixlen,
|
||||||
|
union in_addr_union *ret_start,
|
||||||
|
union in_addr_union *ret_end);
|
||||||
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
|
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
|
||||||
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
|
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
|
||||||
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
|
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include "firewall-util-private.h"
|
#include "firewall-util-private.h"
|
||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "memory-util.h"
|
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
|
|
||||||
@ -30,9 +29,6 @@
|
|||||||
|
|
||||||
#define UDP_DPORT_OFFSET 2
|
#define UDP_DPORT_OFFSET 2
|
||||||
|
|
||||||
void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
|
|
||||||
struct in6_addr *start, struct in6_addr *end);
|
|
||||||
|
|
||||||
static int nfnl_netlink_sendv(sd_netlink *nfnl,
|
static int nfnl_netlink_sendv(sd_netlink *nfnl,
|
||||||
sd_netlink_message *messages[],
|
sd_netlink_message *messages[],
|
||||||
size_t msgcount) {
|
size_t msgcount) {
|
||||||
@ -848,55 +844,19 @@ static int fw_nftables_recreate_table(sd_netlink *nfnl, int af, sd_netlink_messa
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
|
static int nft_message_add_setelem_ip6range(
|
||||||
struct in6_addr *ret_start, struct in6_addr *ret_end) {
|
sd_netlink_message *m,
|
||||||
uint8_t carry = 0;
|
const union in_addr_union *source,
|
||||||
int i, j;
|
unsigned int prefixlen) {
|
||||||
|
|
||||||
assert(prefixlen <= 128);
|
union in_addr_union start, end;
|
||||||
|
|
||||||
for (i = 0, j = 15; i < 16; i++) {
|
|
||||||
uint8_t nm;
|
|
||||||
|
|
||||||
nm = 0xFF;
|
|
||||||
if (prefixlen < 8)
|
|
||||||
nm = 0xFF << (8 - prefixlen);
|
|
||||||
|
|
||||||
ret_start->s6_addr[i] = source->in6.s6_addr[i] & nm;
|
|
||||||
if (prefixlen <= 8 && j == 15) {
|
|
||||||
carry = 1u << (8 - prefixlen);
|
|
||||||
j = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prefixlen >= 8)
|
|
||||||
prefixlen -= 8;
|
|
||||||
else
|
|
||||||
prefixlen = 0;
|
|
||||||
}
|
|
||||||
*ret_end = *ret_start;
|
|
||||||
|
|
||||||
for (; j >= 0; j--) {
|
|
||||||
uint16_t overflow = ret_end->s6_addr[j] + carry;
|
|
||||||
|
|
||||||
ret_end->s6_addr[j] = overflow;
|
|
||||||
if (overflow <= 0xff)
|
|
||||||
break;
|
|
||||||
carry = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(ret_start, ret_end, sizeof(*ret_start)) > 0)
|
|
||||||
zero(ret_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int nft_message_add_setelem_ip6range(sd_netlink_message *m,
|
|
||||||
const union in_addr_union *source,
|
|
||||||
unsigned int prefixlen) {
|
|
||||||
struct in6_addr start, end;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
nft_in6addr_to_range(source, prefixlen, &start, &end);
|
r = in_addr_prefix_range(AF_INET6, source, prefixlen, &start, &end);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = sd_nfnl_nft_message_add_setelem(m, 0, &start, sizeof(start), NULL, 0);
|
r = sd_nfnl_nft_message_add_setelem(m, 0, &start.in6, sizeof(start.in6), NULL, 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -904,7 +864,7 @@ static int nft_message_add_setelem_ip6range(sd_netlink_message *m,
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_nfnl_nft_message_add_setelem(m, 1, &end, sizeof(end), NULL, 0);
|
r = sd_nfnl_nft_message_add_setelem(m, 1, &end.in6, sizeof(end.in6), NULL, 0);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "firewall-util.h"
|
#include "firewall-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -8,32 +6,14 @@
|
|||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
|
||||||
#define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))}
|
#define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))}
|
||||||
|
#define MAKE_IN6_ADDR_UNION(str, u) assert_se(in_addr_from_string(AF_INET6, str, u) >= 0)
|
||||||
void nft_in6addr_to_range(const union in_addr_union *source, unsigned int prefixlen,
|
|
||||||
struct in6_addr *start, struct in6_addr *end);
|
|
||||||
|
|
||||||
static void make_in6_addr_union(const char *addr, union in_addr_union *u) {
|
|
||||||
assert_se(inet_pton(AF_INET6, addr, &u->in6) >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool test_in6_eq(const char *addr, const union in_addr_union *u) {
|
|
||||||
union in_addr_union tmp;
|
|
||||||
|
|
||||||
make_in6_addr_union(addr, &tmp);
|
|
||||||
|
|
||||||
return memcmp(&tmp.in6, &u->in6, sizeof(tmp.in6)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void assert_in6_eq(const union in_addr_union *a, const union in_addr_union *b) {
|
|
||||||
assert_se(memcmp(&a->in6, &b->in6, sizeof(a->in6)) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_v6(FirewallContext **ctx) {
|
static void test_v6(FirewallContext **ctx) {
|
||||||
union in_addr_union u = {}, u2 = {};
|
union in_addr_union u = {}, u2 = {};
|
||||||
uint8_t prefixlen;
|
uint8_t prefixlen;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
make_in6_addr_union("dead::beef", &u);
|
MAKE_IN6_ADDR_UNION("dead::beef", &u);
|
||||||
|
|
||||||
r = fw_add_masquerade(ctx, true, AF_INET6, &u, 128);
|
r = fw_add_masquerade(ctx, true, AF_INET6, &u, 128);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -55,7 +35,7 @@ static void test_v6(FirewallContext **ctx) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to modify firewall: %m");
|
log_error_errno(r, "Failed to modify firewall: %m");
|
||||||
|
|
||||||
make_in6_addr_union("1c3::c01d", &u2);
|
MAKE_IN6_ADDR_UNION("1c3::c01d", &u2);
|
||||||
r = fw_add_local_dnat(ctx, true, AF_INET6, IPPROTO_TCP, 4711, &u2, 815, &u);
|
r = fw_add_local_dnat(ctx, true, AF_INET6, IPPROTO_TCP, 4711, &u2, 815, &u);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to modify firewall: %m");
|
log_error_errno(r, "Failed to modify firewall: %m");
|
||||||
@ -77,52 +57,6 @@ static void test_v6(FirewallContext **ctx) {
|
|||||||
log_error_errno(r, "Failed to modify ipv6 firewall: %m");
|
log_error_errno(r, "Failed to modify ipv6 firewall: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_v6_range(void) {
|
|
||||||
unsigned int prefixlen = 64;
|
|
||||||
union in_addr_union a, b, s;
|
|
||||||
|
|
||||||
make_in6_addr_union("dead:0:0:beef::", &s);
|
|
||||||
|
|
||||||
nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
|
|
||||||
|
|
||||||
assert_in6_eq(&s, &a);
|
|
||||||
assert_se(test_in6_eq("dead:0:0:bef0::", &b));
|
|
||||||
|
|
||||||
make_in6_addr_union("2001::", &s);
|
|
||||||
prefixlen = 56;
|
|
||||||
nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
|
|
||||||
assert_in6_eq(&s, &a);
|
|
||||||
assert_se(test_in6_eq("2001:0:0:0100::", &b));
|
|
||||||
|
|
||||||
prefixlen = 48;
|
|
||||||
nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
|
|
||||||
assert_in6_eq(&s, &a);
|
|
||||||
|
|
||||||
assert_se(test_in6_eq("2001:0:0001::", &b));
|
|
||||||
|
|
||||||
prefixlen = 65;
|
|
||||||
nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
|
|
||||||
assert_se(test_in6_eq("2001::", &a));
|
|
||||||
|
|
||||||
assert_se(test_in6_eq("2001::8000:0:0:0", &b));
|
|
||||||
|
|
||||||
prefixlen = 66;
|
|
||||||
nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
|
|
||||||
assert_in6_eq(&s, &a);
|
|
||||||
|
|
||||||
assert_se(test_in6_eq("2001::4000:0:0:0", &b));
|
|
||||||
|
|
||||||
prefixlen = 127;
|
|
||||||
nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
|
|
||||||
assert_in6_eq(&s, &a);
|
|
||||||
assert_se(test_in6_eq("2001::0002", &b));
|
|
||||||
|
|
||||||
make_in6_addr_union("dead:beef::1", &s);
|
|
||||||
prefixlen = 64;
|
|
||||||
nft_in6addr_to_range(&s, prefixlen, &a.in6, &b.in6);
|
|
||||||
assert_se(test_in6_eq("dead:beef::", &a));
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
_cleanup_(fw_ctx_freep) FirewallContext *ctx;
|
_cleanup_(fw_ctx_freep) FirewallContext *ctx;
|
||||||
int r;
|
int r;
|
||||||
@ -175,7 +109,6 @@ int main(int argc, char *argv[]) {
|
|||||||
log_error_errno(r, "Failed to modify firewall: %m");
|
log_error_errno(r, "Failed to modify firewall: %m");
|
||||||
|
|
||||||
test_v6(&ctx);
|
test_v6(&ctx);
|
||||||
test_v6_range();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -238,10 +238,12 @@ static void test_in_addr_prefix_intersect(void) {
|
|||||||
static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
|
static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
|
||||||
union in_addr_union ubefore, uafter, t;
|
union in_addr_union ubefore, uafter, t;
|
||||||
|
|
||||||
|
log_info("/* %s(%s, prefixlen=%u) */", __func__, before, pl);
|
||||||
|
|
||||||
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
|
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
|
||||||
|
|
||||||
t = ubefore;
|
t = ubefore;
|
||||||
assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after);
|
assert_se((in_addr_prefix_next(f, &t, pl) >= 0) == !!after);
|
||||||
|
|
||||||
if (after) {
|
if (after) {
|
||||||
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
|
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
|
||||||
@ -250,13 +252,12 @@ static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigne
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_in_addr_prefix_next(void) {
|
static void test_in_addr_prefix_next(void) {
|
||||||
log_info("/* %s */", __func__);
|
|
||||||
|
|
||||||
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
|
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
|
||||||
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
|
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
|
||||||
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
|
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
|
||||||
|
|
||||||
test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1");
|
test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1");
|
||||||
|
test_in_addr_prefix_next_one(AF_INET, "255.255.255.254", 32, "255.255.255.255");
|
||||||
test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL);
|
test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL);
|
||||||
test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL);
|
test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL);
|
||||||
|
|
||||||
@ -275,10 +276,12 @@ static void test_in_addr_prefix_next(void) {
|
|||||||
static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) {
|
static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) {
|
||||||
union in_addr_union ubefore, uafter, t;
|
union in_addr_union ubefore, uafter, t;
|
||||||
|
|
||||||
|
log_info("/* %s(%s, prefixlen=%u, nth=%"PRIu64") */", __func__, before, pl, nth);
|
||||||
|
|
||||||
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
|
assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
|
||||||
|
|
||||||
t = ubefore;
|
t = ubefore;
|
||||||
assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after);
|
assert_se((in_addr_prefix_nth(f, &t, pl, nth) >= 0) == !!after);
|
||||||
|
|
||||||
if (after) {
|
if (after) {
|
||||||
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
|
assert_se(in_addr_from_string(f, after, &uafter) >= 0);
|
||||||
@ -287,10 +290,9 @@ static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_in_addr_prefix_nth(void) {
|
static void test_in_addr_prefix_nth(void) {
|
||||||
log_info("/* %s */", __func__);
|
|
||||||
|
|
||||||
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0");
|
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0");
|
||||||
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0");
|
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 0, "192.168.0.0");
|
||||||
|
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 1, "192.168.1.0");
|
||||||
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0");
|
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0");
|
||||||
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128");
|
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128");
|
||||||
test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128");
|
test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128");
|
||||||
@ -309,6 +311,48 @@ static void test_in_addr_prefix_nth(void) {
|
|||||||
test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL);
|
test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL);
|
||||||
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL);
|
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL);
|
||||||
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL);
|
test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL);
|
||||||
|
test_in_addr_prefix_nth_one(AF_INET6, "1234:5678:90ab:cdef:1234:5678:90ab:cdef", 12, 1, "1240::");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_in_addr_prefix_range_one(
|
||||||
|
int family,
|
||||||
|
const char *in,
|
||||||
|
unsigned prefixlen,
|
||||||
|
const char *expected_start,
|
||||||
|
const char *expected_end) {
|
||||||
|
|
||||||
|
union in_addr_union a, s, e;
|
||||||
|
|
||||||
|
log_info("/* %s(%s, prefixlen=%u) */", __func__, in, prefixlen);
|
||||||
|
|
||||||
|
assert_se(in_addr_from_string(family, in, &a) >= 0);
|
||||||
|
assert_se((in_addr_prefix_range(family, &a, prefixlen, &s, &e) >= 0) == !!expected_start);
|
||||||
|
|
||||||
|
if (expected_start) {
|
||||||
|
union in_addr_union es;
|
||||||
|
|
||||||
|
assert_se(in_addr_from_string(family, expected_start, &es) >= 0);
|
||||||
|
assert_se(in_addr_equal(family, &s, &es) > 0);
|
||||||
|
}
|
||||||
|
if (expected_end) {
|
||||||
|
union in_addr_union ee;
|
||||||
|
|
||||||
|
assert_se(in_addr_from_string(family, expected_end, &ee) >= 0);
|
||||||
|
assert_se(in_addr_equal(family, &e, &ee) > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_in_addr_prefix_range(void) {
|
||||||
|
test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 24, "192.168.123.0", "192.168.124.0");
|
||||||
|
test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 16, "192.168.0.0", "192.169.0.0");
|
||||||
|
|
||||||
|
test_in_addr_prefix_range_one(AF_INET6, "dead:beef::", 64, "dead:beef::", "dead:beef:0:1::");
|
||||||
|
test_in_addr_prefix_range_one(AF_INET6, "dead:0:0:beef::", 64, "dead:0:0:beef::", "dead:0:0:bef0::");
|
||||||
|
test_in_addr_prefix_range_one(AF_INET6, "2001::", 48, "2001::", "2001:0:1::");
|
||||||
|
test_in_addr_prefix_range_one(AF_INET6, "2001::", 56, "2001::", "2001:0:0:0100::");
|
||||||
|
test_in_addr_prefix_range_one(AF_INET6, "2001::", 65, "2001::", "2001::8000:0:0:0");
|
||||||
|
test_in_addr_prefix_range_one(AF_INET6, "2001::", 66, "2001::", "2001::4000:0:0:0");
|
||||||
|
test_in_addr_prefix_range_one(AF_INET6, "2001::", 127, "2001::", "2001::2");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_in_addr_to_string_one(int f, const char *addr) {
|
static void test_in_addr_to_string_one(int f, const char *addr) {
|
||||||
@ -339,6 +383,7 @@ int main(int argc, char *argv[]) {
|
|||||||
test_in_addr_prefix_intersect();
|
test_in_addr_prefix_intersect();
|
||||||
test_in_addr_prefix_next();
|
test_in_addr_prefix_next();
|
||||||
test_in_addr_prefix_nth();
|
test_in_addr_prefix_nth();
|
||||||
|
test_in_addr_prefix_range();
|
||||||
test_in_addr_to_string();
|
test_in_addr_to_string();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user