diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index a60cd746a4..ccb4a426fa 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -802,7 +802,7 @@ int link_drop_ipv6ll_addresses(Link *link) { /* IPv6LL address may be in the tentative state, and in that case networkd has not received it. * So, we need to dump all IPv6 addresses. */ - if (link_may_have_ipv6ll(link)) + if (link_may_have_ipv6ll(link, /* check_multicast = */ false)) return 0; r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_GETADDR, link->ifindex, AF_INET6); diff --git a/src/network/networkd-ipv4acd.c b/src/network/networkd-ipv4acd.c index 009cde27de..4f2563ff9c 100644 --- a/src/network/networkd-ipv4acd.c +++ b/src/network/networkd-ipv4acd.c @@ -1,14 +1,44 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include + #include "sd-dhcp-client.h" #include "sd-ipv4acd.h" +#include "ipvlan.h" #include "networkd-address.h" #include "networkd-dhcp4.h" #include "networkd-ipv4acd.h" #include "networkd-link.h" #include "networkd-manager.h" +bool link_ipv4acd_supported(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + /* ARPHRD_INFINIBAND seems to potentially support IPv4ACD. + * But currently sd-ipv4acd only supports ARPHRD_ETHER. */ + if (link->iftype != ARPHRD_ETHER) + return false; + + if (link->hw_addr.length != ETH_ALEN) + return false; + + if (ether_addr_is_null(&link->hw_addr.ether)) + return false; + + if (streq_ptr(link->kind, "vrf")) + return false; + + /* L3 or L3S mode do not support ARP. */ + if (IN_SET(link_get_ipvlan_mode(link), NETDEV_IPVLAN_MODE_L3, NETDEV_IPVLAN_MODE_L3S)) + return false; + + return true; +} + static int static_ipv4acd_address_remove(Link *link, Address *address, bool on_conflict) { int r; @@ -141,7 +171,7 @@ int ipv4acd_configure(Address *address) { if (!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) return 0; - if (link->hw_addr.length != ETH_ALEN || hw_addr_is_null(&link->hw_addr)) + if (!link_ipv4acd_supported(link)) return 0; /* Currently, only static and DHCP4 addresses are supported. */ diff --git a/src/network/networkd-ipv4acd.h b/src/network/networkd-ipv4acd.h index 6ebfa36289..7bd6a26b40 100644 --- a/src/network/networkd-ipv4acd.h +++ b/src/network/networkd-ipv4acd.h @@ -4,6 +4,7 @@ typedef struct Address Address; typedef struct Link Link; +bool link_ipv4acd_supported(Link *link); int ipv4acd_configure(Address *address); int ipv4acd_update_mac(Link *link); int ipv4acd_start(Link *link); diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index ac5bb217c3..8b0849d2d2 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -5,12 +5,28 @@ #include "netif-util.h" #include "networkd-address.h" +#include "networkd-ipv4acd.h" #include "networkd-ipv4ll.h" #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-queue.h" #include "parse-util.h" +bool link_ipv4ll_enabled(Link *link) { + assert(link); + + if (!link_ipv4acd_supported(link)) + return false; + + if (!link->network) + return false; + + if (link->network->bond) + return false; + + return link->network->link_local & ADDRESS_FAMILY_IPV4; +} + static int address_new_from_ipv4ll(Link *link, Address **ret) { _cleanup_(address_freep) Address *address = NULL; struct in_addr addr; diff --git a/src/network/networkd-ipv4ll.h b/src/network/networkd-ipv4ll.h index f5c6928535..fa53bd2b39 100644 --- a/src/network/networkd-ipv4ll.h +++ b/src/network/networkd-ipv4ll.h @@ -7,6 +7,8 @@ typedef struct Link Link; +bool link_ipv4ll_enabled(Link *link); + int ipv4ll_configure(Link *link); int ipv4ll_update_mac(Link *link); diff --git a/src/network/networkd-ipv6ll.c b/src/network/networkd-ipv6ll.c index 9b85989701..32229a3fc7 100644 --- a/src/network/networkd-ipv6ll.c +++ b/src/network/networkd-ipv6ll.c @@ -38,7 +38,7 @@ bool link_ipv6ll_enabled(Link *link) { return link->network->link_local & ADDRESS_FAMILY_IPV6; } -bool link_may_have_ipv6ll(Link *link) { +bool link_may_have_ipv6ll(Link *link, bool check_multicast) { assert(link); /* @@ -62,6 +62,9 @@ bool link_may_have_ipv6ll(Link *link) { if (!link->network) return false; + if (check_multicast && !FLAGS_SET(link->flags, IFF_MULTICAST) && link->network->multicast <= 0) + return false; + ORDERED_HASHMAP_FOREACH(a, link->network->addresses_by_section) { if (a->family != AF_INET6) continue; diff --git a/src/network/networkd-ipv6ll.h b/src/network/networkd-ipv6ll.h index a9763debb1..2759eed7f7 100644 --- a/src/network/networkd-ipv6ll.h +++ b/src/network/networkd-ipv6ll.h @@ -22,7 +22,7 @@ typedef enum IPv6LinkLocalAddressGenMode { } IPv6LinkLocalAddressGenMode; bool link_ipv6ll_enabled(Link *link); -bool link_may_have_ipv6ll(Link *link); +bool link_may_have_ipv6ll(Link *link, bool check_multicast); IPv6LinkLocalAddressGenMode link_get_ipv6ll_addrgen_mode(Link *link); int ipv6ll_addrgen_mode_fill_message(sd_netlink_message *message, IPv6LinkLocalAddressGenMode mode); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 35d1e2f206..76e0690aef 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -27,7 +27,6 @@ #include "format-util.h" #include "fs-util.h" #include "glyph-util.h" -#include "ipvlan.h" #include "missing_network.h" #include "netlink-util.h" #include "network-internal.h" @@ -69,56 +68,22 @@ #include "util.h" #include "vrf.h" -bool link_ipv4ll_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->iftype == ARPHRD_CAN) - return false; - - if (link->hw_addr.length != ETH_ALEN) - return false; - - if (ether_addr_is_null(&link->hw_addr.ether)) - return false; - - /* ARPHRD_INFINIBAND seems to potentially support IPv4LL. - * But currently sd-ipv4ll and sd-ipv4acd only support ARPHRD_ETHER. */ - if (link->iftype != ARPHRD_ETHER) - return false; - - if (streq_ptr(link->kind, "vrf")) - return false; - - /* L3 or L3S mode do not support ARP. */ - if (IN_SET(link_get_ipvlan_mode(link), NETDEV_IPVLAN_MODE_L3, NETDEV_IPVLAN_MODE_L3S)) - return false; - - if (link->network->bond) - return false; - - return link->network->link_local & ADDRESS_FAMILY_IPV4; -} - bool link_ipv6_enabled(Link *link) { assert(link); if (!socket_ipv6_is_supported()) return false; - if (link->network->bond) - return false; - if (link->iftype == ARPHRD_CAN) return false; - /* DHCPv6 client will not be started if no IPv6 link-local address is configured. */ - if (link_ipv6ll_enabled(link)) + if (!link->network) + return false; + + if (link->network->bond) + return false; + + if (link_may_have_ipv6ll(link, /* check_multicast = */ false)) return true; if (network_has_static_ipv6_configurations(link->network)) diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index dfe43bb3a0..807fb44709 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -225,8 +225,6 @@ static inline bool link_has_carrier(Link *link) { bool link_ipv6_enabled(Link *link); int link_ipv6ll_gained(Link *link); -bool link_ipv4ll_enabled(Link *link); - int link_stop_engines(Link *link, bool may_keep_dhcp); const char* link_state_to_string(LinkState s) _const_; diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 943e12ba56..dfbb7043bf 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -41,7 +41,7 @@ bool link_ipv6_accept_ra_enabled(Link *link) { if (!link->network) return false; - if (!link_may_have_ipv6ll(link)) + if (!link_may_have_ipv6ll(link, /* check_multicast = */ true)) return false; assert(link->network->ipv6_accept_ra >= 0); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c index 32ee7aa7ab..c59ae82694 100644 --- a/src/network/networkd-radv.c +++ b/src/network/networkd-radv.c @@ -54,7 +54,7 @@ void network_adjust_radv(Network *network) { bool link_radv_enabled(Link *link) { assert(link); - if (!link_may_have_ipv6ll(link)) + if (!link_may_have_ipv6ll(link, /* check_multicast = */ true)) return false; if (link->hw_addr.length != ETH_ALEN) diff --git a/test/test-network/conf/25-wireguard.network b/test/test-network/conf/25-wireguard.network index d3b0ea4e6c..bd3c735f4c 100644 --- a/test/test-network/conf/25-wireguard.network +++ b/test/test-network/conf/25-wireguard.network @@ -4,4 +4,6 @@ Name=wg99 [Network] Address=192.168.124.1/24 +Address=fe80::1/64 +Address=169.254.11.1/24 IPv6AcceptRA=no diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 1c043a692e..71f284fd18 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1416,6 +1416,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): print(output) self.assertIn('inet 192.168.124.1/24 scope global wg99', output) + output = check_output('ip -4 address show dev wg99') + print(output) + self.assertIn('inet 169.254.11.1/24 scope link wg99', output) + + output = check_output('ip -6 address show dev wg99') + print(output) + self.assertIn('inet6 fe80::1/64 scope link', output) + output = check_output('ip -4 address show dev wg98') print(output) self.assertIn('inet 192.168.123.123/24 scope global wg98', output)