From 832583ada8b9df0de3b486207dd4c703e0f181bc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 19 Feb 2021 06:01:34 +0900 Subject: [PATCH 1/2] network: make Broadcast= accept boolean value And disable it for wireguard interfaces by default. Closes #18492. --- man/systemd.network.xml | 10 ++++---- src/network/networkd-address.c | 44 ++++++++++++++++++++++++++++++++-- src/network/networkd-address.h | 1 + 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index dfc1dd37ff..015fcf01f9 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1044,12 +1044,12 @@ IPv6Token=prefixstable:2002:da8:1:: Broadcast= - The broadcast address, which must be in the format - described in + Takes an IPv4 address or boolean value. The address must be in the format described in inet_pton3. - This key only applies to IPv4 addresses. If it is not - given, it is derived from the Address= - key. + If set to true, then the IPv4 broadcast address will be derived from the + Address= setting. If set to false, then the broadcast address will not + be set. Defaults to true, except for wireguard interfaces, where it default to false. + diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 566709b371..58b089901b 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -57,6 +57,7 @@ int address_new(Address **ret) { .scope = RT_SCOPE_UNIVERSE, .cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME, .cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME, + .set_broadcast = -1, .duplicate_address_detection = ADDRESS_FAMILY_IPV6, }; @@ -153,6 +154,20 @@ static bool address_may_have_broadcast(const Address *a) { a->prefixlen <= 30; } +static bool address_may_set_broadcast(const Address *a, const Link *link) { + assert(a); + assert(link); + + if (!address_may_have_broadcast(a)) + return false; + + if (a->set_broadcast >= 0) + return a->set_broadcast; + + /* Typical configuration for wireguard does not set broadcast. */ + return !streq_ptr(link->kind, "wireguard"); +} + static uint32_t address_prefix(const Address *a) { assert(a); @@ -887,7 +902,7 @@ int address_configure( r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer); if (r < 0) return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); - } else if (address_may_have_broadcast(address)) { + } else if (address_may_set_broadcast(address, link)) { r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); if (r < 0) return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m"); @@ -1467,6 +1482,25 @@ int config_parse_broadcast( return 0; } + if (isempty(rvalue)) { + /* The broadcast address will be calculated based on Address=, and set if the link is + * not a wireguard interface. Here, we do not check or set n->family. */ + n->broadcast = (struct in_addr) {}; + n->set_broadcast = -1; + TAKE_PTR(n); + return 0; + } + + r = parse_boolean(rvalue); + if (r >= 0) { + /* The broadcast address will be calculated based on Address=. Here, we do not check or + * set n->family. */ + n->broadcast = (struct in_addr) {}; + n->set_broadcast = r; + TAKE_PTR(n); + return 0; + } + if (n->family == AF_INET6) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue); @@ -1479,8 +1513,14 @@ int config_parse_broadcast( "Broadcast is invalid, ignoring assignment: %s", rvalue); return 0; } + if (in4_addr_is_null(&u.in)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Broadcast cannot be ANY address, ignoring assignment: %s", rvalue); + return 0; + } n->broadcast = u.in; + n->set_broadcast = true; n->family = AF_INET; TAKE_PTR(n); @@ -1835,7 +1875,7 @@ static int address_section_verify(Address *address) { } if (address_may_have_broadcast(address)) { - if (address->broadcast.s_addr == 0) + if (address->broadcast.s_addr == 0 && address->set_broadcast != 0) address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen); } else if (address->broadcast.s_addr != 0) { log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. " diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 7c2d0db3d0..e3ca868c2e 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -30,6 +30,7 @@ typedef struct Address { uint32_t flags; char *label; + int set_broadcast; struct in_addr broadcast; struct ifa_cacheinfo cinfo; From 045db4fa0dba022e0db7102549a9098776992ae8 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 19 Feb 2021 06:06:51 +0900 Subject: [PATCH 2/2] test-network: add tests for Broadcast= with boolean settings --- test/test-network/conf/25-address-static.network | 4 ++++ test/test-network/conf/25-wireguard-23-peers.network | 1 + test/test-network/systemd-networkd-tests.py | 9 +++++++++ 3 files changed, 14 insertions(+) diff --git a/test/test-network/conf/25-address-static.network b/test/test-network/conf/25-address-static.network index da57bf7351..3227fe8dfd 100644 --- a/test/test-network/conf/25-address-static.network +++ b/test/test-network/conf/25-address-static.network @@ -61,6 +61,10 @@ Scope=link Address=2001:0db8:1:f101::1/64 PreferredLifetime=0 +[Address] +Address=10.8.8.1/16 +Broadcast=no + # test for ENOBUFS issue #17012 [Network] Address=10.3.3.1/16 diff --git a/test/test-network/conf/25-wireguard-23-peers.network b/test/test-network/conf/25-wireguard-23-peers.network index 4dc87f8d4c..033ffa155d 100644 --- a/test/test-network/conf/25-wireguard-23-peers.network +++ b/test/test-network/conf/25-wireguard-23-peers.network @@ -2,6 +2,7 @@ Name=wg98 [Network] +Address=192.168.123.123/24 Address=fd8d:4d6d:3ccb:0500::1/64 # nat64 via 1 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 12e9a0a4a3..a5942ec4ea 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1220,6 +1220,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): start_networkd() self.wait_online(['wg99:carrier', 'wg98:routable', 'wg97:carrier']) + output = check_output('ip -4 address show dev wg98') + print(output) + self.assertIn('inet 192.168.123.123/24 scope global wg98', output) + + output = check_output('ip -6 address show dev wg98') + print(output) + self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output) + if shutil.which('wg'): call('wg') @@ -1833,6 +1841,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output) self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output) self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output) + self.assertIn('inet 10.8.8.1/16 scope global dummy98', output) # test for ENOBUFS issue #17012 for i in range(1,254):