From: Yu Watanabe Date: Mon, 17 May 2021 10:31:55 +0000 (+0900) Subject: network: introduce address_set_broadcast() X-Git-Tag: v249-rc1~208^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=473680be325d9c849f5d344f682adc94b729b355;p=thirdparty%2Fsystemd.git network: introduce address_set_broadcast() --- diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 5a3388c3c4a..c350b6e9331 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -146,12 +146,38 @@ Address *address_free(Address *address) { static bool address_may_have_broadcast(const Address *a) { assert(a); + if (a->family != AF_INET) + return false; + + if (in4_addr_is_set(&a->in_addr_peer.in)) + return false; + /* A /31 or /32 IPv4 address does not have a broadcast address. * See https://tools.ietf.org/html/rfc3021 */ + if (a->prefixlen > 30) + return false; + + if (a->set_broadcast >= 0) + return a->set_broadcast; - return a->family == AF_INET && - in4_addr_is_null(&a->in_addr_peer.in) && - a->prefixlen <= 30; + return true; /* Defaults to true. */ +} + +void address_set_broadcast(Address *a) { + assert(a); + + if (!address_may_have_broadcast(a)) + return; + + /* If explicitly configured, do not update the address. */ + if (in4_addr_is_set(&a->broadcast)) + return; + + /* If Address= is 0.0.0.0, then the broadcast address will be set later in address_acquire(). */ + if (in4_addr_is_null(&a->in_addr.in)) + return; + + a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen); } static bool address_may_set_broadcast(const Address *a, const Link *link) { @@ -161,9 +187,6 @@ static bool address_may_set_broadcast(const Address *a, const Link *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"); } @@ -825,7 +848,6 @@ int link_drop_addresses(Link *link) { static int address_acquire(Link *link, const Address *original, Address **ret) { union in_addr_union in_addr = IN_ADDR_NULL; - struct in_addr broadcast = {}; _cleanup_(address_freep) Address *na = NULL; int r; @@ -847,16 +869,10 @@ static int address_acquire(Link *link, const Address *original, Address **ret) { if (r == 0) return -EBUSY; - if (original->family == AF_INET) { - /* Pick first address in range for ourselves ... */ + /* Pick first address in range for ourselves. */ + if (original->family == AF_INET) in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1); - - /* .. and use last as broadcast address */ - if (original->prefixlen > 30) - broadcast.s_addr = 0; - else - broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen); - } else if (original->family == AF_INET6) + else if (original->family == AF_INET6) in_addr.in6.s6_addr[15] |= 1; r = address_new(&na); @@ -867,8 +883,8 @@ static int address_acquire(Link *link, const Address *original, Address **ret) { if (r < 0) return r; - na->broadcast = broadcast; na->in_addr = in_addr; + address_set_broadcast(na); r = set_ensure_put(&link->pool_addresses, &address_hash_ops, na); if (r < 0) @@ -1957,10 +1973,9 @@ static int address_section_verify(Address *address) { address->section->filename, address->section->line); } - if (address_may_have_broadcast(address)) { - 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) { + if (address_may_have_broadcast(address)) + address_set_broadcast(address); + 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. " "Ignoring Broadcast= setting in the [Address] section from line %u.", address->section->filename, address->section->line); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index e9fddddf9f7..34dea4aa645 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -57,6 +57,7 @@ int address_remove_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Lin int address_remove(const Address *address, Link *link, link_netlink_message_handler_t callback); bool address_equal(const Address *a1, const Address *a2); bool address_is_ready(const Address *a); +void address_set_broadcast(Address *a); int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret); diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c index 8e2d761cf90..12ba5c085ad 100644 --- a/src/network/networkd-ipv4ll.c +++ b/src/network/networkd-ipv4ll.c @@ -31,9 +31,9 @@ static int address_new_from_ipv4ll(Link *link, Address **ret) { address->family = AF_INET; address->in_addr.in = addr; address->prefixlen = 16; - address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> address->prefixlen); address->scope = RT_SCOPE_LINK; address->route_metric = IPV4LL_ROUTE_METRIC; + address_set_broadcast(address); *ret = TAKE_PTR(address); return 0;