diff --git a/README b/README index 02a3e39052..346f1aad42 100644 --- a/README +++ b/README @@ -39,10 +39,12 @@ REQUIREMENTS: ≥ 4.11 for nsfs NS_GET_NSTYPE ≥ 4.13 for TIOCGPTPEER ≥ 4.15 for cgroup-bpf device hook and cpu controller in cgroup v2 - ≥ 4.17 for cgroup-bpf socket address hooks and /sys/power/resume_offset + ≥ 4.17 for cgroup-bpf socket address hooks, /sys/power/resume_offset, + and FRA_PROTOCOL attribute for fib rules ≥ 4.20 for PSI (used by systemd-oomd) ≥ 5.2 for cgroup freezer and new mount API - ≥ 5.3 for bounded loops in BPF program and keyring namespacing + ≥ 5.3 for bounded loops in BPF program, keyring namespacing, + and nexthop support ≥ 5.4 for pidfd and signed Verity images ⛔ Kernel versions below 5.4 ("minimum baseline") are not supported at all, diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index d0f0282075..d35d2ed521 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -1148,7 +1148,6 @@ static void address_forget(Link *link, Address *address, bool removed_by_us, con } static int address_set_netlink_message(const Address *address, sd_netlink_message *m, Link *link) { - uint32_t flags; int r; assert(address); @@ -1163,12 +1162,8 @@ static int address_set_netlink_message(const Address *address, sd_netlink_messag * flags except tentative flag here unconditionally. Without setting the flag, the template * addresses generated by kernel will not be removed automatically when the main address is * removed. */ - flags = address->flags & ~IFA_F_TENTATIVE; - r = sd_rtnl_message_addr_set_flags(m, flags & 0xff); - if (r < 0) - return r; - - if ((flags & ~0xff) != 0) { + uint32_t flags = address->flags & ~IFA_F_TENTATIVE; + if (flags != 0) { r = sd_netlink_message_append_u32(m, IFA_FLAGS, flags); if (r < 0) return r; @@ -1339,12 +1334,12 @@ int link_drop_ipv6ll_addresses(Link *link) { for (sd_netlink_message *addr = reply; addr; addr = sd_netlink_message_next(addr)) { _cleanup_(address_unrefp) Address *a = NULL; - unsigned char flags, prefixlen; + unsigned char prefixlen; struct in6_addr address; int ifindex; - /* NETLINK_GET_STRICT_CHK socket option is supported since kernel 4.20. To support - * older kernels, we need to check ifindex here. */ + /* We set ifindex in the request, and NETLINK_GET_STRICT_CHK socket option is set. Hence the + * check below is redundant, but let's do that for safety. */ r = sd_rtnl_message_addr_get_ifindex(addr, &ifindex); if (r < 0) { log_link_debug_errno(link, r, "rtnl: received address message without valid ifindex, ignoring: %m"); @@ -1352,9 +1347,10 @@ int link_drop_ipv6ll_addresses(Link *link) { } else if (link->ifindex != ifindex) continue; - r = sd_rtnl_message_addr_get_flags(addr, &flags); + uint32_t flags; + r = sd_netlink_message_read_u32(addr, IFA_FLAGS, &flags); if (r < 0) { - log_link_debug_errno(link, r, "rtnl: received address message without valid flags, ignoring: %m"); + log_link_debug_errno(link, r, "rtnl: Failed to read IFA_FLAGS attribute, ignoring: %m"); continue; } @@ -1971,14 +1967,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, } r = sd_netlink_message_read_u32(message, IFA_FLAGS, &address->flags); - if (r == -ENODATA) { - unsigned char flags; - - /* For old kernels. */ - r = sd_rtnl_message_addr_get_flags(message, &flags); - if (r >= 0) - address->flags = flags; - } else if (r < 0) + if (r < 0) log_link_debug_errno(link, r, "rtnl: failed to read IFA_FLAGS attribute, ignoring: %m"); struct ifa_cacheinfo cinfo; diff --git a/src/network/networkd-bridge-mdb.c b/src/network/networkd-bridge-mdb.c index 358ca4d294..80ef3c1458 100644 --- a/src/network/networkd-bridge-mdb.c +++ b/src/network/networkd-bridge-mdb.c @@ -90,13 +90,7 @@ static int bridge_mdb_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, assert(link); r = sd_netlink_message_get_errno(m); - if (r == -EINVAL && streq_ptr(link->kind, "bridge") && link->master_ifindex <= 0) { - /* To configure bridge MDB entries on bridge master, 1bc844ee0faa1b92e3ede00bdd948021c78d7088 (v5.4) is required. */ - if (!link->manager->bridge_mdb_on_master_not_supported) { - log_link_warning_errno(link, r, "Kernel seems not to support bridge MDB entries on bridge master, ignoring: %m"); - link->manager->bridge_mdb_on_master_not_supported = true; - } - } else if (r < 0 && r != -EEXIST) { + if (r < 0 && r != -EEXIST) { log_link_message_warning_errno(link, m, r, "Could not add MDB entry"); link_enter_failed(link); return 1; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 67fc725f98..14cf7197bb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2321,7 +2321,7 @@ static int link_update_permanent_hardware_address(Link *link, sd_netlink_message if (r != -ENODATA) return log_link_debug_errno(link, r, "Failed to read IFLA_PERM_ADDRESS attribute: %m"); - /* Fallback to ethtool for older kernels. */ + /* Fallback to ethtool for kernels older than v5.6 (f74877a5457d34d604dba6dbbb13c4c05bac8b93). */ r = link_update_permanent_hardware_address_from_ethtool(link, message); if (r < 0) return r; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 1592e258ec..c2625d548b 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -277,6 +277,7 @@ static int manager_connect_genl(Manager *m) { if (r < 0) return r; + /* If the kernel is built without CONFIG_WIRELESS, the belows will fail with -EOPNOTSUPP. */ r = genl_add_match(m->genl, NULL, NL80211_GENL_NAME, NL80211_MULTICAST_GROUP_CONFIG, 0, &manager_genl_process_nl80211_config, NULL, m, "network-genl_process_nl80211_config"); if (r < 0 && r != -EOPNOTSUPP) @@ -1049,12 +1050,14 @@ int manager_enumerate(Manager *m) { if (r < 0) return log_error_errno(r, "Could not enumerate links: %m"); + /* If the kernel is built without CONFIG_NET_SCHED, the below will fail with -EOPNOTSUPP. */ r = manager_enumerate_qdisc(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate QDiscs, ignoring: %m"); else if (r < 0) return log_error_errno(r, "Could not enumerate QDisc: %m"); + /* If the kernel is built without CONFIG_NET_CLS, the below will fail with -EOPNOTSUPP. */ r = manager_enumerate_tclass(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate TClasses, ignoring: %m"); @@ -1069,25 +1072,22 @@ int manager_enumerate(Manager *m) { if (r < 0) return log_error_errno(r, "Could not enumerate neighbors: %m"); - /* NextHop support is added in kernel v5.3 (65ee00a9409f751188a8cdc0988167858eb4a536), - * and older kernels return -EOPNOTSUPP, or -EINVAL if SELinux is enabled. */ r = manager_enumerate_nexthop(m); - if (r == -EOPNOTSUPP || (r == -EINVAL && mac_selinux_enforcing())) - log_debug_errno(r, "Could not enumerate nexthops, ignoring: %m"); - else if (r < 0) + if (r < 0) return log_error_errno(r, "Could not enumerate nexthops: %m"); r = manager_enumerate_routes(m); if (r < 0) return log_error_errno(r, "Could not enumerate routes: %m"); - /* If kernel is built with CONFIG_FIB_RULES=n, it returns -EOPNOTSUPP. */ + /* If the kernel is built without CONFIG_FIB_RULES, the below will fail with -EOPNOTSUPP. */ r = manager_enumerate_rules(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate routing policy rules, ignoring: %m"); else if (r < 0) return log_error_errno(r, "Could not enumerate routing policy rules: %m"); + /* If the kernel is built without CONFIG_WIRELESS, the belows will fail with -EOPNOTSUPP. */ r = manager_enumerate_nl80211_wiphy(m); if (r == -EOPNOTSUPP) log_debug_errno(r, "Could not enumerate wireless LAN phy, ignoring: %m"); diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index 9891b8c1fc..59e07748c6 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -118,8 +118,6 @@ struct Manager { usec_t speed_meter_usec_new; usec_t speed_meter_usec_old; - bool bridge_mdb_on_master_not_supported; - FirewallContext *fw_ctx; bool request_queued; diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 7eb7548412..6c723325cb 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1050,26 +1050,6 @@ int link_request_static_routing_policy_rules(Link *link) { return 0; } -static const RoutingPolicyRule kernel_rules[] = { - { .family = AF_INET, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET, .priority_set = true, .priority = 1000, .table = RT_TABLE_UNSPEC, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, .l3mdev = true }, - { .family = AF_INET, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET, .priority_set = true, .priority = 32767, .table = RT_TABLE_DEFAULT, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET6, .priority_set = true, .priority = 0, .table = RT_TABLE_LOCAL, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, - { .family = AF_INET6, .priority_set = true, .priority = 1000, .table = RT_TABLE_UNSPEC, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, .l3mdev = true }, - { .family = AF_INET6, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN, .action = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, .suppress_ifgroup = -1, }, -}; - -static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) { - assert(rule); - - FOREACH_ELEMENT(i, kernel_rules) - if (routing_policy_rule_equal(rule, i, i->family, i->priority)) - return true; - - return false; -} - int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int r; @@ -1249,16 +1229,10 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man return 0; } - /* If FRA_PROTOCOL is supported by kernel, then the attribute is always appended. If the received - * message does not have FRA_PROTOCOL, then we need to adjust the protocol of the rule. That requires - * all properties compared in the routing_policy_rule_compare_func(), hence it must be done after - * reading them. */ + /* The kernel always sets the FRA_PROTOCOL attribute, and it is necessary for comparing rules. + * Hence, -ENODATA here is critical. */ r = sd_netlink_message_read_u8(message, FRA_PROTOCOL, &tmp->protocol); - if (r == -ENODATA) - /* As .network files does not have setting to specify protocol, we can assume the - * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */ - tmp->protocol = routing_policy_rule_is_created_by_kernel(tmp) ? RTPROT_KERNEL : RTPROT_STATIC; - else if (r < 0) { + if (r < 0) { log_warning_errno(r, "rtnl: could not get FRA_PROTOCOL attribute, ignoring: %m"); return 0; } diff --git a/src/network/networkd.c b/src/network/networkd.c index 883f16d81b..2e1b242da2 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -70,9 +70,8 @@ static int run(int argc, char *argv[]) { return log_error_errno(r, "Failed to drop privileges: %m"); } - /* Always create the directories people can create inotify watches in. - * It is necessary to create the following subdirectories after drop_privileges() - * to support old kernels not supporting AmbientCapabilities=. */ + /* Always create the directories people can create inotify watches in. It is necessary to create the + * following subdirectories after drop_privileges() to make them owned by systemd-network. */ FOREACH_STRING(p, "/run/systemd/netif/links/", "/run/systemd/netif/leases/") {