]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: set broadcast address on request
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 23 Feb 2022 22:07:02 +0000 (07:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 23 Feb 2022 22:07:04 +0000 (07:07 +0900)
Previously, the broadcast address was set to a Address object in
address_section_verify() (or address_acquire()). But, for wireguard
interfaces, we do not use the broadcast address. The .network file may
be assigned to multiple interfaces, hence, we cannot determine if we
should set the broadcast address in address_section_verify().

This makes the broadcast address set in link_request_address().
Then, we set the broadcast address only when we need it.

src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-dhcp-server.c
src/network/networkd-ipv4ll.c

index 7d84b0df50989496509d05ea0c027f47b0308c60..ee1f0fc21a6f4db0c716efc697b0ad7b61cf5778 100644 (file)
@@ -174,8 +174,9 @@ void link_mark_addresses(Link *link, NetworkConfigSource source, const struct in
         }
 }
 
-static bool address_may_have_broadcast(const Address *a) {
+static bool address_needs_to_set_broadcast(const Address *a, Link *link) {
         assert(a);
+        assert(link);
 
         if (a->family != AF_INET)
                 return false;
@@ -188,38 +189,26 @@ static bool address_may_have_broadcast(const Address *a) {
         if (a->prefixlen > 30)
                 return false;
 
-        if (a->set_broadcast >= 0)
-                return a->set_broadcast;
-
-        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;
+                return false;
 
-        /* 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;
+        if (a->set_broadcast >= 0)
+                return a->set_broadcast;
 
-        a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen);
+        /* Defaults to true, except for wireguard, as typical configuration for wireguard does not set
+         * broadcast. */
+        return !streq_ptr(link->kind, "wireguard");
 }
 
-static bool address_may_set_broadcast(const Address *a, const Link *link) {
+void address_set_broadcast(Address *a, Link *link) {
         assert(a);
         assert(link);
 
-        if (!address_may_have_broadcast(a))
-                return false;
+        if (!address_needs_to_set_broadcast(a, link))
+                return;
 
-        /* Typical configuration for wireguard does not set broadcast. */
-        return !streq_ptr(link->kind, "wireguard");
+        a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen);
 }
 
 static struct ifa_cacheinfo *address_set_cinfo(const Address *a, struct ifa_cacheinfo *cinfo) {
@@ -975,7 +964,6 @@ static int address_acquire(Link *link, const Address *original, Address **ret) {
                 return r;
 
         na->in_addr = in_addr;
-        address_set_broadcast(na);
 
         *ret = TAKE_PTR(na);
         return 1;
@@ -1037,7 +1025,7 @@ static 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_set_broadcast(address, link)) {
+        } else if (in4_addr_is_set(&address->broadcast)) {
                 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");
@@ -1132,6 +1120,21 @@ int link_request_address(
                 consume_object = true;
         }
 
+        if (address_needs_to_set_broadcast(address, link)) {
+                if (!consume_object) {
+                        Address *a;
+
+                        r = address_dup(address, &a);
+                        if (r < 0)
+                                return r;
+
+                        address = a;
+                        consume_object = true;
+                }
+
+                address_set_broadcast(address, link);
+        }
+
         if (address_get(link, address, &existing) < 0) {
                 _cleanup_(address_freep) Address *tmp = NULL;
 
@@ -1922,10 +1925,11 @@ static int address_section_verify(Address *address) {
                                          address->section->filename, address->section->line);
         }
 
-        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. "
+        if (in4_addr_is_set(&address->broadcast) &&
+            (address->family == AF_INET6 || address->prefixlen > 30 ||
+             in_addr_is_set(address->family, &address->in_addr_peer))) {
+                log_warning("%s: broadcast address is set for an IPv6 address, "
+                            "an IPv4 address with peer address, or with prefix length larger than 30. "
                             "Ignoring Broadcast= setting in the [Address] section from line %u.",
                             address->section->filename, address->section->line);
 
index b135c66a09f46e8a62dd405c0cf01af04002f155..0b1f3192a2de92281ea44daacb9897b38f15741d 100644 (file)
@@ -70,7 +70,7 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m,
 int address_remove(Address *address);
 int address_dup(const Address *src, Address **ret);
 bool address_is_ready(const Address *a);
-void address_set_broadcast(Address *a);
+void address_set_broadcast(Address *a, Link *link);
 
 DEFINE_SECTION_CLEANUP_FUNCTIONS(Address, address_free);
 
index 48e919ce93175127de1bc024343267fe191888aa..b28d13ba65abab8c2684f6529ca885030eea394c 100644 (file)
@@ -106,7 +106,7 @@ int link_request_dhcp_server_address(Link *link) {
         address->family = AF_INET;
         address->in_addr.in = link->network->dhcp_server_address;
         address->prefixlen = link->network->dhcp_server_address_prefixlen;
-        address_set_broadcast(address);
+        address_set_broadcast(address, link);
 
         if (address_get(link, address, &existing) >= 0 &&
             address_exists(existing) &&
index f1d40fb99d40907d2800868a9c7062fa4e057f78..5e3854281c5627521082030a390597ba2cd3b7bd 100644 (file)
@@ -34,7 +34,7 @@ static int address_new_from_ipv4ll(Link *link, Address **ret) {
         address->prefixlen = 16;
         address->scope = RT_SCOPE_LINK;
         address->route_metric = IPV4LL_ROUTE_METRIC;
-        address_set_broadcast(address);
+        address_set_broadcast(address, link);
 
         *ret = TAKE_PTR(address);
         return 0;