]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/address: use generic section parser more
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 6 Sep 2024 01:38:15 +0000 (10:38 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 6 Sep 2024 01:38:15 +0000 (10:38 +0900)
This also
- rename variable n -> address,
- use log_syntax_parse_error() where applicable,
- add one more assertion for lvalue in config_parse_address().

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

index c2342c641affb086dc6e2841566924a29d207a18..18f0234ec379c296304f84e42e98e4fd325c9df4 100644 (file)
@@ -2015,7 +2015,7 @@ finalize:
         return 1;
 }
 
-int config_parse_broadcast(
+static int config_parse_broadcast(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -2027,72 +2027,49 @@ int config_parse_broadcast(
                 void *data,
                 void *userdata) {
 
-        Network *network = userdata;
-        _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
+        Address *address = ASSERT_PTR(userdata);
         union in_addr_union u;
         int r;
 
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = address_new_static(network, filename, section_line, &n);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Failed to allocate new address, ignoring assignment: %m");
-                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;
+                 * not a wireguard interface. Here, we do not check or set address->family. */
+                address->broadcast = (struct in_addr) {};
+                address->set_broadcast = -1;
+                return 1;
         }
 
         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;
+                 * set address->family. */
+                address->broadcast = (struct in_addr) {};
+                address->set_broadcast = r;
+                return 1;
         }
 
-        if (n->family == AF_INET6) {
+        if (address->family == AF_INET6) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0,
                            "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
                 return 0;
         }
 
         r = in_addr_from_string(AF_INET, rvalue, &u);
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Broadcast is invalid, ignoring assignment: %s", rvalue);
-                return 0;
-        }
+        if (r < 0)
+                return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
         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);
-
-        return 0;
+        address->broadcast = u.in;
+        address->set_broadcast = true;
+        address->family = AF_INET;
+        return 1;
 }
 
-int config_parse_address(
+static int config_parse_address(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -2104,36 +2081,12 @@ int config_parse_address(
                 void *data,
                 void *userdata) {
 
-        Network *network = userdata;
-        _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
+        Address *address = ASSERT_PTR(userdata);
         union in_addr_union buffer;
         unsigned char prefixlen;
         int r, f;
 
-        assert(filename);
-        assert(section);
-        assert(lvalue);
         assert(rvalue);
-        assert(data);
-
-        if (streq(section, "Network")) {
-                if (isempty(rvalue)) {
-                        /* If an empty string specified in [Network] section, clear previously assigned addresses. */
-                        network->addresses_by_section = ordered_hashmap_free(network->addresses_by_section);
-                        return 0;
-                }
-
-                /* we are not in an Address section, so use line number instead. */
-                r = address_new_static(network, filename, line, &n);
-        } else
-                r = address_new_static(network, filename, section_line, &n);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Failed to allocate new address, ignoring assignment: %m");
-                return 0;
-        }
 
         /* Address=address/prefixlen */
         r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen);
@@ -2144,12 +2097,10 @@ int config_parse_address(
                                    "Address '%s' is specified without prefix length. Assuming the prefix length is %u. "
                                    "Please specify the prefix length explicitly.", rvalue, prefixlen);
         }
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue);
-                return 0;
-        }
+        if (r < 0)
+                return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
 
-        if (n->family != AF_UNSPEC && f != n->family) {
+        if (address->family != AF_UNSPEC && f != address->family) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue);
                 return 0;
         }
@@ -2167,20 +2118,21 @@ int config_parse_address(
                 }
         }
 
-        n->family = f;
-        n->prefixlen = prefixlen;
+        address->family = f;
+        address->prefixlen = prefixlen;
 
-        if (streq(lvalue, "Address")) {
-                n->in_addr = buffer;
-                n->requested_as_null = !in_addr_is_set(n->family, &n->in_addr);
-        } else
-                n->in_addr_peer = buffer;
+        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();
 
-        TAKE_PTR(n);
-        return 0;
+        return 1;
 }
 
