]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-address-pool.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "alloc-util.h"
4 #include "networkd-address-pool.h"
5 #include "networkd-manager.h"
7 #include "string-util.h"
9 #define RANDOM_PREFIX_TRIAL_MAX 1024
11 static int address_pool_new(
15 const union in_addr_union
*u
,
24 p
= new(AddressPool
, 1);
31 .prefixlen
= prefixlen
,
35 LIST_PREPEND(address_pools
, m
->address_pools
, p
);
41 int address_pool_new_from_string(
48 union in_addr_union u
;
55 r
= in_addr_from_string(family
, p
, &u
);
59 return address_pool_new(m
, ret
, family
, &u
, prefixlen
);
62 void address_pool_free(AddressPool
*p
) {
68 LIST_REMOVE(address_pools
, p
->manager
->address_pools
, p
);
73 static bool address_pool_prefix_is_taken(
75 const union in_addr_union
*u
,
84 HASHMAP_FOREACH(l
, p
->manager
->links
) {
87 /* Don't clash with assigned addresses */
88 SET_FOREACH(a
, l
->addresses
) {
89 if (a
->family
!= p
->family
)
92 if (in_addr_prefix_intersect(p
->family
, u
, prefixlen
, &a
->in_addr
, a
->prefixlen
))
96 /* Don't clash with addresses already pulled from the pool, but not assigned yet */
97 LIST_FOREACH(addresses
, a
, l
->pool_addresses
) {
98 if (a
->family
!= p
->family
)
101 if (in_addr_prefix_intersect(p
->family
, u
, prefixlen
, &a
->in_addr
, a
->prefixlen
))
106 /* And don't clash with configured but un-assigned addresses either */
107 ORDERED_HASHMAP_FOREACH(n
, p
->manager
->networks
) {
110 LIST_FOREACH(addresses
, a
, n
->static_addresses
) {
111 if (a
->family
!= p
->family
)
114 if (in_addr_prefix_intersect(p
->family
, u
, prefixlen
, &a
->in_addr
, a
->prefixlen
))
122 int address_pool_acquire(AddressPool
*p
, unsigned prefixlen
, union in_addr_union
*found
) {
123 union in_addr_union u
;
128 assert(prefixlen
> 0);
131 if (p
->prefixlen
>= prefixlen
)
136 for (i
= 0; i
< RANDOM_PREFIX_TRIAL_MAX
; i
++) {
137 r
= in_addr_random_prefix(p
->family
, &u
, p
->prefixlen
, prefixlen
);
141 if (!address_pool_prefix_is_taken(p
, &u
, prefixlen
)) {
143 _cleanup_free_
char *s
= NULL
;
145 (void) in_addr_to_string(p
->family
, &u
, &s
);
146 log_debug("Found range %s/%u", strna(s
), prefixlen
);