]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: configure NDisc after MAC address is assigned
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 31 Jan 2022 03:35:44 +0000 (12:35 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 31 Jan 2022 04:10:28 +0000 (13:10 +0900)
src/network/networkd-link.c
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h
src/network/networkd-queue.c
src/network/networkd-queue.h

index ab4f321b0064ddcfeeeeacb97cd2c5cc3e748f76..a8de644559bde59e1bdd33b4e0990e760a6ecfd7 100644 (file)
@@ -1200,7 +1200,7 @@ static int link_configure(Link *link) {
         if (r < 0)
                 return r;
 
-        r = ndisc_configure(link);
+        r = link_request_ndisc(link);
         if (r < 0)
                 return r;
 
index f616f2c9bc71b557e96d2ffdc43e03e746a847f2..4193b510931b0b9ae8bd53bad6a9d115b84e9a77 100644 (file)
@@ -34,6 +34,12 @@ bool link_ipv6_accept_ra_enabled(Link *link) {
         if (link->flags & IFF_LOOPBACK)
                 return false;
 
+        if (link->hw_addr.length != ETH_ALEN && !streq_ptr(link->kind, "wwan"))
+                /* Currently, only interfaces whose MAC address length is ETH_ALEN are supported.
+                 * Note, wwan interfaces may be assigned MAC address slightly later.
+                 * Hence, let's wait for a while.*/
+                return false;
+
         if (!link->network)
                 return false;
 
@@ -1055,7 +1061,7 @@ static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event_t event, sd_ndisc_router
         }
 }
 
-int ndisc_configure(Link *link) {
+static int ndisc_configure(Link *link) {
         int r;
 
         assert(link);
@@ -1090,6 +1096,8 @@ int ndisc_configure(Link *link) {
 }
 
 int ndisc_start(Link *link) {
+        int r;
+
         assert(link);
 
         if (!link->ndisc || !link->dhcp6_client)
@@ -1103,7 +1111,60 @@ int ndisc_start(Link *link) {
 
         log_link_debug(link, "Discovering IPv6 routers");
 
-        return sd_ndisc_start(link->ndisc);
+        r = sd_ndisc_start(link->ndisc);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+int request_process_ndisc(Request *req) {
+        Link *link;
+        int r;
+
+        assert(req);
+        assert(req->type == REQUEST_TYPE_NDISC);
+
+        link = ASSERT_PTR(req->link);
+
+        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
+                return 0;
+
+        if (link->hw_addr.length != ETH_ALEN || hw_addr_is_null(&link->hw_addr))
+                /* No MAC address is assigned to the hardware, or non-supported MAC address length. */
+                return 0;
+
+        r = ndisc_configure(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to configure IPv6 Router Discovery: %m");
+
+        r = ndisc_start(link);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to start IPv6 Router Discovery: %m");
+
+        log_link_debug(link, "IPv6 Router Discovery is configured%s.",
+                       r > 0 ? " and started" : "");
+
+        return 1;
+}
+
+int link_request_ndisc(Link *link) {
+        int r;
+
+        assert(link);
+
+        if (!link_ipv6_accept_ra_enabled(link))
+                return 0;
+
+        if (link->ndisc)
+                return 0;
+
+        r = link_queue_request(link, REQUEST_TYPE_NDISC, NULL, false, NULL, NULL, NULL);
+        if (r < 0)
+                return log_link_warning_errno(link, r, "Failed to request configuring of the IPv6 Router Discovery: %m");
+
+        log_link_debug(link, "Requested configuring of the IPv6 Router Discovery.");
+        return 0;
 }
 
 void ndisc_vacuum(Link *link) {
index acb97a892e2240c992aece0dc3418ef501456515..1958652778d47693901f4d5c685da441cd364d7c 100644 (file)
@@ -6,6 +6,7 @@
 
 typedef struct Link Link;
 typedef struct Network Network;
+typedef struct Request Request;
 
 typedef enum IPv6AcceptRAStartDHCP6Client {
         IPV6_ACCEPT_RA_START_DHCP6_CLIENT_NO,
@@ -43,10 +44,12 @@ bool link_ipv6_accept_ra_enabled(Link *link);
 
 void network_adjust_ipv6_accept_ra(Network *network);
 
-int ndisc_configure(Link *link);
 int ndisc_start(Link *link);
 void ndisc_vacuum(Link *link);
 void ndisc_flush(Link *link);
 
+int request_process_ndisc(Request *req);
+int link_request_ndisc(Link *link);
+
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_start_dhcp6_client);
 CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_accept_ra_use_domains);
index 8cd5300ce60e18751664e99e47c614f671f80989..14dc1cf4926e81644dd2a91192f6bb4d15e01899 100644 (file)
@@ -9,6 +9,7 @@
 #include "networkd-dhcp6.h"
 #include "networkd-ipv6-proxy-ndp.h"
 #include "networkd-manager.h"
+#include "networkd-ndisc.h"
 #include "networkd-neighbor.h"
 #include "networkd-nexthop.h"
 #include "networkd-route.h"
@@ -39,6 +40,8 @@ static void request_free_object(RequestType type, void *object) {
         case REQUEST_TYPE_IPV6_PROXY_NDP:
                 free(object);
                 break;
+        case REQUEST_TYPE_NDISC:
+                break;
         case REQUEST_TYPE_NEIGHBOR:
                 neighbor_free(object);
                 break;
@@ -119,6 +122,9 @@ static void request_hash_func(const Request *req, struct siphash *state) {
         case REQUEST_TYPE_IPV6_PROXY_NDP:
                 in6_addr_hash_func(req->ipv6_proxy_ndp, state);
                 break;
+        case REQUEST_TYPE_NDISC:
+                /* This type does not have an object. */
+                break;
         case REQUEST_TYPE_NEIGHBOR:
                 neighbor_hash_func(req->neighbor, state);
                 break;
@@ -177,6 +183,8 @@ static int request_compare_func(const struct Request *a, const struct Request *b
                 return 0;
         case REQUEST_TYPE_IPV6_PROXY_NDP:
                 return in6_addr_compare_func(a->ipv6_proxy_ndp, b->ipv6_proxy_ndp);
+        case REQUEST_TYPE_NDISC:
+                return 0;
         case REQUEST_TYPE_NEIGHBOR:
                 return neighbor_compare_func(a->neighbor, b->neighbor);
         case REQUEST_TYPE_NEXTHOP:
@@ -224,6 +232,7 @@ int link_queue_request(
                       REQUEST_TYPE_DHCP_SERVER,
                       REQUEST_TYPE_DHCP4_CLIENT,
                       REQUEST_TYPE_DHCP6_CLIENT,
+                      REQUEST_TYPE_NDISC,
                       REQUEST_TYPE_RADV,
                       REQUEST_TYPE_SET_LINK,
                       REQUEST_TYPE_UP_DOWN) ||
@@ -232,6 +241,7 @@ int link_queue_request(
                       REQUEST_TYPE_DHCP_SERVER,
                       REQUEST_TYPE_DHCP4_CLIENT,
                       REQUEST_TYPE_DHCP6_CLIENT,
+                      REQUEST_TYPE_NDISC,
                       REQUEST_TYPE_RADV) ||
                netlink_handler);
 
@@ -314,6 +324,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
                         case REQUEST_TYPE_IPV6_PROXY_NDP:
                                 r = request_process_ipv6_proxy_ndp_address(req);
                                 break;
+                        case REQUEST_TYPE_NDISC:
+                                r = request_process_ndisc(req);
+                                break;
                         case REQUEST_TYPE_NEIGHBOR:
                                 r = request_process_neighbor(req);
                                 break;
index c0cdacfbd8027bbe59527a52beb03558bf632394..ac33e885f2bc6fe29cf0eac9aeccf0b13d28e23d 100644 (file)
@@ -25,6 +25,7 @@ typedef enum RequestType {
         REQUEST_TYPE_DHCP4_CLIENT,
         REQUEST_TYPE_DHCP6_CLIENT,
         REQUEST_TYPE_IPV6_PROXY_NDP,
+        REQUEST_TYPE_NDISC,
         REQUEST_TYPE_NEIGHBOR,
         REQUEST_TYPE_NEXTHOP,
         REQUEST_TYPE_RADV,