1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-07 09:56:51 +03:00

networkd: Add hashmap to store prefixes and associated link

Add a hashmap to the Manager struct that stores the association
between an IPv6 prefix and the network Link it is assigned to.
This is added in order to keep assigning the same prefixes with
the same links even though they are delegated at different times
or by different DHCPv6 clients.
This commit is contained in:
Patrik Flykt 2018-01-04 15:11:58 +02:00
parent de661ccec7
commit e133b289aa
2 changed files with 85 additions and 0 deletions

View File

@ -1234,6 +1234,77 @@ static int manager_dirty_handler(sd_event_source *s, void *userdata) {
return 1;
}
Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
assert_return(m, NULL);
assert_return(m->dhcp6_prefixes, NULL);
assert_return(addr, NULL);
return hashmap_get(m->dhcp6_prefixes, addr);
}
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
assert_return(m, -EINVAL);
assert_return(m->dhcp6_prefixes, -ENODATA);
assert_return(addr, -EINVAL);
return hashmap_put(m->dhcp6_prefixes, addr, link);
}
int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
Link *l;
assert_return(m, -EINVAL);
assert_return(m->dhcp6_prefixes, -ENODATA);
assert_return(addr, -EINVAL);
l = hashmap_remove(m->dhcp6_prefixes, addr);
if (!l)
return -EINVAL;
(void) sd_radv_remove_prefix(l->radv, addr, 64);
return 0;
}
int manager_dhcp6_prefix_remove_all(Manager *m, Link *link) {
Iterator i;
Link *l;
struct in6_addr *addr;
assert_return(m, -EINVAL);
assert_return(l, -EINVAL);
HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i) {
if (l != link)
continue;
(void) sd_radv_remove_prefix(l->radv, addr, 64);
hashmap_remove(m->dhcp6_prefixes, addr);
}
return 0;
}
static void dhcp6_prefixes_hash_func(const void *p, struct siphash *state) {
const struct in6_addr *addr = p;
assert(p);
siphash24_compress(addr, sizeof(*addr), state);
}
static int dhcp6_prefixes_compare_func(const void *_a, const void *_b) {
const struct in6_addr *a = _a, *b = _b;
return memcmp(&a, &b, sizeof(*a));
}
static const struct hash_ops dhcp6_prefixes_hash_ops = {
.hash = dhcp6_prefixes_hash_func,
.compare = dhcp6_prefixes_compare_func,
};
int manager_new(Manager **ret, sd_event *event) {
_cleanup_manager_free_ Manager *m = NULL;
int r;
@ -1270,6 +1341,10 @@ int manager_new(Manager **ret, sd_event *event) {
if (r < 0)
return r;
m->dhcp6_prefixes = hashmap_new(&dhcp6_prefixes_hash_ops);
if (!m->dhcp6_prefixes)
return -ENOMEM;
m->duid.type = DUID_TYPE_EN;
(void) routing_policy_load_rules(m->state_file, &m->rules_saved);
@ -1294,6 +1369,10 @@ void manager_free(Manager *m) {
while ((network = m->networks))
network_free(network);
while ((link = hashmap_first(m->dhcp6_prefixes)))
link_unref(link);
hashmap_free(m->dhcp6_prefixes);
while ((link = hashmap_first(m->links)))
link_unref(link);
hashmap_free(m->links);

View File

@ -58,6 +58,7 @@ struct Manager {
Hashmap *links;
Hashmap *netdevs;
Hashmap *networks_by_name;
Hashmap *dhcp6_prefixes;
LIST_HEAD(Network, networks);
LIST_HEAD(AddressPool, address_pools);
@ -109,5 +110,10 @@ Link* manager_find_uplink(Manager *m, Link *exclude);
int manager_set_hostname(Manager *m, const char *hostname);
int manager_set_timezone(Manager *m, const char *timezone);
Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr);
int manager_dhcp6_prefix_remove_all(Manager *m, Link *link);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
#define _cleanup_manager_free_ _cleanup_(manager_freep)