X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsystemd.git;a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-link.c;h=67c0903fa69b834b4344652a0c5939ee80ce497c;hp=924cc8ce6af25b32f1eea102debb813b4551ee07;hb=4b381a9ef65d68dc79760b093436a9c81f43fa5d;hpb=3f8841f286e2868bf0cba4cfca098573cecdc71a diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 924cc8ce6af..67c0903fa69 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -62,6 +62,20 @@ DUID* link_get_duid(Link *link) { return &link->manager->duid; } +int link_sysctl_ipv6_enabled(Link *link) { + _cleanup_free_ char *value = NULL; + int r; + + r = sysctl_read_ip_property(AF_INET6, link->ifname, "disable_ipv6", &value); + if (r < 0) + return log_link_warning_errno(link, r, + "Failed to read net.ipv6.conf.%s.disable_ipv6 sysctl property: %m", + link->ifname); + + link->sysctl_ipv6_enabled = value[0] == '0'; + return link->sysctl_ipv6_enabled; +} + static bool link_dhcp6_enabled(Link *link) { assert(link); @@ -80,7 +94,7 @@ static bool link_dhcp6_enabled(Link *link) { if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan")) return false; - if (manager_sysctl_ipv6_enabled(link->manager) == 0) + if (link_sysctl_ipv6_enabled(link) == 0) return false; return link->network->dhcp & ADDRESS_FAMILY_IPV6; @@ -132,7 +146,7 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) { if (!link->network) return false; - if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan")) + if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan", "nlmon")) return false; /* L3 or L3S mode do not support ARP. */ @@ -142,6 +156,9 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) { if (link->network->bond) return false; + if (link->network->bond) + return false; + return link->network->link_local & mask; } @@ -157,13 +174,13 @@ static bool link_ipv6ll_enabled(Link *link) { if (!link->network) return false; - if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan")) + if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan", "nlmon")) return false; if (link->network->bond) return false; - if (manager_sysctl_ipv6_enabled(link->manager) == 0) + if (link_sysctl_ipv6_enabled(link) == 0) return false; return link->network->link_local & ADDRESS_FAMILY_IPV6; @@ -178,7 +195,7 @@ static bool link_ipv6_enabled(Link *link) { if (link->network->bond) return false; - if (manager_sysctl_ipv6_enabled(link->manager) == 0) + if (link_sysctl_ipv6_enabled(link) == 0) return false; if (STRPTR_IN_SET(link->kind, "can", "vcan", "vxcan")) @@ -227,7 +244,7 @@ static bool link_ipv6_forward_enabled(Link *link) { if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID) return false; - if (manager_sysctl_ipv6_enabled(link->manager) == 0) + if (link_sysctl_ipv6_enabled(link) == 0) return false; return link->network->ip_forward & ADDRESS_FAMILY_IPV6; @@ -538,6 +555,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { .rtnl_extended_attrs = true, .ifindex = ifindex, .iftype = iftype, + .sysctl_ipv6_enabled = -1, }; link->ifname = strdup(ifname); @@ -677,14 +695,17 @@ static void link_enter_unmanaged(Link *link) { link_dirty(link); } -int link_stop_clients(Link *link) { +int link_stop_clients(Link *link, bool may_keep_dhcp) { int r = 0, k; assert(link); assert(link->manager); assert(link->manager->event); - if (link->dhcp_client) { + dhcp4_release_old_lease(link); + + if (link->dhcp_client && (!may_keep_dhcp || !link->network || + !FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP))) { k = sd_dhcp_client_stop(link->dhcp_client); if (k < 0) r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m"); @@ -728,7 +749,7 @@ void link_enter_failed(Link *link) { link_set_state(link, LINK_STATE_FAILED); - link_stop_clients(link); + link_stop_clients(link, false); link_dirty(link); } @@ -826,14 +847,14 @@ static int link_request_set_routing_policy_rule(Link *link) { continue; } - r = routing_policy_rule_configure(rule, link, NULL, false); + r = routing_policy_rule_configure(rule, link, NULL); if (r < 0) { log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); link_enter_failed(link); return r; } - - link->routing_policy_rule_messages++; + if (r > 0) + link->routing_policy_rule_messages++; } routing_policy_rule_purge(link->manager, link); @@ -907,8 +928,8 @@ int link_request_set_routes(Link *link) { link_enter_failed(link); return r; } - - link->route_messages++; + if (r > 0) + link->route_messages++; } if (link->route_messages == 0) { @@ -954,22 +975,26 @@ void link_check_ready(Link *link) { if (!link->routing_policy_rules_configured) return; - if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !(link->ipv4ll_address && link->ipv4ll_route)) - return; + if (link_has_carrier(link) || !link->network->configure_without_carrier) { - if (link_ipv6ll_enabled(link) && - in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) - return; + if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !(link->ipv4ll_address && link->ipv4ll_route)) + return; - if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && - !(link->dhcp4_configured || link->dhcp6_configured) && - !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && 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_ipv6ll_enabled(link) && + in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) + return; - if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured) - return; + if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && + !link->dhcp4_configured && + !link->dhcp6_configured && + !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && 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) + return; + } if (link->state != LINK_STATE_CONFIGURED) link_enter_configured(link); @@ -1187,8 +1212,8 @@ static int link_request_set_addresses(Link *link) { link_enter_failed(link); return r; } - - link->address_messages++; + if (r > 0) + link->address_messages++; } LIST_FOREACH(labels, label, link->network->address_labels) { @@ -2481,6 +2506,33 @@ static bool link_is_static_route_configured(Link *link, Route *route) { return false; } +static bool link_address_is_dynamic(Link *link, Address *address) { + Route *route; + Iterator i; + + assert(link); + assert(address); + + if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME) + return true; + + /* Even when the address is leased from a DHCP server, networkd assign the address + * without lifetime when KeepConfiguration=dhcp. So, let's check that we have + * corresponding routes with RTPROT_DHCP. */ + SET_FOREACH(route, link->routes_foreign, i) { + if (route->protocol != RTPROT_DHCP) + continue; + + if (address->family != route->family) + continue; + + if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc)) + return true; + } + + return false; +} + static int link_drop_foreign_config(Link *link) { Address *address; Route *route; @@ -2492,6 +2544,12 @@ static int link_drop_foreign_config(Link *link) { if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) continue; + if (link_address_is_dynamic(link, address)) { + if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + } else if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + if (link_is_static_address_configured(link, address)) { r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); if (r < 0) @@ -2508,6 +2566,14 @@ static int link_drop_foreign_config(Link *link) { if (route->protocol == RTPROT_KERNEL) continue; + if (route->protocol == RTPROT_STATIC && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (route->protocol == RTPROT_DHCP && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + if (link_is_static_route_configured(link, route)) { r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL); if (r < 0) @@ -2574,7 +2640,8 @@ static int link_configure(Link *link) { /* Drop foreign config, but ignore loopback or critical devices. * We do not want to remove loopback address or addresses used for root NFS. */ - if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) { + if (!(link->flags & IFF_LOOPBACK) && + link->network->keep_configuration != KEEP_CONFIGURATION_YES) { r = link_drop_foreign_config(link); if (r < 0) return r; @@ -3260,7 +3327,7 @@ static int link_carrier_lost(Link *link) { if (link->setting_mtu) return 0; - r = link_stop_clients(link); + r = link_stop_clients(link, false); if (r < 0) { link_enter_failed(link); return r;