]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: use request queue to set IPv6LL address generation mode
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 21 May 2021 05:43:35 +0000 (14:43 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 7 Jun 2021 21:33:27 +0000 (06:33 +0900)
src/network/networkd-link.c
src/network/networkd-setlink.c
src/network/networkd-setlink.h

index dfd1806786e7e3f0119d4c0f22ba2d42745b6d79..5a1dba18d3369dcde3a6d5532ffe01d3d4ccd696 100644 (file)
@@ -56,7 +56,6 @@
 #include "stdio-util.h"
 #include "string-table.h"
 #include "strv.h"
-#include "sysctl-util.h"
 #include "tc.h"
 #include "tmpfile-util.h"
 #include "udev-util.h"
@@ -1026,97 +1025,6 @@ bool link_has_carrier(Link *link) {
         return false;
 }
 
-static int link_address_genmode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(m);
-        assert(link);
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 0;
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0) {
-                log_link_message_warning_errno(link, m, r, "Could not set IPv6LL address generation mode, ignoring");
-                return 0;
-        }
-
-        log_link_debug(link, "IPv6LL address genaration mode set.");
-
-        r = link_drop_ipv6ll_addresses(link);
-        if (r < 0) {
-                log_link_warning_errno(link, r, "Failed to drop IPv6LL address: %m");
-                link_enter_failed(link);
-        }
-
-        return 0;
-}
-
-static int link_configure_addrgen_mode(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        uint8_t ipv6ll_mode;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->manager);
-        assert(link->manager->rtnl);
-
-        if (!socket_ipv6_is_supported())
-                return 0;
-
-        log_link_debug(link, "Setting IPv6LL address generation mode for link");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
-
-        r = sd_netlink_message_open_container(req, AF_INET6);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
-
-        if (!link_ipv6ll_enabled(link))
-                ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
-        else if (link->network->ipv6ll_address_gen_mode < 0) {
-                r = sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL);
-                if (r < 0) {
-                        /* The file may not exist. And even if it exists, when stable_secret is unset,
-                         * reading the file fails with ENOMEM when read_full_virtual_file(), which uses
-                         * read() as the backend, and EIO when read_one_line_file() which uses fgetc(). */
-                        log_link_debug_errno(link, r, "Failed to read sysctl property stable_secret, ignoring: %m");
-
-                        ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
-                } else
-                        ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
-        } else
-                ipv6ll_mode = link->network->ipv6ll_address_gen_mode;
-
-        r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE attribute: %m");
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_address_genmode_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return 0;
-}
-
 static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -1879,7 +1787,7 @@ static int link_configure(Link *link) {
         if (r < 0)
                 return r;
 
-        r = link_configure_addrgen_mode(link);
+        r = link_request_to_set_addrgen_mode(link);
         if (r < 0)
                 return r;
 
index 1120c5b922912118a24e0736356934a2b2fa70b4..89b414a321f90c043477220ee3e0e6b209f98515 100644 (file)
@@ -9,8 +9,10 @@
 #include "networkd-manager.h"
 #include "networkd-queue.h"
 #include "string-table.h"
+#include "sysctl-util.h"
 
 static const char *const set_link_operation_table[_SET_LINK_OPERATION_MAX] = {
+        [SET_LINK_ADDRESS_GENERATION_MODE] = "IPv6LL address generation mode",
         [SET_LINK_FLAGS]                   = "link flags",
         [SET_LINK_GROUP]                   = "interface group",
         [SET_LINK_MAC]                     = "MAC address",
@@ -48,6 +50,22 @@ static int set_link_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
         return 1;
 }
 
+static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        r = set_link_handler_internal(rtnl, m, link, SET_LINK_ADDRESS_GENERATION_MODE, true);
+        if (r <= 0)
+                return r;
+
+        r = link_drop_ipv6ll_addresses(link);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Failed to drop IPv6LL addresses: %m");
+                link_enter_failed(link);
+        }
+
+        return 0;
+}
+
 static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         return set_link_handler_internal(rtnl, m, link, SET_LINK_FLAGS, true);
 }
@@ -105,6 +123,27 @@ static int link_configure(
                 return log_link_debug_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
 
         switch (op) {
+        case SET_LINK_ADDRESS_GENERATION_MODE:
+                r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
+
+                r = sd_netlink_message_open_container(req, AF_INET6);
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not open AF_INET6 container: %m");
+
+                r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, PTR_TO_UINT8(userdata));
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE attribute: %m");
+
+                r = sd_netlink_message_close_container(req);
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not close AF_INET6 container: %m");
+
+                r = sd_netlink_message_close_container(req);
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
+                break;
         case SET_LINK_FLAGS: {
                 unsigned ifi_change = 0, ifi_flags = 0;
 
@@ -221,6 +260,42 @@ static int link_request_set_link(
         return 0;
 }
 
+int link_request_to_set_addrgen_mode(Link *link) {
+        Request *req;
+        uint8_t mode;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        if (!socket_ipv6_is_supported())
+                return 0;
+
+        if (!link_ipv6ll_enabled(link))
+                mode = IN6_ADDR_GEN_MODE_NONE;
+        else if (link->network->ipv6ll_address_gen_mode >= 0)
+                mode = link->network->ipv6ll_address_gen_mode;
+        else {
+                r = sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL);
+                if (r < 0) {
+                        /* The file may not exist. And even if it exists, when stable_secret is unset,
+                         * reading the file fails with ENOMEM when read_full_virtual_file(), which uses
+                         * read() as the backend, and EIO when read_one_line_file() which uses fgetc(). */
+                        log_link_debug_errno(link, r, "Failed to read sysctl property stable_secret, ignoring: %m");
+
+                        mode = IN6_ADDR_GEN_MODE_EUI64;
+                } else
+                        mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+        }
+
+        r = link_request_set_link(link, SET_LINK_ADDRESS_GENERATION_MODE, link_set_addrgen_mode_handler, &req);
+        if (r < 0)
+                return r;
+
+        req->userdata = UINT8_TO_PTR(mode);
+        return 0;
+}
+
 int link_request_to_set_flags(Link *link) {
         assert(link);
         assert(link->network);
index 42934c359018311f4e6bbe38e8d930fdebd127c9..33f1bbd37a015717d2aad238092b2c960e8c59b7 100644 (file)
@@ -7,6 +7,7 @@ typedef struct Link Link;
 typedef struct Request Request;
 
 typedef enum SetLinkOperation {
+        SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */
         SET_LINK_FLAGS,                   /* Setting IFF_NOARP or friends. */
         SET_LINK_GROUP,                   /* Setting interface group. */
         SET_LINK_MAC,                     /* Setting MAC address. */
@@ -15,6 +16,7 @@ typedef enum SetLinkOperation {
         _SET_LINK_OPERATION_INVALID = -EINVAL,
 } SetLinkOperation;
 
+int link_request_to_set_addrgen_mode(Link *link);
 int link_request_to_set_flags(Link *link);
 int link_request_to_set_group(Link *link);
 int link_request_to_set_mac(Link *link);