]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-link.c
networkd: Log error if LLDP fails to start/stop
[thirdparty/systemd.git] / src / network / networkd-link.c
index d3928e2862f3a034a4f8a7c1a9a51c3922ce7d6b..f13fcb7b6e67fa31d9cb2d173d4d59e4ebff7c46 100644 (file)
@@ -110,7 +110,7 @@ static bool link_dhcp4_server_enabled(Link *link) {
         return link->network->dhcp_server;
 }
 
-static bool link_ipv4ll_enabled(Link *link) {
+bool link_ipv4ll_enabled(Link *link) {
         assert(link);
 
         if (link->flags & IFF_LOOPBACK)
@@ -128,6 +128,24 @@ static bool link_ipv4ll_enabled(Link *link) {
         return link->network->link_local & ADDRESS_FAMILY_IPV4;
 }
 
+bool link_ipv4ll_fallback_enabled(Link *link) {
+        assert(link);
+
+        if (link->flags & IFF_LOOPBACK)
+                return false;
+
+        if (!link->network)
+                return false;
+
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+                return false;
+
+        if (link->network->bond)
+                return false;
+
+        return link->network->link_local & ADDRESS_FAMILY_FALLBACK_IPV4;
+}
+
 static bool link_ipv6ll_enabled(Link *link) {
         assert(link);
 
@@ -320,8 +338,7 @@ static int link_enable_ipv6(Link *link) {
 
         r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", disabled);
         if (r < 0)
-                log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m",
-                                       enable_disable(!disabled), link->ifname);
+                log_link_warning_errno(link, r, "Cannot %s IPv6: %m", enable_disable(!disabled));
         else
                 log_link_info(link, "IPv6 successfully %sd", enable_disable(!disabled));
 
@@ -506,8 +523,6 @@ static int link_update_flags(Link *link, sd_netlink_message *m) {
         return 0;
 }
 
-DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
-
 static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         _cleanup_(link_unrefp) Link *link = NULL;
         uint16_t type;
@@ -606,30 +621,15 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
 }
 
 static Link *link_free(Link *link) {
-        Link *carrier;
         Address *address;
-        Route *route;
-        Iterator i;
 
         assert(link);
 
-        while ((route = set_first(link->routes)))
-                route_free(route);
-
-        while ((route = set_first(link->routes_foreign)))
-                route_free(route);
+        link->routes = set_free_with_destructor(link->routes, route_free);
+        link->routes_foreign = set_free_with_destructor(link->routes_foreign, route_free);
 
-        link->routes = set_free(link->routes);
-        link->routes_foreign = set_free(link->routes_foreign);
-
-        while ((address = set_first(link->addresses)))
-                address_free(address);
-
-        while ((address = set_first(link->addresses_foreign)))
-                address_free(address);
-
-        link->addresses = set_free(link->addresses);
-        link->addresses_foreign = set_free(link->addresses_foreign);
+        link->addresses = set_free_with_destructor(link->addresses, address_free);
+        link->addresses_foreign = set_free_with_destructor(link->addresses_foreign, address_free);
 
         while ((address = link->pool_addresses)) {
                 LIST_REMOVE(addresses, link->pool_addresses, address);
@@ -662,16 +662,13 @@ static Link *link_free(Link *link) {
 
         sd_device_unref(link->sd_device);
 
-        HASHMAP_FOREACH (carrier, link->bound_to_links, i)
-                hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
         hashmap_free(link->bound_to_links);
-
-        HASHMAP_FOREACH (carrier, link->bound_by_links, i)
-                hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
         hashmap_free(link->bound_by_links);
 
         set_free_with_destructor(link->slaves, link_unref);
 
+        network_unref(link->network);
+
         return mfree(link);
 }
 
@@ -718,7 +715,7 @@ static void link_enter_unmanaged(Link *link) {
         link_dirty(link);
 }
 
-static int link_stop_clients(Link *link) {
+int link_stop_clients(Link *link) {
         int r = 0, k;
 
         assert(link);
@@ -913,7 +910,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         return 1;
 }
 
-static int link_request_set_routes(Link *link) {
+int link_request_set_routes(Link *link) {
         enum {
                 PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */
                 PHASE_GATEWAY,     /* Second phase: Routes with a gateway */
@@ -994,21 +991,18 @@ void link_check_ready(Link *link) {
         if (!link->routing_policy_rules_configured)
                 return;
 
-        if (link_ipv4ll_enabled(link))
-                if (!link->ipv4ll_address ||
-                    !link->ipv4ll_route)
-                        return;
+        if (link_ipv4ll_enabled(link) && !(link->ipv4ll_address && link->ipv4ll_route))
+                return;
 
         if (link_ipv6ll_enabled(link) &&
             in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address))
                 return;
 
-        if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
-             !link->dhcp4_configured) ||
-            (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
-             !link->dhcp6_configured) ||
-            (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) &&
-             !link->dhcp4_configured && !link->dhcp6_configured))
+        if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) &&
+            !(link->dhcp4_configured || link->dhcp6_configured) &&
+            !(link_ipv4ll_fallback_enabled(link) && link->ipv4ll_address && link->ipv4ll_route))
+                /* When DHCP is enabled, at least one protocol must provide an address, or
+                 * an IPv4ll fallback address must be configured. */
                 return;
 
         if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
@@ -1854,7 +1848,6 @@ static int link_acquire_ipv4_conf(Link *link) {
         int r;
 
         assert(link);
-        assert(link->network);
         assert(link->manager);
         assert(link->manager->event);
 
@@ -2038,6 +2031,8 @@ static int link_up(Link *link) {
         }
 
         if (link_ipv6_enabled(link)) {
+                uint8_t ipv6ll_mode;
+
                 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");
@@ -2053,6 +2048,19 @@ static int link_up(Link *link) {
                                 return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
                 }
 
+                if (!link_ipv6ll_enabled(link))
+                        ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
+                else if (sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL) < 0)
+                        /* The file may not exist. And event if it exists, when stable_secret is unset,
+                         * reading the file fails with EIO. */
+                        ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
+                else
+                        ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+
+                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: %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");
@@ -3019,10 +3027,14 @@ static int link_update_lldp(Link *link) {
                 r = sd_lldp_start(link->lldp);
                 if (r > 0)
                         log_link_debug(link, "Started LLDP.");
+                else
+                        log_link_warning_errno(link, r, "Failed to start LLDP: %m");
         } else {
                 r = sd_lldp_stop(link->lldp);
                 if (r > 0)
                         log_link_debug(link, "Stopped LLDP.");
+                else
+                        log_link_warning_errno(link, r, "Failed to stop LLDP: %m");
         }
 
         return r;
@@ -3115,7 +3127,7 @@ static int link_configure(Link *link) {
         if (r < 0)
                 return r;
 
-        if (link_ipv4ll_enabled(link)) {
+        if (link_ipv4ll_enabled(link) || link_ipv4ll_fallback_enabled(link)) {
                 r = ipv4ll_configure(link);
                 if (r < 0)
                         return r;
@@ -3365,7 +3377,7 @@ static int link_initialized_and_synced(Link *link) {
         /* We may get called either from the asynchronous netlink callback,
          * or directly for link_add() if running in a container. See link_add(). */
         if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED))
-                return 1;
+                return 0;
 
         log_link_debug(link, "Link state is up-to-date");
         link_set_state(link, LINK_STATE_INITIALIZED);
@@ -3383,7 +3395,7 @@ static int link_initialized_and_synced(Link *link) {
                                 &link->mac, &network);
                 if (r == -ENOENT) {
                         link_enter_unmanaged(link);
-                        return 1;
+                        return 0;
                 } else if (r == 0 && network->unmanaged) {
                         link_enter_unmanaged(link);
                         return 0;
@@ -3420,7 +3432,7 @@ static int link_initialized_and_synced(Link *link) {
         if (r < 0)
                 return r;
 
-        return 1;
+        return 0;
 }
 
 static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@@ -3735,7 +3747,7 @@ int link_ipv6ll_gained(Link *link, const struct in6_addr *address) {
         link->ipv6ll_address = *address;
         link_check_ready(link);
 
-        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+        if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
                 r = link_acquire_ipv6_conf(link);
                 if (r < 0) {
                         link_enter_failed(link);
@@ -3751,7 +3763,7 @@ static int link_carrier_gained(Link *link) {
 
         assert(link);
 
-        if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
+        if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
                 r = link_acquire_conf(link);
                 if (r < 0) {
                         link_enter_failed(link);
@@ -3843,7 +3855,7 @@ int link_update(Link *link, sd_netlink_message *m) {
         assert(m);
 
         if (link->state == LINK_STATE_LINGER) {
-                log_link_info(link, "Link readded");
+                log_link_info(link, "Link re-added");
                 link_set_state(link, LINK_STATE_CONFIGURING);
 
                 r = link_new_carrier_maps(link);