]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: Add hashmap to store prefixes and associated link
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Thu, 4 Jan 2018 13:11:58 +0000 (15:11 +0200)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Thu, 4 Jan 2018 13:22:44 +0000 (15:22 +0200)
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.

src/network/networkd-manager.c
src/network/networkd-manager.h

index e3c514c8044829c03fedc3713a2d6c5c412a1026..9d9d96ec8f1ace0ee09750b38461a14bb5a7da03 100644 (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);
index 186cb418911b3ed033bd766f22d215183f9236a2..c46914f78d6b83bfa44c684ed982427826561420 100644 (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)