]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: refuse 169.254.0.0/24 and 169.254.255.0/24 for IPv4LLStartAddress=
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Jul 2022 18:36:30 +0000 (03:36 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Jul 2022 18:37:09 +0000 (03:37 +0900)
Follow-up for #23927.

man/systemd.network.xml
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/libsystemd-network/sd-ipv4ll.c
src/network/networkd-ipv4ll.c

index 671771830426838558615b7da3aa97a800fd6230..516a42e25a0090656a5061964db3d5f749d912ab 100644 (file)
       <varlistentry>
         <term><varname>IPv4LLStartAddress=</varname></term>
         <listitem>
-          <para>Specifies the first IPv4 link-local address to try. Takes an IPv4 address
-          for example 169.254.1.2, from the link-local address range 169.254.0.0/16.
-          This setting may be useful if the device should always have the same address
-          as long as there is no address conflict. When unset, a random address will be automatically selected.
-          Defaults to unset.
-          </para>
+          <para>Specifies the first IPv4 link-local address to try. Takes an IPv4 address for example
+          169.254.1.2, from the link-local address range: 169.254.0.0/16 except for 169.254.0.0/24 and
+          169.254.255.0/24. This setting may be useful if the device should always have the same address
+          as long as there is no address conflict. When unset, a random address will be automatically
+          selected. Defaults to unset.</para>
         </listitem>
       </varlistentry>
 
index 6f8ffaf25969f18c31c8e7d3ba6f15cf4ee55592..fe356c6d15c169875d085767a55330480bdb1f47 100644 (file)
@@ -49,6 +49,20 @@ bool in4_addr_is_link_local(const struct in_addr *a) {
         return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
 }
 
+bool in4_addr_is_link_local_dynamic(const struct in_addr *a) {
+        assert(a);
+
+        if (!in4_addr_is_link_local(a))
+                return false;
+
+        /* 169.254.0.0/24 and 169.254.255.0/24 must not be used for the dynamic IPv4LL assignment.
+         * See RFC 3927 Section 2.1:
+         * The IPv4 prefix 169.254/16 is registered with the IANA for this purpose. The first 256 and last
+         * 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected by a
+         * host using this dynamic configuration mechanism. */
+        return !IN_SET(be32toh(a->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
+}
+
 bool in6_addr_is_link_local(const struct in6_addr *a) {
         assert(a);
 
index c1e7ef965da0117ab98cb0397d6da726a93f8767..fbc60436c799162a098bb5a5ca93ccfb3ddf7d6c 100644 (file)
@@ -44,6 +44,7 @@ static inline bool in_addr_data_is_set(const struct in_addr_data *a) {
 int in_addr_is_multicast(int family, const union in_addr_union *u);
 
 bool in4_addr_is_link_local(const struct in_addr *a);
+bool in4_addr_is_link_local_dynamic(const struct in_addr *a);
 bool in6_addr_is_link_local(const struct in6_addr *a);
 int in_addr_is_link_local(int family, const union in_addr_union *u);
 bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);
index fe0d8361655063880aa26314902c1a0ddc1e85e1..155c1a5de6ce5fa8a2726db8a7cc9bf6c5fb2e71 100644 (file)
@@ -212,21 +212,12 @@ int sd_ipv4ll_is_running(sd_ipv4ll *ll) {
         return sd_ipv4acd_is_running(ll->acd);
 }
 
-static bool ipv4ll_address_is_valid(const struct in_addr *address) {
-        assert(address);
-
-        if (!in4_addr_is_link_local(address))
-                return false;
-
-        return !IN_SET(be32toh(address->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
-}
-
 int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) {
         int r;
 
         assert_return(ll, -EINVAL);
         assert_return(address, -EINVAL);
-        assert_return(ipv4ll_address_is_valid(address), -EINVAL);
+        assert_return(in4_addr_is_link_local_dynamic(address), -EINVAL);
 
         r = sd_ipv4acd_set_address(ll->acd, address);
         if (r < 0)
index 8833bee2330dfbff39e6930b7a921edb806cb326..6dfa60e08bdf568db7ac739639122d0a08c5ab81 100644 (file)
@@ -295,9 +295,10 @@ int config_parse_ipv4ll_address(
                            "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
                 return 0;
         }
-        if (!in4_addr_is_link_local(&a.in)) {
+        if (!in4_addr_is_link_local_dynamic(&a.in)) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0,
-                           "Not a IPv4 link local address, ignoring assignment: %s", rvalue);
+                           "Specified address cannot be used as an IPv4 link local address, ignoring assignment: %s",
+                           rvalue);
                 return 0;
         }