]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/address: several cleanups for config_parse_address()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 22 Sep 2024 18:36:15 +0000 (03:36 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 11 Oct 2024 18:26:06 +0000 (03:26 +0900)
- make it accept an empty string,
- use config_parse_in_addr_prefix(),
- move null address checker to address_section_verify().

No functional change, just refactoring.

src/network/networkd-address.c
src/network/networkd-address.h
src/network/networkd-network-gperf.gperf

index e2fec8e268d9b8710975bc3353f4b28759764c6c..deffa4deadeba0712a1f21cda96dd62164880a82 100644 (file)
@@ -3,8 +3,10 @@
 #include <net/if.h>
 #include <net/if_arp.h>
 
+#include "af-list.h"
 #include "alloc-util.h"
 #include "firewall-util.h"
+#include "in-addr-prefix-util.h"
 #include "logarithm.h"
 #include "memory-util.h"
 #include "netlink-util.h"
@@ -2076,53 +2078,33 @@ static int config_parse_address(
                 void *userdata) {
 
         Address *address = ASSERT_PTR(userdata);
-        union in_addr_union buffer;
-        unsigned char prefixlen;
-        int r, f;
+        union in_addr_union *a = ASSERT_PTR(data);
+        struct in_addr_prefix prefix;
+        int r;
 
         assert(rvalue);
 
-        /* Address=address/prefixlen */
-        r = in_addr_prefix_from_string_auto_full(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen);
-        if (r == -ENOANO) {
-                r = in_addr_prefix_from_string_auto(rvalue, &f, &buffer, &prefixlen);
-                if (r >= 0)
-                        log_syntax(unit, LOG_WARNING, filename, line, r,
-                                   "Address '%s' is specified without prefix length. Assuming the prefix length is %u. "
-                                   "Please specify the prefix length explicitly.", rvalue, prefixlen);
+        if (isempty(rvalue)) {
+                /* When an empty string is assigned, clear both Address= and Peer=. */
+                address->family = AF_UNSPEC;
+                address->prefixlen = 0;
+                address->in_addr = IN_ADDR_NULL;
+                address->in_addr_peer = IN_ADDR_NULL;
+                return 1;
         }
-        if (r < 0)
-                return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
 
-        if (address->family != AF_UNSPEC && f != address->family) {
+        r = config_parse_in_addr_prefix(unit, filename, line, section, section_line, lvalue, /* ltype = */ true, rvalue, &prefix, /* userdata = */ NULL);
+        if (r <= 0)
+                return r;
+
+        if (address->family != AF_UNSPEC && prefix.family != address->family) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue);
                 return 0;
         }
 
-        if (in_addr_is_null(f, &buffer)) {
-                /* Will use address from address pool. Note that for ipv6 case, prefix of the address
-                 * pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
-                 * let's limit the prefix length to 64 or larger. See RFC4193. */
-                if ((f == AF_INET && prefixlen < 8) ||
-                    (f == AF_INET6 && prefixlen < 64)) {
-                        log_syntax(unit, LOG_WARNING, filename, line, 0,
-                                   "Null address with invalid prefixlen='%u', ignoring assignment: %s",
-                                   prefixlen, rvalue);
-                        return 0;
-                }
-        }
-
-        address->family = f;
-        address->prefixlen = prefixlen;
-
-        if (streq_ptr(lvalue, "Address")) {
-                address->in_addr = buffer;
-                address->requested_as_null = !in_addr_is_set(address->family, &address->in_addr);
-        } else if (streq_ptr(lvalue, "Peer"))
-                address->in_addr_peer = buffer;
-        else
-                assert_not_reached();
-
+        address->family = prefix.family;
+        address->prefixlen = prefix.prefixlen;
+        *a = prefix.address;
         return 1;
 }
 
@@ -2263,7 +2245,8 @@ int config_parse_address_section(
                 void *userdata) {
 
         static const ConfigSectionParser table[_ADDRESS_CONF_PARSER_MAX] = {
-                [ADDRESS_ADDRESS]                  = { .parser = config_parse_address,            .ltype = 0,                        .offset = 0,                                              },
+                [ADDRESS_ADDRESS]                  = { .parser = config_parse_address,            .ltype = 0,                        .offset = offsetof(Address, in_addr),                     },
+                [ADDRESS_PEER]                     = { .parser = config_parse_address,            .ltype = 0,                        .offset = offsetof(Address, in_addr_peer),                },
                 [ADDRESS_BROADCAST]                = { .parser = config_parse_broadcast,          .ltype = 0,                        .offset = 0,                                              },
                 [ADDRESS_LABEL]                    = { .parser = config_parse_address_label,      .ltype = 0,                        .offset = offsetof(Address, label),                       },
                 [ADDRESS_PREFERRED_LIFETIME]       = { .parser = config_parse_address_lifetime,   .ltype = 0,                        .offset = offsetof(Address, lifetime_preferred_usec),     },
@@ -2366,11 +2349,22 @@ int address_section_verify(Address *address) {
 
         if (address->family == AF_UNSPEC)
                 return log_address_section(address, "Address section without Address= field was configured.");
+        assert(IN_SET(address->family, AF_INET, AF_INET6));
 
         if (address->family == AF_INET6 && !socket_ipv6_is_supported())
                 return log_address_section(address, "An IPv6 address was configured, but the kernel does not support IPv6.");
 
-        assert(IN_SET(address->family, AF_INET, AF_INET6));
+        if (in_addr_is_null(address->family, &address->in_addr)) {
+                /* Will use address from address pool. Note that for ipv6 case, prefix of the address
+                 * pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
+                 * let's limit the prefix length to 64 or larger. See RFC4193. */
+                unsigned min_prefixlen = address->family == AF_INET ? 8 : 64;
+                if (address->prefixlen < min_prefixlen)
+                        return log_address_section(address, "Prefix length for %s null address must be equal or larger than %u.",
+                                                   af_to_ipv4_ipv6(address->family), min_prefixlen);
+
+                address->requested_as_null = !in_addr_is_set(address->family, &address->in_addr);
+        }
 
         address_section_adjust_broadcast(address);
 
index 083a939e1f04cbf4fa7f327a7d2ab941a9edbe61..f799d59460e24ecce7e83b1a5cd1e5ce6b6d76e1 100644 (file)
@@ -161,6 +161,7 @@ void link_mark_addresses(Link *link, NetworkConfigSource source);
 
 typedef enum AddressConfParserType {
         ADDRESS_ADDRESS,
+        ADDRESS_PEER,
         ADDRESS_BROADCAST,
         ADDRESS_LABEL,
         ADDRESS_PREFERRED_LIFETIME,
index d91a15d085cd44f6babc3e66361cb569a6d32ba4..26b22ffd9e993440729a9392325643b28d453f1f 100644 (file)
@@ -157,7 +157,7 @@ Network.KeepConfiguration,                   config_parse_keep_configuration,
 Network.IPv6SendRA,                          config_parse_router_prefix_delegation,                    0,                             offsetof(Network, router_prefix_delegation)
 Network.DHCPPrefixDelegation,                config_parse_tristate,                                    0,                             offsetof(Network, dhcp_pd)
 Address.Address,                             config_parse_address_section,                             ADDRESS_ADDRESS,               0
-Address.Peer,                                config_parse_address_section,                             ADDRESS_ADDRESS,               0
+Address.Peer,                                config_parse_address_section,                             ADDRESS_PEER,                  0
 Address.Broadcast,                           config_parse_address_section,                             ADDRESS_BROADCAST,             0
 Address.Label,                               config_parse_address_section,                             ADDRESS_LABEL,                 0
 Address.PreferredLifetime,                   config_parse_address_section,                             ADDRESS_PREFERRED_LIFETIME,    0