]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: introduce address_set_broadcast()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 17 May 2021 10:31:55 +0000 (19:31 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 18 May 2021 11:20:20 +0000 (20:20 +0900)
src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-ipv4ll.c

index 5a3388c3c4aa85083099043523913a9f736897a2..c350b6e93312bc3f722f8374bf05b571e5ad8908 100644 (file)
@@ -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);
index e9fddddf9f71938c878dd81611989542bc2ff8d3..34dea4aa6455292017cc6ab01c5b3a49aa888531 100644 (file)
@@ -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);
 
index 8e2d761cf904a0a2ffe53be123ac5767c1d1a037..12ba5c085ad8d0595ecae2581db3b11b08e8b17a 100644 (file)
@@ -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;