]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
manager: Add and remove routes for DHCPv6 Prefix Delegation
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Thu, 4 Jan 2018 13:12:00 +0000 (15:12 +0200)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Thu, 4 Jan 2018 13:22:44 +0000 (15:22 +0200)
Configure routes to the links they are delegated to. Remove routes
once the delegation itself or the link is removed.

src/network/networkd-manager.c

index 9d9d96ec8f1ace0ee09750b38461a14bb5a7da03..2a0a546d5434791c76aaf051fe52ed4696b16c4f 100644 (file)
@@ -1242,16 +1242,82 @@ Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
         return hashmap_get(m->dhcp6_prefixes, addr);
 }
 
+static int dhcp6_route_add_callback(sd_netlink *nl, sd_netlink_message *m,
+                                       void *userdata) {
+        Link *l = userdata;
+        int r;
+        union in_addr_union prefix;
+        _cleanup_free_ char *buf = NULL;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r != 0) {
+                log_link_debug_errno(l, r, "Received error adding DHCPv6 Prefix Delegation route: %m");
+                return 0;
+        }
+
+        r = sd_netlink_message_read_in6_addr(m, RTA_DST, &prefix.in6);
+        if (r < 0) {
+                log_link_debug_errno(l, r, "Could not read IPv6 address from DHCPv6 Prefix Delegation while adding route: %m");
+                return 0;
+        }
+
+        (void) in_addr_to_string(AF_INET6, &prefix, &buf);
+        log_link_debug(l, "Added DHCPv6 Prefix Deleagtion route %s/64",
+                       strnull(buf));
+
+        return 0;
+}
+
 int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
+        int r;
+        Route *route;
+
         assert_return(m, -EINVAL);
         assert_return(m->dhcp6_prefixes, -ENODATA);
         assert_return(addr, -EINVAL);
 
+        r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64,
+                      0, 0, 0, &route);
+        if (r < 0)
+                return r;
+
+        r = route_configure(route, link, dhcp6_route_add_callback);
+        if (r < 0)
+                return r;
+
         return hashmap_put(m->dhcp6_prefixes, addr, link);
 }
 
+static int dhcp6_route_remove_callback(sd_netlink *nl, sd_netlink_message *m,
+                                       void *userdata) {
+        Link *l = userdata;
+        int r;
+        union in_addr_union prefix;
+        _cleanup_free_ char *buf = NULL;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r != 0) {
+                log_link_debug_errno(l, r, "Received error on DHCPv6 Prefix Delegation route removal: %m");
+                return 0;
+        }
+
+        r = sd_netlink_message_read_in6_addr(m, RTA_DST, &prefix.in6);
+        if (r < 0) {
+                log_link_debug_errno(l, r, "Could not read IPv6 address from DHCPv6 Prefix Delegation while removing route: %m");
+                return 0;
+        }
+
+        (void) in_addr_to_string(AF_INET6, &prefix, &buf);
+        log_link_debug(l, "Removed DHCPv6 Prefix Delegation route %s/64",
+                       strnull(buf));
+
+        return 0;
+}
+
 int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
         Link *l;
+        int r;
+        Route *route;
 
         assert_return(m, -EINVAL);
         assert_return(m->dhcp6_prefixes, -ENODATA);
@@ -1262,6 +1328,10 @@ int manager_dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) {
                 return -EINVAL;
 
         (void) sd_radv_remove_prefix(l->radv, addr, 64);
+        r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64,
+                      0, 0, 0, &route);
+        if (r >= 0)
+                (void) route_remove(route, l, dhcp6_route_remove_callback);
 
         return 0;
 }
@@ -1278,9 +1348,7 @@ int manager_dhcp6_prefix_remove_all(Manager *m, Link *link) {
                 if (l != link)
                         continue;
 
-                (void) sd_radv_remove_prefix(l->radv, addr, 64);
-
-                hashmap_remove(m->dhcp6_prefixes, addr);
+                (void) manager_dhcp6_prefix_remove(m, addr);
         }
 
         return 0;