-int config_parse_label(
+static int config_parse_address_label(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -2192,46 +2144,23 @@ int config_parse_label(
                 void *data,
                 void *userdata) {
 
-        _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
-        Network *network = userdata;
+        char **label = ASSERT_PTR(data);
         int r;
 
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = address_new_static(network, filename, section_line, &n);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Failed to allocate new address, ignoring assignment: %m");
-                return 0;
-        }
-
-        if (isempty(rvalue)) {
-                n->label = mfree(n->label);
-                TAKE_PTR(n);
-                return 0;
-        }
-
-        if (!address_label_valid(rvalue)) {
+        if (!isempty(rvalue) && !address_label_valid(rvalue)) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0,
                            "Interface label is too long or invalid, ignoring assignment: %s", rvalue);
                 return 0;
         }
 
-        r = free_and_strdup(&n->label, rvalue);
+        r = free_and_strdup_warn(label, empty_to_null(rvalue));
         if (r < 0)
-                return log_oom();
+                return r;
 
-        TAKE_PTR(n);
-        return 0;
+        return 1;
 }
 
-int config_parse_lifetime(
+static int config_parse_address_lifetime(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -2243,44 +2172,23 @@ int config_parse_lifetime(
                 void *data,
                 void *userdata) {
 
-        Network *network = userdata;
-        _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
-        usec_t k;
-        int r;
-
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = address_new_static(network, filename, section_line, &n);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Failed to allocate new address, ignoring assignment: %m");
-                return 0;
-        }
+        usec_t *usec = ASSERT_PTR(data);
 
         /* We accept only "forever", "infinity", empty, or "0". */
-        if (STR_IN_SET(rvalue, "forever", "infinity", ""))
-                k = USEC_INFINITY;
+        if (isempty(rvalue) || STR_IN_SET(rvalue, "forever", "infinity"))
+                *usec = USEC_INFINITY;
         else if (streq(rvalue, "0"))
-                k = 0;
+                *usec = 0;
         else {
                 log_syntax(unit, LOG_WARNING, filename, line, 0,
                            "Invalid PreferredLifetime= value, ignoring: %s", rvalue);
                 return 0;
         }
 
-        n->lifetime_preferred_usec = k;
-        TAKE_PTR(n);
-
-        return 0;
+        return 1;
 }
 
-int config_parse_address_scope(
+static int config_parse_address_scope(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -2292,39 +2200,25 @@ int config_parse_address_scope(
                 void *data,
                 void *userdata) {
 
-        Network *network = userdata;
-        _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
+        Address *address = ASSERT_PTR(userdata);
         int r;
 
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = address_new_static(network, filename, section_line, &n);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Failed to allocate new address, ignoring assignment: %m");
-                return 0;
+        if (isempty(rvalue)) {
+                address->scope = RT_SCOPE_UNIVERSE;
+                address->scope_set = false;
+                return 1;
         }
 
         r = route_scope_from_string(rvalue);
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Could not parse address scope \"%s\", ignoring assignment: %m", rvalue);
-                return 0;
-        }
+        if (r < 0)
+                return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
 
-        n->scope = r;
-        n->scope_set = true;
-        TAKE_PTR(n);
-        return 0;
+        address->scope = r;
+        address->scope_set = true;
+        return 1;
 }
 
-int config_parse_duplicate_address_detection(
+static int config_parse_address_dad(
                 const char *unit,
                 const char *filename,
                 unsigned line,
@@ -2336,23 +2230,12 @@ int config_parse_duplicate_address_detection(
                 void *data,
                 void *userdata) {
 
-        Network *network = userdata;
-        _cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
+        AddressFamily *p = ASSERT_PTR(data);
         int r;
 
-        assert(filename);
-        assert(section);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = address_new_static(network, filename, section_line, &n);
-        if (r == -ENOMEM)
-                return log_oom();
-        if (r < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, r,
-                           "Failed to allocate new address, ignoring assignment: %m");
-                return 0;
+        if (isempty(rvalue)) {
+                *p = _ADDRESS_FAMILY_INVALID;
+                return 1;
         }
 
         r = parse_boolean(rvalue);
@@ -2361,21 +2244,16 @@ int config_parse_duplicate_address_detection(
                            "For historical reasons, %s=%s means %s=%s. "
                            "Please use 'both', 'ipv4', 'ipv6' or 'none' instead.",
                            lvalue, rvalue, lvalue, r ? "none" : "both");
-                n->duplicate_address_detection = r ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_YES;
-                n = NULL;
-                return 0;
+                *p = r ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_YES;
+                return 1;
         }
 
         AddressFamily a = duplicate_address_detection_address_family_from_string(rvalue);
-        if (a < 0) {
-                log_syntax(unit, LOG_WARNING, filename, line, a,
-                           "Failed to parse %s=, ignoring: %s", lvalue, rvalue);
-                return 0;
-        }
-        n->duplicate_address_detection = a;
+        if (a < 0)
+                return log_syntax_parse_error(unit, filename, line, a, lvalue, rvalue);
 
-        TAKE_PTR(n);
-        return 0;
+        *p = a;
+        return 1;
 }
 
 int config_parse_address_section(
@@ -2391,11 +2269,17 @@ 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_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),     },
                 [ADDRESS_HOME_ADDRESS]             = { .parser = config_parse_uint32_flag,        .ltype = IFA_F_HOMEADDRESS,        .offset = offsetof(Address, flags),                       },
                 [ADDRESS_MANAGE_TEMPORARY_ADDRESS] = { .parser = config_parse_uint32_flag,        .ltype = IFA_F_MANAGETEMPADDR,     .offset = offsetof(Address, flags),                       },
                 [ADDRESS_PREFIX_ROUTE]             = { .parser = config_parse_uint32_flag,        .ltype = IFA_F_NOPREFIXROUTE,      .offset = offsetof(Address, flags),                       },
                 [ADDRESS_ADD_PREFIX_ROUTE]         = { .parser = config_parse_uint32_invert_flag, .ltype = IFA_F_NOPREFIXROUTE,      .offset = offsetof(Address, flags),                       },
                 [ADDRESS_AUTO_JOIN]                = { .parser = config_parse_uint32_flag,        .ltype = IFA_F_MCAUTOJOIN,         .offset = offsetof(Address, flags),                       },
+                [ADDRESS_DAD]                      = { .parser = config_parse_address_dad,        .ltype = 0,                        .offset = offsetof(Address, duplicate_address_detection), },
+                [ADDRESS_SCOPE]                    = { .parser = config_parse_address_scope,      .ltype = 0,                        .offset = 0,                                              },
                 [ADDRESS_ROUTE_METRIC]             = { .parser = config_parse_uint32,             .ltype = 0,                        .offset = offsetof(Address, route_metric),                },
                 [ADDRESS_NET_LABEL]                = { .parser = config_parse_string,             .ltype = CONFIG_PARSE_STRING_SAFE, .offset = offsetof(Address, netlabel),                    },
                 [ADDRESS_NFT_SET]                  = { .parser = config_parse_nft_set,            .ltype = NFT_SET_PARSE_NETWORK,    .offset = offsetof(Address, nft_set_context),             },
@@ -2406,8 +2290,21 @@ int config_parse_address_section(
         int r;
 
         assert(filename);
+        assert(section);
+
+        if (streq(section, "Network")) {
+                assert(streq(lvalue, "Address"));
 
-        r = address_new_static(network, filename, section_line, &address);
+                if (isempty(rvalue)) {
+                        /* If an empty string specified in [Network] section, clear previously assigned addresses. */
+                        network->addresses_by_section = ordered_hashmap_free(network->addresses_by_section);
+                        return 0;
+                }
+
+                /* we are not in an Address section, so use line number instead. */
+                r = address_new_static(network, filename, line, &address);
+        } else
+                r = address_new_static(network, filename, section_line, &address);
         if (r == -ENOMEM)
                 return log_oom();
         if (r < 0) {
index 0c4a4d166ea467e4a13a1eec50f1f4cb9bd41579..083a939e1f04cbf4fa7f327a7d2ab941a9edbe61 100644 (file)
@@ -160,11 +160,17 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Address, address);
 void link_mark_addresses(Link *link, NetworkConfigSource source);
 
 typedef enum AddressConfParserType {
+        ADDRESS_ADDRESS,
+        ADDRESS_BROADCAST,
+        ADDRESS_LABEL,
+        ADDRESS_PREFERRED_LIFETIME,
         ADDRESS_HOME_ADDRESS,
         ADDRESS_MANAGE_TEMPORARY_ADDRESS,
         ADDRESS_PREFIX_ROUTE,
         ADDRESS_ADD_PREFIX_ROUTE,
         ADDRESS_AUTO_JOIN,
+        ADDRESS_DAD,
+        ADDRESS_SCOPE,
         ADDRESS_ROUTE_METRIC,
         ADDRESS_NET_LABEL,
         ADDRESS_NFT_SET,
@@ -173,9 +179,3 @@ typedef enum AddressConfParserType {
 } AddressConfParserType;
 
 CONFIG_PARSER_PROTOTYPE(config_parse_address_section);
-CONFIG_PARSER_PROTOTYPE(config_parse_address);
-CONFIG_PARSER_PROTOTYPE(config_parse_broadcast);
-CONFIG_PARSER_PROTOTYPE(config_parse_label);
-CONFIG_PARSER_PROTOTYPE(config_parse_lifetime);
-CONFIG_PARSER_PROTOTYPE(config_parse_address_scope);
-CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection);
index d6a610e958e0ac73ff5f6418de54234686937788..9f235424936215264fe974f9bcaa531616041cd3 100644 (file)
@@ -117,7 +117,7 @@ Network.IPv4LLRoute,                         config_parse_bool,
 Network.DefaultRouteOnDevice,                config_parse_bool,                                        0,                             offsetof(Network, default_route_on_device)
 Network.LLDP,                                config_parse_lldp_mode,                                   0,                             offsetof(Network, lldp_mode)
 Network.EmitLLDP,                            config_parse_lldp_multicast_mode,                         0,                             offsetof(Network, lldp_multicast_mode)
-Network.Address,                             config_parse_address,                                     0,                             0
+Network.Address,                             config_parse_address_section,                             ADDRESS_ADDRESS,               0
 Network.Gateway,                             config_parse_gateway,                                     0,                             0
 Network.Domains,                             config_parse_domains,                                     0,                             0
 Network.UseDomains,                          config_parse_use_domains,                                 0,                             offsetof(Network, use_domains)
@@ -156,18 +156,18 @@ Network.IgnoreCarrierLoss,                   config_parse_ignore_carrier_loss,
 Network.KeepConfiguration,                   config_parse_keep_configuration,                          0,                             offsetof(Network, 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,                                     0,                             0
-Address.Peer,                                config_parse_address,                                     0,                             0
-Address.Broadcast,                           config_parse_broadcast,                                   0,                             0
-Address.Label,                               config_parse_label,                                       0,                             0
-Address.PreferredLifetime,                   config_parse_lifetime,                                    0,                             0
+Address.Address,                             config_parse_address_section,                             ADDRESS_ADDRESS,               0
+Address.Peer,                                config_parse_address_section,                             ADDRESS_ADDRESS,               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
 Address.HomeAddress,                         config_parse_address_section,                             ADDRESS_HOME_ADDRESS,          0
 Address.ManageTemporaryAddress,              config_parse_address_section,                             ADDRESS_MANAGE_TEMPORARY_ADDRESS, 0
 Address.PrefixRoute,                         config_parse_address_section,                             ADDRESS_PREFIX_ROUTE,          0 /* deprecated */
 Address.AddPrefixRoute,                      config_parse_address_section,                             ADDRESS_ADD_PREFIX_ROUTE,      0
 Address.AutoJoin,                            config_parse_address_section,                             ADDRESS_AUTO_JOIN,             0
-Address.DuplicateAddressDetection,           config_parse_duplicate_address_detection,                 0,                             0
-Address.Scope,                               config_parse_address_scope,                               0,                             0
+Address.DuplicateAddressDetection,           config_parse_address_section,                             ADDRESS_DAD,                   0
+Address.Scope,                               config_parse_address_section,                             ADDRESS_SCOPE,                 0
 Address.RouteMetric,                         config_parse_address_section,                             ADDRESS_ROUTE_METRIC,          0
 Address.NetLabel,                            config_parse_address_section,                             ADDRESS_NET_LABEL,             0
 Address.NFTSet,                              config_parse_address_section,                             ADDRESS_NFT_SET,               0
index 186d9d3e6521f47c830597516c6dec49dc8ba405..f44383d03ab4fa48509ca9ca902b22f0795a0e96 100644 (file)
@@ -194,7 +194,7 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign
         assert_se(network->filename = strdup("hogehoge.network"));
 
         assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match.ifname, network) == 0);
-        assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
+        assert_se(config_parse_address_section("network", "filename", 1, "section", 1, "Address", ADDRESS_ADDRESS, rvalue, network, network) == 0);
         assert_se(ordered_hashmap_size(network->addresses_by_section) == 1);
         assert_se(network_verify(network) >= 0);
         assert_se(ordered_hashmap_size(network->addresses_by_section) == n_addresses);