diff options
Diffstat (limited to 'src/network/networkd-link.c')
-rw-r--r-- | src/network/networkd-link.c | 223 |
1 files changed, 138 insertions, 85 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6b591271a0..60ac980ad9 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -20,6 +21,7 @@ #include <netinet/ether.h> #include <linux/if.h> #include <unistd.h> +#include <stdio_ext.h> #include "alloc-util.h" #include "bus-util.h" @@ -226,6 +228,9 @@ static bool link_ipv6_accept_ra_enabled(Link *link) { if (!link->network) return false; + if (!link_ipv6ll_enabled(link)) + return false; + /* If unset use system default (enabled if local forwarding is disabled. * disabled if local forwarding is enabled). * If set, ignore or enforce RA independent of local forwarding state. @@ -735,7 +740,10 @@ void link_check_ready(Link *link) { if (!link->network) return; - if (!link->static_configured) + if (!link->static_routes_configured) + return; + + if (!link->routing_policy_rules_configured) return; if (link_ipv4ll_enabled(link)) @@ -743,20 +751,23 @@ void link_check_ready(Link *link) { !link->ipv4ll_route) return; - if (link_ipv6ll_enabled(link)) - if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0) - return; + if (!link->network->bridge) { - 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)) - return; + if (link_ipv6ll_enabled(link)) + if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0) + 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_enabled(link) && !link_dhcp4_enabled(link) && + !link->dhcp6_configured) || + (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) && + !link->dhcp4_configured && !link->dhcp6_configured)) + return; + + if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured) + return; + } SET_FOREACH(a, link->addresses, i) if (!address_is_ready(a)) @@ -768,16 +779,51 @@ void link_check_ready(Link *link) { return; } +static int link_set_routing_policy_rule(Link *link) { + RoutingPolicyRule *rule, *rrule = NULL; + int r; + + assert(link); + assert(link->network); + + LIST_FOREACH(rules, rule, link->network->rules) { + r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to, + rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, rule->iif, rule->oif, &rrule); + if (r == 1) { + (void) routing_policy_rule_make_local(link->manager, rrule); + continue; + } + + r = routing_policy_rule_configure(rule, link, link_routing_policy_rule_handler, false); + 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++; + } + + routing_policy_rule_purge(link->manager, link); + if (link->routing_policy_rule_messages == 0) { + link->routing_policy_rules_configured = true; + link_check_ready(link); + } else + log_link_debug(link, "Setting routing policy rules"); + + return 0; +} + static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; - assert(link->link_messages > 0); + assert(link->route_messages > 0); assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED, LINK_STATE_LINGER)); - link->link_messages--; + link->route_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; @@ -786,9 +832,9 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata if (r < 0 && r != -EEXIST) log_link_warning_errno(link, r, "Could not set route: %m"); - if (link->link_messages == 0) { + if (link->route_messages == 0) { log_link_debug(link, "Routes set"); - link->static_configured = true; + link->static_routes_configured = true; link_check_ready(link); } @@ -813,11 +859,13 @@ static int link_enter_set_routes(Link *link) { return r; } - link->link_messages++; + link->route_messages++; } - if (link->link_messages == 0) { - link->static_configured = true; + (void) link_set_routing_policy_rule(link); + + if (link->route_messages == 0) { + link->static_routes_configured = true; link_check_ready(link); } else log_link_debug(link, "Setting routes"); @@ -851,11 +899,11 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda assert(m); assert(link); assert(link->ifname); - assert(link->link_messages > 0); + assert(link->address_messages > 0); assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, LINK_STATE_FAILED, LINK_STATE_LINGER)); - link->link_messages--; + link->address_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; @@ -866,7 +914,7 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda else if (r >= 0) manager_rtnl_process_address(rtnl, m, link->manager); - if (link->link_messages == 0) { + if (link->address_messages == 0) { log_link_debug(link, "Addresses set"); link_enter_set_routes(link); } @@ -882,9 +930,9 @@ static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void * assert(m); assert(link); assert(link->ifname); - assert(link->link_messages > 0); + assert(link->address_label_messages > 0); - link->link_messages--; + link->address_label_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1; @@ -895,10 +943,8 @@ static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, void * else if (r >= 0) manager_rtnl_process_address(rtnl, m, link->manager); - if (link->link_messages == 0) { + if (link->address_label_messages == 0) log_link_debug(link, "Addresses label set"); - link_enter_set_routes(link); - } return 1; } @@ -1015,7 +1061,6 @@ static int link_set_bridge_fdb(Link *link) { } static int link_enter_set_addresses(Link *link) { - RoutingPolicyRule *rule, *rrule = NULL; AddressLabel *label; Address *ad; int r; @@ -1038,7 +1083,7 @@ static int link_enter_set_addresses(Link *link) { return r; } - link->link_messages++; + link->address_messages++; } LIST_FOREACH(labels, label, link->network->address_labels) { @@ -1049,29 +1094,9 @@ static int link_enter_set_addresses(Link *link) { return r; } - link->link_messages++; - } - - LIST_FOREACH(rules, rule, link->network->rules) { - r = routing_policy_rule_get(link->manager, rule->family, &rule->from, rule->from_prefixlen, &rule->to, - rule->to_prefixlen, rule->tos, rule->fwmark, rule->table, &rrule); - if (r == 1) { - (void) routing_policy_rule_make_local(link->manager, rrule); - continue; - } - - r = routing_policy_rule_configure(rule, link, link_routing_policy_rule_handler, false); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); - link_enter_failed(link); - return r; - } - - link->link_messages++; + link->address_label_messages++; } - routing_policy_rule_purge(link->manager, link); - /* now that we can figure out a default address for the dhcp server, start it */ if (link_dhcp4_server_enabled(link)) { @@ -1192,7 +1217,7 @@ static int link_enter_set_addresses(Link *link) { log_link_debug(link, "Offering DHCPv4 leases"); } - if (link->link_messages == 0) + if (link->address_messages == 0) link_enter_set_routes(link); else log_link_debug(link, "Setting addresses"); @@ -1300,6 +1325,8 @@ int link_set_mtu(Link *link, uint32_t mtu) { if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + link->setting_mtu = true; + link_ref(link); return 0; @@ -1646,6 +1673,11 @@ static int link_acquire_conf(Link *link) { assert(link); + if (link->setting_mtu) { + link->setting_mtu = false; + return 0; + } + r = link_acquire_ipv4_conf(link); if (r < 0) return r; @@ -2276,6 +2308,11 @@ static int link_enter_join_netdev(Link *link) { HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { + if (netdev->ifindex > 0) { + link_joined(link); + continue; + } + log_struct(LOG_DEBUG, LOG_LINK_INTERFACE(link), LOG_NETDEV_INTERFACE(netdev), @@ -2602,6 +2639,10 @@ static int link_configure(Link *link) { } if (link_dhcp4_enabled(link)) { + r = dhcp4_set_promote_secondaries(link); + if (r < 0) + return r; + r = dhcp4_configure(link); if (r < 0) return r; @@ -2770,7 +2811,7 @@ int link_initialized(Link *link, struct udev_device *device) { return r; r = sd_netlink_call_async(link->manager->rtnl, req, - link_initialized_and_synced, link, 0, NULL); + link_initialized_and_synced, link, 0, NULL); if (r < 0) return r; @@ -3076,13 +3117,20 @@ static int link_carrier_lost(Link *link) { assert(link); + /* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop. + setting_mtu keep track whether the device got reset because of setting MTU and does not drop the + configuration and stop the clients as well. */ + if (link->setting_mtu) + return 0; + r = link_stop_clients(link); if (r < 0) { link_enter_failed(link); return r; } - (void) sd_dhcp_server_stop(link->dhcp_server); + if (link_dhcp4_server_enabled(link)) + (void) sd_dhcp_server_stop(link->dhcp_server); r = link_drop_config(link); if (r < 0) @@ -3145,7 +3193,7 @@ int link_update(Link *link, sd_netlink_message *m) { r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); if (r >= 0 && !streq(ifname, link->ifname)) { - log_link_info(link, "Renamed to %s", ifname); + log_link_info(link, "Interface name change detected, %s has been renamed to %s.", link->ifname, ifname); link_free_carrier_maps(link); @@ -3233,7 +3281,7 @@ int link_update(Link *link, sd_netlink_message *m) { ARPHRD_ETHER, (const uint8_t *)&link->mac, sizeof(link->mac)); - if(r < 0) + if (r < 0) return log_link_warning_errno(link, r, "Could not update MAC client id in DHCP client: %m"); break; default: @@ -3313,16 +3361,16 @@ static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) { if (hashmap_isempty(h)) return; - fputs_unlocked(prefix, f); + fputs(prefix, f); HASHMAP_FOREACH(link, h, i) { if (space) - fputc_unlocked(' ', f); + fputc(' ', f); fprintf(f, "%i", link->ifindex); space = true; } - fputc_unlocked('\n', f); + fputc('\n', f); } int link_save(Link *link) { @@ -3356,6 +3404,7 @@ int link_save(Link *link) { if (r < 0) goto fail; + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); (void) fchmod(fileno(f), 0644); fprintf(f, @@ -3372,6 +3421,9 @@ int link_save(Link *link) { char **dhcp_domains = NULL; unsigned j; + fprintf(f, "REQUIRED_FOR_ONLINE=%s\n", + yes_no(link->network->required_for_online)); + if (link->dhcp6_client) { r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); if (r < 0 && r != -ENOMSG) @@ -3380,7 +3432,7 @@ int link_save(Link *link) { fprintf(f, "NETWORK_FILE=%s\n", link->network->filename); - fputs_unlocked("DNS=", f); + fputs("DNS=", f); space = false; for (j = 0; j < link->network->n_dns; j++) { @@ -3394,8 +3446,8 @@ int link_save(Link *link) { } if (space) - fputc_unlocked(' ', f); - fputs_unlocked(b, f); + fputc(' ', f); + fputs(b, f); space = true; } @@ -3406,7 +3458,7 @@ int link_save(Link *link) { r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); if (r > 0) { if (space) - fputc_unlocked(' ', f); + fputc(' ', f); serialize_in_addrs(f, addresses, r); space = true; } @@ -3418,7 +3470,7 @@ int link_save(Link *link) { r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs); if (r > 0) { if (space) - fputc_unlocked(' ', f); + fputc(' ', f); serialize_in6_addrs(f, in6_addrs, r); space = true; } @@ -3432,16 +3484,16 @@ int link_save(Link *link) { SET_FOREACH(dd, link->ndisc_rdnss, i) { if (space) - fputc_unlocked(' ', f); + fputc(' ', f); serialize_in6_addrs(f, &dd->address, 1); space = true; } } - fputc_unlocked('\n', f); + fputc('\n', f); - fputs_unlocked("NTP=", f); + fputs("NTP=", f); space = false; fputstrv(f, link->network->ntp, NULL, &space); @@ -3452,7 +3504,7 @@ int link_save(Link *link) { r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); if (r > 0) { if (space) - fputc_unlocked(' ', f); + fputc(' ', f); serialize_in_addrs(f, addresses, r); space = true; } @@ -3466,7 +3518,7 @@ int link_save(Link *link) { &in6_addrs); if (r > 0) { if (space) - fputc_unlocked(' ', f); + fputc(' ', f); serialize_in6_addrs(f, in6_addrs, r); space = true; } @@ -3476,7 +3528,7 @@ int link_save(Link *link) { fputstrv(f, hosts, NULL, &space); } - fputc_unlocked('\n', f); + fputc('\n', f); if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { if (link->dhcp_lease) { @@ -3487,7 +3539,7 @@ int link_save(Link *link) { (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains); } - fputs_unlocked("DOMAINS=", f); + fputs("DOMAINS=", f); space = false; fputstrv(f, link->network->search_domains, NULL, &space); @@ -3505,9 +3557,9 @@ int link_save(Link *link) { fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); } - fputc_unlocked('\n', f); + fputc('\n', f); - fputs_unlocked("ROUTE_DOMAINS=", f); + fputs("ROUTE_DOMAINS=", f); space = false; fputstrv(f, link->network->route_domains, NULL, &space); @@ -3525,7 +3577,7 @@ int link_save(Link *link) { fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); } - fputc_unlocked('\n', f); + fputc('\n', f); fprintf(f, "LLMNR=%s\n", resolve_support_to_string(link->network->llmnr)); @@ -3539,14 +3591,14 @@ int link_save(Link *link) { if (!set_isempty(link->network->dnssec_negative_trust_anchors)) { const char *n; - fputs_unlocked("DNSSEC_NTA=", f); + fputs("DNSSEC_NTA=", f); space = false; SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) fputs_with_space(f, n, NULL, &space); - fputc_unlocked('\n', f); + fputc('\n', f); } - fputs_unlocked("ADDRESSES=", f); + fputs("ADDRESSES=", f); space = false; SET_FOREACH(a, link->addresses, i) { _cleanup_free_ char *address_str = NULL; @@ -3558,9 +3610,9 @@ int link_save(Link *link) { fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen); space = true; } - fputc_unlocked('\n', f); + fputc('\n', f); - fputs_unlocked("ROUTES=", f); + fputs("ROUTES=", f); space = false; SET_FOREACH(route, link->routes, i) { _cleanup_free_ char *route_str = NULL; @@ -3569,12 +3621,13 @@ int link_save(Link *link) { if (r < 0) goto fail; - fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu/"USEC_FMT, space ? " " : "", route_str, + fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%"PRIu32"/"USEC_FMT, + space ? " " : "", route_str, route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime); space = true; } - fputc_unlocked('\n', f); + fputc('\n', f); } print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links); @@ -3592,9 +3645,9 @@ int link_save(Link *link) { r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); if (r >= 0) { - fputs_unlocked("DHCP4_ADDRESS=", f); + fputs("DHCP4_ADDRESS=", f); serialize_in_addrs(f, &address, 1); - fputc_unlocked('\n', f); + fputc('\n', f); } r = dhcp_lease_save(link->dhcp_lease, link->lease_file); @@ -3612,9 +3665,9 @@ int link_save(Link *link) { r = sd_ipv4ll_get_address(link->ipv4ll, &address); if (r >= 0) { - fputs_unlocked("IPV4LL_ADDRESS=", f); + fputs("IPV4LL_ADDRESS=", f); serialize_in_addrs(f, &address, 1); - fputc_unlocked('\n', f); + fputc('\n', f); } } |