]>
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
,
85 HASHMAP_FOREACH(l
, p
->manager
->links
, i
) {
89 /* Don't clash with assigned addresses */
90 SET_FOREACH(a
, l
->addresses
, j
) {
91 if (a
->family
!= p
->family
)
94 if (in_addr_prefix_intersect(p
->family
, u
, prefixlen
, &a
->in_addr
, a
->prefixlen
))
98 /* Don't clash with addresses already pulled from the pool, but not assigned yet */
99 LIST_FOREACH(addresses
, a
, l
->pool_addresses
) {
100 if (a
->family
!= p
->family
)
103 if (in_addr_prefix_intersect(p
->family
, u
, prefixlen
, &a
->in_addr
, a
->prefixlen
))
108 /* And don't clash with configured but un-assigned addresses either */
109 ORDERED_HASHMAP_FOREACH(n
, p
->manager
->networks
, i
) {
112 LIST_FOREACH(addresses
, a
, n
->static_addresses
) {
113 if (a
->family
!= p
->family
)
116 if (in_addr_prefix_intersect(p
->family
, u
, prefixlen
, &a
->in_addr
, a
->prefixlen
))
124 int address_pool_acquire(AddressPool
*p
, unsigned prefixlen
, union in_addr_union
*found
) {
125 union in_addr_union u
;
130 assert(prefixlen
> 0);
133 if (p
->prefixlen
>= prefixlen
)
138 for (i
= 0; i
< RANDOM_PREFIX_TRIAL_MAX
; i
++) {
139 r
= in_addr_random_prefix(p
->family
, &u
, p
->prefixlen
, prefixlen
);
143 if (!address_pool_prefix_is_taken(p
, &u
, prefixlen
)) {
145 _cleanup_free_
char *s
= NULL
;
147 (void) in_addr_to_string(p
->family
, &u
, &s
);
148 log_debug("Found range %s/%u", strna(s
), prefixlen
);