Merge pull request #11770 from yuwata/fix-9955
network: rework address pool
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "in-addr-util.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "random-util.h"
|
||||
#include "util.h"
|
||||
|
||||
bool in4_addr_is_null(const struct in_addr *a) {
|
||||
@@ -215,6 +216,83 @@ int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen)
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
int in_addr_random_prefix(
|
||||
int family,
|
||||
union in_addr_union *u,
|
||||
unsigned prefixlen_fixed_part,
|
||||
unsigned prefixlen) {
|
||||
|
||||
assert(u);
|
||||
|
||||
/* Random network part of an address by one. */
|
||||
|
||||
if (prefixlen <= 0)
|
||||
return 0;
|
||||
|
||||
if (family == AF_INET) {
|
||||
uint32_t c, n;
|
||||
|
||||
if (prefixlen_fixed_part > 32)
|
||||
prefixlen_fixed_part = 32;
|
||||
if (prefixlen > 32)
|
||||
prefixlen = 32;
|
||||
if (prefixlen_fixed_part >= prefixlen)
|
||||
return -EINVAL;
|
||||
|
||||
c = be32toh(u->in.s_addr);
|
||||
c &= ((UINT32_C(1) << prefixlen_fixed_part) - 1) << (32 - prefixlen_fixed_part);
|
||||
|
||||
random_bytes(&n, sizeof(n));
|
||||
n &= ((UINT32_C(1) << (prefixlen - prefixlen_fixed_part)) - 1) << (32 - prefixlen);
|
||||
|
||||
u->in.s_addr = htobe32(n | c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (family == AF_INET6) {
|
||||
struct in6_addr n;
|
||||
unsigned i, j;
|
||||
|
||||
if (prefixlen_fixed_part > 128)
|
||||
prefixlen_fixed_part = 128;
|
||||
if (prefixlen > 128)
|
||||
prefixlen = 128;
|
||||
if (prefixlen_fixed_part >= prefixlen)
|
||||
return -EINVAL;
|
||||
|
||||
random_bytes(&n, sizeof(n));
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
uint8_t mask_fixed_part = 0, mask = 0;
|
||||
|
||||
if (i < (prefixlen_fixed_part + 7) / 8) {
|
||||
if (i < prefixlen_fixed_part / 8)
|
||||
mask_fixed_part = 0xffu;
|
||||
else {
|
||||
j = prefixlen_fixed_part % 8;
|
||||
mask_fixed_part = ((UINT8_C(1) << (j + 1)) - 1) << (8 - j);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < (prefixlen + 7) / 8) {
|
||||
if (i < prefixlen / 8)
|
||||
mask = 0xffu ^ mask_fixed_part;
|
||||
else {
|
||||
j = prefixlen % 8;
|
||||
mask = (((UINT8_C(1) << (j + 1)) - 1) << (8 - j)) ^ mask_fixed_part;
|
||||
}
|
||||
}
|
||||
|
||||
u->in6.s6_addr[i] &= mask_fixed_part;
|
||||
u->in6.s6_addr[i] |= n.s6_addr[i] & mask;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
|
||||
char *x;
|
||||
size_t l;
|
||||
|
||||
@@ -35,6 +35,7 @@ bool in4_addr_is_non_local(const struct in_addr *a);
|
||||
int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b);
|
||||
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
|
||||
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
|
||||
int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);
|
||||
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
|
||||
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
|
||||
int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
|
||||
|
||||
Reference in New Issue
Block a user