]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: make Broadcast= accept boolean value
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 18 Feb 2021 21:01:34 +0000 (06:01 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 20 Feb 2021 05:23:00 +0000 (14:23 +0900)
And disable it for wireguard interfaces by default.

Closes #18492.

man/systemd.network.xml
src/network/networkd-address.c
src/network/networkd-address.h

index dfc1dd37ff75f126826b9b3fd23e6e1650613cbf..015fcf01f99f5f597863a8fa8cfa2833bb0ca821 100644 (file)
@@ -1044,12 +1044,12 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
         <varlistentry>
           <term><varname>Broadcast=</varname></term>
           <listitem>
-            <para>The broadcast address, which must be in the format
-            described in
+            <para>Takes an IPv4 address or boolean value. The address must be in the format described in
             <citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
-            This key only applies to IPv4 addresses. If it is not
-            given, it is derived from the <varname>Address=</varname>
-            key.</para>
+            If set to true, then the IPv4 broadcast address will be derived from the
+            <varname>Address=</varname> 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.
+            </para>
           </listitem>
         </varlistentry>
         <varlistentry>
index 566709b3715d5c89ee024e9ad00aa6591e7a8843..58b089901bae4d4c28be37786e07ecad2bc79874 100644 (file)
@@ -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. "
index 7c2d0db3d07f6a0a1adc31176a2c54ed4056eb60..e3ca868c2ee8d27e3377c46c683c6ea129e8fc2d 100644 (file)
@@ -30,6 +30,7 @@ typedef struct Address {
         uint32_t flags;
         char *label;
 
+        int set_broadcast;
         struct in_addr broadcast;
         struct ifa_cacheinfo cinfo;