summaryrefslogtreecommitdiff
path: root/src/network/networkd-link.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-link.c')
-rw-r--r--src/network/networkd-link.c223
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);
}
}