From 152b8a4e7171654670d6e4b643397412c7a4bad5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 28 Aug 2024 11:57:34 +0900 Subject: [PATCH 1/9] conf-parser: introduce config section parser wrapper It will be used later. --- src/network/networkd-routing-policy-rule.c | 58 +++++++++------------- src/shared/conf-parser.c | 31 ++++++++++++ src/shared/conf-parser.h | 19 +++++++ 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index 1efb2bff94..6fba52e887 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -1639,33 +1639,6 @@ static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT( AddressFamily, ADDRESS_FAMILY_NO); -typedef struct RoutingPolicyRuleConfParser { - ConfigParserCallback parser; - int ltype; - size_t offset; -} RoutingPolicyRuleConfParser; - -static RoutingPolicyRuleConfParser routing_policy_rule_conf_parser_table[_ROUTING_POLICY_RULE_CONF_PARSER_MAX] = { - [ROUTING_POLICY_RULE_IIF] = { .parser = config_parse_ifname, .ltype = 0, .offset = offsetof(RoutingPolicyRule, iif), }, - [ROUTING_POLICY_RULE_OIF] = { .parser = config_parse_ifname, .ltype = 0, .offset = offsetof(RoutingPolicyRule, oif), }, - [ROUTING_POLICY_RULE_FAMILY] = { .parser = config_parse_routing_policy_rule_family, .ltype = 0, .offset = offsetof(RoutingPolicyRule, address_family), }, - [ROUTING_POLICY_RULE_FWMARK] = { .parser = config_parse_routing_policy_rule_fwmark, .ltype = 0, .offset = 0, }, - [ROUTING_POLICY_RULE_GOTO] = { .parser = config_parse_routing_policy_rule_goto, .ltype = 0, .offset = 0, }, - [ROUTING_POLICY_RULE_INVERT] = { .parser = config_parse_uint32_flag, .ltype = FIB_RULE_INVERT, .offset = offsetof(RoutingPolicyRule, flags), }, - [ROUTING_POLICY_RULE_IP_PROTOCOL] = { .parser = config_parse_ip_protocol, .ltype = 0, .offset = offsetof(RoutingPolicyRule, ipproto), }, - [ROUTING_POLICY_RULE_L3MDEV] = { .parser = config_parse_bool, .ltype = 0, .offset = offsetof(RoutingPolicyRule, l3mdev), }, - [ROUTING_POLICY_RULE_SPORT] = { .parser = config_parse_routing_policy_rule_port_range, .ltype = 0, .offset = offsetof(RoutingPolicyRule, sport), }, - [ROUTING_POLICY_RULE_DPORT] = { .parser = config_parse_routing_policy_rule_port_range, .ltype = 0, .offset = offsetof(RoutingPolicyRule, dport), }, - [ROUTING_POLICY_RULE_PREFIX] = { .parser = config_parse_routing_policy_rule_prefix, .ltype = 0, .offset = 0, }, - [ROUTING_POLICY_RULE_PRIORITY] = { .parser = config_parse_routing_policy_rule_priority, .ltype = 0, .offset = 0, }, - [ROUTING_POLICY_RULE_SUPPRESS_IFGROUP] = { .parser = config_parse_routing_policy_rule_suppress, .ltype = INT32_MAX, .offset = offsetof(RoutingPolicyRule, suppress_ifgroup), }, - [ROUTING_POLICY_RULE_SUPPRESS_PREFIXLEN] = { .parser = config_parse_routing_policy_rule_suppress, .ltype = 128, .offset = offsetof(RoutingPolicyRule, suppress_prefixlen), }, - [ROUTING_POLICY_RULE_TABLE] = { .parser = config_parse_routing_policy_rule_table, .ltype = 0, .offset = offsetof(RoutingPolicyRule, table), }, - [ROUTING_POLICY_RULE_TOS] = { .parser = config_parse_uint8, .ltype = 0, .offset = offsetof(RoutingPolicyRule, tos), }, - [ROUTING_POLICY_RULE_TYPE] = { .parser = config_parse_routing_policy_rule_type, .ltype = 0, .offset = offsetof(RoutingPolicyRule, type), }, - [ROUTING_POLICY_RULE_UID_RANGE] = { .parser = config_parse_routing_policy_rule_uid_range, .ltype = 0, .offset = offsetof(RoutingPolicyRule, uid_range), }, -}; - int config_parse_routing_policy_rule( const char *unit, const char *filename, @@ -1678,24 +1651,39 @@ int config_parse_routing_policy_rule( void *data, void *userdata) { + static const ConfigSectionParser table[_ROUTING_POLICY_RULE_CONF_PARSER_MAX] = { + [ROUTING_POLICY_RULE_IIF] = { .parser = config_parse_ifname, .ltype = 0, .offset = offsetof(RoutingPolicyRule, iif), }, + [ROUTING_POLICY_RULE_OIF] = { .parser = config_parse_ifname, .ltype = 0, .offset = offsetof(RoutingPolicyRule, oif), }, + [ROUTING_POLICY_RULE_FAMILY] = { .parser = config_parse_routing_policy_rule_family, .ltype = 0, .offset = offsetof(RoutingPolicyRule, address_family), }, + [ROUTING_POLICY_RULE_FWMARK] = { .parser = config_parse_routing_policy_rule_fwmark, .ltype = 0, .offset = 0, }, + [ROUTING_POLICY_RULE_GOTO] = { .parser = config_parse_routing_policy_rule_goto, .ltype = 0, .offset = 0, }, + [ROUTING_POLICY_RULE_INVERT] = { .parser = config_parse_uint32_flag, .ltype = FIB_RULE_INVERT, .offset = offsetof(RoutingPolicyRule, flags), }, + [ROUTING_POLICY_RULE_IP_PROTOCOL] = { .parser = config_parse_ip_protocol, .ltype = 0, .offset = offsetof(RoutingPolicyRule, ipproto), }, + [ROUTING_POLICY_RULE_L3MDEV] = { .parser = config_parse_bool, .ltype = 0, .offset = offsetof(RoutingPolicyRule, l3mdev), }, + [ROUTING_POLICY_RULE_SPORT] = { .parser = config_parse_routing_policy_rule_port_range, .ltype = 0, .offset = offsetof(RoutingPolicyRule, sport), }, + [ROUTING_POLICY_RULE_DPORT] = { .parser = config_parse_routing_policy_rule_port_range, .ltype = 0, .offset = offsetof(RoutingPolicyRule, dport), }, + [ROUTING_POLICY_RULE_PREFIX] = { .parser = config_parse_routing_policy_rule_prefix, .ltype = 0, .offset = 0, }, + [ROUTING_POLICY_RULE_PRIORITY] = { .parser = config_parse_routing_policy_rule_priority, .ltype = 0, .offset = 0, }, + [ROUTING_POLICY_RULE_SUPPRESS_IFGROUP] = { .parser = config_parse_routing_policy_rule_suppress, .ltype = INT32_MAX, .offset = offsetof(RoutingPolicyRule, suppress_ifgroup), }, + [ROUTING_POLICY_RULE_SUPPRESS_PREFIXLEN] = { .parser = config_parse_routing_policy_rule_suppress, .ltype = 128, .offset = offsetof(RoutingPolicyRule, suppress_prefixlen), }, + [ROUTING_POLICY_RULE_TABLE] = { .parser = config_parse_routing_policy_rule_table, .ltype = 0, .offset = offsetof(RoutingPolicyRule, table), }, + [ROUTING_POLICY_RULE_TOS] = { .parser = config_parse_uint8, .ltype = 0, .offset = offsetof(RoutingPolicyRule, tos), }, + [ROUTING_POLICY_RULE_TYPE] = { .parser = config_parse_routing_policy_rule_type, .ltype = 0, .offset = offsetof(RoutingPolicyRule, type), }, + [ROUTING_POLICY_RULE_UID_RANGE] = { .parser = config_parse_routing_policy_rule_uid_range, .ltype = 0, .offset = offsetof(RoutingPolicyRule, uid_range), }, + }; + _cleanup_(routing_policy_rule_unref_or_set_invalidp) RoutingPolicyRule *rule = NULL; Network *network = ASSERT_PTR(userdata); int r; assert(filename); - assert(ltype >= 0); - assert(ltype < _ROUTING_POLICY_RULE_CONF_PARSER_MAX); r = routing_policy_rule_new_static(network, filename, section_line, &rule); if (r < 0) return log_oom(); - RoutingPolicyRuleConfParser *e = routing_policy_rule_conf_parser_table + ltype; - assert(e->parser); - assert(e->offset < sizeof(RoutingPolicyRule)); - - r = e->parser(unit, filename, line, section, section_line, lvalue, e->ltype, rvalue, - (uint8_t*) rule + e->offset, rule); + r = config_section_parse(table, ELEMENTSOF(table), + unit, filename, line, section, section_line, lvalue, ltype, rvalue, rule); if (r <= 0) /* 0 means non-critical error, but the section will be ignored. */ return r; diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index e50ccad35a..d29d113bbc 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -793,6 +793,37 @@ bool stats_by_path_equal(Hashmap *a, Hashmap *b) { return true; } +int config_section_parse( + const ConfigSectionParser *parsers, + size_t n_parsers, + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *userdata) { + + assert(parsers); + assert(n_parsers > 0); + assert(ltype >= 0); + assert((size_t) ltype < n_parsers); + assert(userdata); + + const ConfigSectionParser *e = parsers + ltype; + assert(e->parser); + + /* This is used when a object is dynamically allocated per [SECTION] in a config parser, e.g. + * [Address] for systemd.network. Takes the allocated object as 'userdata', then it is passed to + * config parsers in the table. The 'data' field points to an element of the passed object, where + * its offset is given by the table. */ + + return e->parser(unit, filename, line, section, section_line, lvalue, e->ltype, rvalue, + (uint8_t*) userdata + e->offset, userdata); +} + void config_section_hash_func(const ConfigSection *c, struct siphash *state) { siphash24_compress_string(c->filename, state); siphash24_compress_typesafe(c->line, state); diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index bf64ab2ba6..bd7caf1f46 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -147,6 +147,25 @@ int config_get_stats_by_path( int hashmap_put_stats_by_path(Hashmap **stats_by_path, const char *path, const struct stat *st); bool stats_by_path_equal(Hashmap *a, Hashmap *b); +typedef struct ConfigSectionParser { + ConfigParserCallback parser; + int ltype; + size_t offset; +} ConfigSectionParser; + +int config_section_parse( + const ConfigSectionParser *parsers, + size_t n_parsers, + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *userdata); + typedef struct ConfigSection { unsigned line; bool invalid; From 934cf1c06b177553da38ec6137557cb912960cba Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 28 Aug 2024 13:57:05 +0900 Subject: [PATCH 2/9] network/address-label: introduce generic conf parser for [IPv6AddressLabel] section This also - renames n -> label, - use log_syntax_parse_error(). No functional change, just refactoring. --- src/network/networkd-address-label.c | 113 +++++++++++++---------- src/network/networkd-address-label.h | 15 ++- src/network/networkd-gperf.gperf | 4 +- src/network/networkd-network-gperf.gperf | 4 +- 4 files changed, 79 insertions(+), 57 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 3ac0cca72e..454516f7b9 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -336,7 +336,7 @@ void manager_drop_invalid_address_labels(Manager *manager) { drop_invalid_address_labels(manager->address_labels_by_section); } -int config_parse_address_label_prefix( +static int config_parse_ipv6_address_label_prefix( const char *unit, const char *filename, unsigned line, @@ -348,35 +348,20 @@ int config_parse_address_label_prefix( void *data, void *userdata) { - _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; - Manager *manager = ltype ? userdata : NULL; - Network *network = ltype ? NULL : userdata; + AddressLabel *label = ASSERT_PTR(userdata); unsigned char prefixlen; union in_addr_union a; int r; - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(userdata); - - r = address_label_new_static(manager, network, filename, section_line, &n); - if (r < 0) - return log_oom(); - if (isempty(rvalue)) { - n->prefix_set = false; - TAKE_PTR(n); - return 0; + label->prefix_set = false; + return 1; } r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &prefixlen); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Invalid prefix for address label, ignoring assignment: %s", rvalue); - return 0; - } + if (r < 0) + return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); + if (in6_addr_is_ipv4_mapped_address(&a.in6) && prefixlen > 96) { /* See ip6addrlbl_alloc() in net/ipv6/addrlabel.c of kernel. */ log_syntax(unit, LOG_WARNING, filename, line, 0, @@ -385,14 +370,13 @@ int config_parse_address_label_prefix( return 0; } - n->prefix = a.in6; - n->prefixlen = prefixlen; - n->prefix_set = true; - TAKE_PTR(n); - return 0; + label->prefix = a.in6; + label->prefixlen = prefixlen; + label->prefix_set = true; + return 1; } -int config_parse_address_label( +static int config_parse_ipv6_address_label( const char *unit, const char *filename, unsigned line, @@ -404,40 +388,67 @@ int config_parse_address_label( void *data, void *userdata) { - _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; - Manager *manager = ltype ? userdata : NULL; - Network *network = ltype ? NULL : userdata; - uint32_t k; + uint32_t k, *label = ASSERT_PTR(data); int r; - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(userdata); - - r = address_label_new_static(manager, network, filename, section_line, &n); - if (r < 0) - return log_oom(); - if (isempty(rvalue)) { - n->label = UINT32_MAX; - TAKE_PTR(n); - return 0; + *label = UINT32_MAX; + return 1; } r = safe_atou32(rvalue, &k); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue); - return 0; - } + if (r < 0) + return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); if (k == UINT32_MAX) { log_syntax(unit, LOG_WARNING, filename, line, 0, "Address label is invalid, ignoring: %s", rvalue); return 0; } - n->label = k; - TAKE_PTR(n); + *label = k; + return 1; +} + +int config_parse_ipv6_address_label_section( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + static const ConfigSectionParser table[_IPV6_ADDRESS_LABEL_CONF_PARSER_MAX] = { + [IPV6_ADDRESS_LABEL] = { .parser = config_parse_ipv6_address_label, .ltype = 0, .offset = offsetof(AddressLabel, label), }, + [IPV6_ADDRESS_LABEL_PREFIX] = { .parser = config_parse_ipv6_address_label_prefix, .ltype = 0, .offset = 0, }, + }; + + _cleanup_(address_label_free_or_set_invalidp) AddressLabel *label = NULL; + Manager *manager = NULL; + Network *network = NULL; + int r; + + assert(filename); + + if (FLAGS_SET(ltype, IPV6_ADDRESS_LABEL_BY_MANAGER)) + manager = ASSERT_PTR(userdata); + else + network = ASSERT_PTR(userdata); + + ltype &= IPV6_ADDRESS_LABEL_SECTION_MASK; + + r = address_label_new_static(manager, network, filename, section_line, &label); + if (r < 0) + return log_oom(); + + r = config_section_parse(table, ELEMENTSOF(table), + unit, filename, line, section, section_line, lvalue, ltype, rvalue, label); + if (r <= 0) + return r; + + TAKE_PTR(label); return 0; } diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h index d2165719c3..f0c7943545 100644 --- a/src/network/networkd-address-label.h +++ b/src/network/networkd-address-label.h @@ -30,5 +30,16 @@ void manager_drop_invalid_address_labels(Manager *manager); int link_request_static_address_labels(Link *link); int manager_request_static_address_labels(Manager *manager); -CONFIG_PARSER_PROTOTYPE(config_parse_address_label); -CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix); +typedef enum IPv6AddressLabelConfParserType { + IPV6_ADDRESS_LABEL, + IPV6_ADDRESS_LABEL_PREFIX, + _IPV6_ADDRESS_LABEL_CONF_PARSER_MAX, + _IPV6_ADDRESS_LABEL_CONF_PARSER_INVALID = -EINVAL, + + IPV6_ADDRESS_LABEL_BY_MANAGER = 1 << 16, + IPV6_ADDRESS_LABEL_SECTION_MASK = IPV6_ADDRESS_LABEL_BY_MANAGER - 1, +} IPv6AddressLabelConfParserType; + +assert_cc(IPV6_ADDRESS_LABEL_BY_MANAGER >= _IPV6_ADDRESS_LABEL_CONF_PARSER_MAX); + +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_address_label_section); diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf index 8b64b3af30..5894f4523c 100644 --- a/src/network/networkd-gperf.gperf +++ b/src/network/networkd-gperf.gperf @@ -34,8 +34,8 @@ Network.IPv6Forwarding, config_parse_tristate, Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Manager, ipv6_privacy_extensions) Network.UseDomains, config_parse_use_domains, 0, offsetof(Manager, use_domains) IPv6AcceptRA.UseDomains, config_parse_use_domains, 0, offsetof(Manager, ndisc_use_domains) -IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 1, 0 -IPv6AddressLabel.Label, config_parse_address_label, 1, 0 +IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_BY_MANAGER | IPV6_ADDRESS_LABEL_PREFIX, 0 +IPv6AddressLabel.Label, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_BY_MANAGER | IPV6_ADDRESS_LABEL, 0 DHCPv4.UseDomains, config_parse_use_domains, 0, offsetof(Manager, dhcp_use_domains) DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp_duid) DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp_duid) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index a84de4ca7f..e39c617500 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -171,8 +171,8 @@ Address.Scope, config_parse_address_scope, Address.RouteMetric, config_parse_address_route_metric, 0, 0 Address.NetLabel, config_parse_address_netlabel, 0, 0 Address.NFTSet, config_parse_address_ip_nft_set, NFT_SET_PARSE_NETWORK, 0 -IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0 -IPv6AddressLabel.Label, config_parse_address_label, 0, 0 +IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_PREFIX, 0 +IPv6AddressLabel.Label, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL, 0 Neighbor.Address, config_parse_neighbor_address, 0, 0 Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0 Neighbor.MACAddress, config_parse_neighbor_lladdr, 0, 0 /* deprecated */ From e208fad7984c7706c68ea2b39437cf3a166817c3 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 1 Sep 2024 21:01:40 +0900 Subject: [PATCH 3/9] network/address-label: use log_section_warning_errno() --- src/network/networkd-address-label.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c index 454516f7b9..8f7f571d21 100644 --- a/src/network/networkd-address-label.c +++ b/src/network/networkd-address-label.c @@ -296,6 +296,16 @@ int manager_request_static_address_labels(Manager *manager) { return 0; } +#define log_label_section(label, fmt, ...) \ + ({ \ + const AddressLabel *_label = (label); \ + log_section_warning_errno( \ + _label ? _label->section : NULL, \ + SYNTHETIC_ERRNO(EINVAL), \ + fmt " Ignoring [IPv6AddressLabel] section.", \ + ##__VA_ARGS__); \ + }) + static int address_label_section_verify(AddressLabel *label) { assert(label); assert(label->section); @@ -304,16 +314,10 @@ static int address_label_section_verify(AddressLabel *label) { return -EINVAL; if (!label->prefix_set) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: [IPv6AddressLabel] section without Prefix= setting specified. " - "Ignoring [IPv6AddressLabel] section from line %u.", - label->section->filename, label->section->line); + return log_label_section(label, "[IPv6AddressLabel] section without Prefix= setting specified."); if (label->label == UINT32_MAX) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: [IPv6AddressLabel] section without Label= setting specified. " - "Ignoring [IPv6AddressLabel] section from line %u.", - label->section->filename, label->section->line); + return log_label_section(label, "[IPv6AddressLabel] section without Label= setting specified."); return 0; } From c2e8e1f020ec0e3f47d3abe1519dc7557f9e7da2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sat, 31 Aug 2024 14:45:22 +0900 Subject: [PATCH 4/9] network: align table in network-gperf --- src/network/networkd-gperf.gperf | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf index 5894f4523c..b69ef5fd31 100644 --- a/src/network/networkd-gperf.gperf +++ b/src/network/networkd-gperf.gperf @@ -23,26 +23,26 @@ struct ConfigPerfItem; %struct-type %includes %% -Network.SpeedMeter, config_parse_bool, 0, offsetof(Manager, use_speed_meter) -Network.SpeedMeterIntervalSec, config_parse_sec, 0, offsetof(Manager, speed_meter_interval_usec) -Network.ManageForeignRoutingPolicyRules, config_parse_bool, 0, offsetof(Manager, manage_foreign_rules) -Network.ManageForeignRoutes, config_parse_bool, 0, offsetof(Manager, manage_foreign_routes) -Network.ManageForeignNextHops, config_parse_bool, 0, offsetof(Manager, manage_foreign_nexthops) -Network.RouteTable, config_parse_route_table_names, 0, 0 -Network.IPv4Forwarding, config_parse_tristate, 0, offsetof(Manager, ip_forwarding[0]) -Network.IPv6Forwarding, config_parse_tristate, 0, offsetof(Manager, ip_forwarding[1]) -Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Manager, ipv6_privacy_extensions) -Network.UseDomains, config_parse_use_domains, 0, offsetof(Manager, use_domains) -IPv6AcceptRA.UseDomains, config_parse_use_domains, 0, offsetof(Manager, ndisc_use_domains) +Network.SpeedMeter, config_parse_bool, 0, offsetof(Manager, use_speed_meter) +Network.SpeedMeterIntervalSec, config_parse_sec, 0, offsetof(Manager, speed_meter_interval_usec) +Network.ManageForeignRoutingPolicyRules, config_parse_bool, 0, offsetof(Manager, manage_foreign_rules) +Network.ManageForeignRoutes, config_parse_bool, 0, offsetof(Manager, manage_foreign_routes) +Network.ManageForeignNextHops, config_parse_bool, 0, offsetof(Manager, manage_foreign_nexthops) +Network.RouteTable, config_parse_route_table_names, 0, 0 +Network.IPv4Forwarding, config_parse_tristate, 0, offsetof(Manager, ip_forwarding[0]) +Network.IPv6Forwarding, config_parse_tristate, 0, offsetof(Manager, ip_forwarding[1]) +Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Manager, ipv6_privacy_extensions) +Network.UseDomains, config_parse_use_domains, 0, offsetof(Manager, use_domains) +IPv6AcceptRA.UseDomains, config_parse_use_domains, 0, offsetof(Manager, ndisc_use_domains) IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_BY_MANAGER | IPV6_ADDRESS_LABEL_PREFIX, 0 IPv6AddressLabel.Label, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_BY_MANAGER | IPV6_ADDRESS_LABEL, 0 -DHCPv4.UseDomains, config_parse_use_domains, 0, offsetof(Manager, dhcp_use_domains) -DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp_duid) -DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp_duid) -DHCPv6.UseDomains, config_parse_use_domains, 0, offsetof(Manager, dhcp6_use_domains) -DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp6_duid) -DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp6_duid) -DHCPServer.PersistLeases, config_parse_bool, 0, offsetof(Manager, dhcp_server_persist_leases) +DHCPv4.UseDomains, config_parse_use_domains, 0, offsetof(Manager, dhcp_use_domains) +DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp_duid) +DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp_duid) +DHCPv6.UseDomains, config_parse_use_domains, 0, offsetof(Manager, dhcp6_use_domains) +DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp6_duid) +DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp6_duid) +DHCPServer.PersistLeases, config_parse_bool, 0, offsetof(Manager, dhcp_server_persist_leases) /* Deprecated */ -DHCP.DUIDType, config_parse_manager_duid_type, 0, 0 -DHCP.DUIDRawData, config_parse_manager_duid_rawdata, 0, 0 +DHCP.DUIDType, config_parse_manager_duid_type, 0, 0 +DHCP.DUIDRawData, config_parse_manager_duid_rawdata, 0, 0 From ff616da45903bdbb21b886361a0f9d84678681e0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 28 Aug 2024 13:11:43 +0900 Subject: [PATCH 5/9] conf-parser: introduce config_parse_uint32_invert_flag() It is similar to config_parse_uint32_flag(), but drops the specified flag when true. --- src/shared/conf-parser.c | 25 +++++++++++++++++++++++++ src/shared/conf-parser.h | 1 + 2 files changed, 26 insertions(+) diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index d29d113bbc..6db9431708 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -1061,6 +1061,31 @@ int config_parse_uint32_flag( return 1; } +int config_parse_uint32_invert_flag( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint32_t *flags = ASSERT_PTR(data); + int r; + + assert(ltype != 0); + + r = isempty(rvalue) ? 0 : parse_boolean(rvalue); + if (r < 0) + return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); + + SET_FLAG(*flags, ltype, !r); + return 1; +} + int config_parse_id128( const char *unit, const char *filename, diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index bd7caf1f46..c542839a92 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -274,6 +274,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64); CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64_infinity); CONFIG_PARSER_PROTOTYPE(config_parse_bool); CONFIG_PARSER_PROTOTYPE(config_parse_uint32_flag); +CONFIG_PARSER_PROTOTYPE(config_parse_uint32_invert_flag); CONFIG_PARSER_PROTOTYPE(config_parse_id128); CONFIG_PARSER_PROTOTYPE(config_parse_tristate); CONFIG_PARSER_PROTOTYPE(config_parse_string); From 174c5c5f0686e85204083548805fbbb78a6ede82 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 1 Sep 2024 21:37:33 +0900 Subject: [PATCH 6/9] firewall-util: several cleanups for config_parse_nft_set() - use log_syntax_parse_error(), - return 1 on success, - drop unnecessary or redundant assertions, - add missing log_oom(). --- src/shared/firewall-util-nft.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/shared/firewall-util-nft.c b/src/shared/firewall-util-nft.c index e9bd286786..daf73c5b7b 100644 --- a/src/shared/firewall-util-nft.c +++ b/src/shared/firewall-util-nft.c @@ -1284,16 +1284,11 @@ int config_parse_nft_set( NFTSetContext *nft_set_context = ASSERT_PTR(data); int r; - assert(filename); - assert(lvalue); - assert(rvalue); - assert(nft_set_context); assert(IN_SET(ltype, NFT_SET_PARSE_NETWORK, NFT_SET_PARSE_CGROUP)); if (isempty(rvalue)) { nft_set_context_clear(nft_set_context); - - return 0; + return 1; } for (const char *p = rvalue;;) { @@ -1303,17 +1298,10 @@ int config_parse_nft_set( NFTSetSource source; r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - _cleanup_free_ char *esc = NULL; - - esc = cescape(rvalue); - log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax %s=%s, ignoring: %m", lvalue, strna(esc)); - return 0; - } + if (r < 0) + return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); if (r == 0) - return 0; + return 1; q = tuple; r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE, &source_str, &family_str, &table, &set); @@ -1365,7 +1353,7 @@ int config_parse_nft_set( r = nft_set_add(nft_set_context, source, nfproto, table, set); if (r < 0) - return r; + return log_oom(); } assert_not_reached(); From 6cf41d4603da48064e9349d62ab0ae04b8622a64 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 28 Aug 2024 14:01:36 +0900 Subject: [PATCH 7/9] network/address: introduce generic config parser for [Address] section Then, use generic conf parsers defined in conf-parser.[ch]. --- src/network/networkd-address.c | 159 +++-------------------- src/network/networkd-address.h | 18 ++- src/network/networkd-network-gperf.gperf | 16 +-- 3 files changed, 41 insertions(+), 152 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 7377c22407..c2342c641a 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -2280,53 +2280,6 @@ int config_parse_lifetime( return 0; } -int config_parse_address_flags( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Network *network = userdata; - _cleanup_(address_unref_or_set_invalidp) Address *n = NULL; - 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; - } - - r = parse_boolean(rvalue); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse %s=, ignoring: %s", lvalue, rvalue); - return 0; - } - - if (streq(lvalue, "AddPrefixRoute")) - r = !r; - - SET_FLAG(n->flags, ltype, r); - - TAKE_PTR(n); - return 0; -} - int config_parse_address_scope( const char *unit, const char *filename, @@ -2371,48 +2324,6 @@ int config_parse_address_scope( return 0; } -int config_parse_address_route_metric( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Network *network = userdata; - _cleanup_(address_unref_or_set_invalidp) Address *n = NULL; - 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; - } - - r = safe_atou32(rvalue, &n->route_metric); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, - "Could not parse %s=, ignoring assignment: %s", lvalue, rvalue); - return 0; - } - - TAKE_PTR(n); - return 0; -} - int config_parse_duplicate_address_detection( const char *unit, const char *filename, @@ -2467,7 +2378,7 @@ int config_parse_duplicate_address_detection( return 0; } -int config_parse_address_netlabel( +int config_parse_address_section( const char *unit, const char *filename, unsigned line, @@ -2479,18 +2390,24 @@ int config_parse_address_netlabel( void *data, void *userdata) { - Network *network = userdata; - _cleanup_(address_unref_or_set_invalidp) Address *n = NULL; + static const ConfigSectionParser table[_ADDRESS_CONF_PARSER_MAX] = { + [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_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), }, + }; + + _cleanup_(address_unref_or_set_invalidp) Address *address = NULL; + Network *network = ASSERT_PTR(userdata); int r; assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - assert(network); - r = address_new_static(network, filename, section_line, &n); + r = address_new_static(network, filename, section_line, &address); if (r == -ENOMEM) return log_oom(); if (r < 0) { @@ -2499,12 +2416,12 @@ int config_parse_address_netlabel( return 0; } - r = config_parse_string(unit, filename, line, section, section_line, - lvalue, CONFIG_PARSE_STRING_SAFE, rvalue, &n->netlabel, network); - if (r < 0) + r = config_section_parse(table, ELEMENTSOF(table), + unit, filename, line, section, section_line, lvalue, ltype, rvalue, address); + if (r <= 0) return r; - TAKE_PTR(n); + TAKE_PTR(address); return 0; } @@ -2655,41 +2572,3 @@ int network_drop_invalid_addresses(Network *network) { return 0; } - -int config_parse_address_ip_nft_set( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - Network *network = userdata; - _cleanup_(address_unref_or_set_invalidp) Address *n = NULL; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(network); - - 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 a new address, ignoring assignment: %m"); - return 0; - } - - r = config_parse_nft_set(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->nft_set_context, network); - if (r < 0) - return r; - - TAKE_PTR(n); - return 0; -} diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index fcad445e17..0c4a4d166e 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -159,13 +159,23 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Address, address); void link_mark_addresses(Link *link, NetworkConfigSource source); +typedef enum AddressConfParserType { + ADDRESS_HOME_ADDRESS, + ADDRESS_MANAGE_TEMPORARY_ADDRESS, + ADDRESS_PREFIX_ROUTE, + ADDRESS_ADD_PREFIX_ROUTE, + ADDRESS_AUTO_JOIN, + ADDRESS_ROUTE_METRIC, + ADDRESS_NET_LABEL, + ADDRESS_NFT_SET, + _ADDRESS_CONF_PARSER_MAX, + _ADDRESS_CONF_PARSER_INVALID = -EINVAL, +} 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_flags); CONFIG_PARSER_PROTOTYPE(config_parse_address_scope); -CONFIG_PARSER_PROTOTYPE(config_parse_address_route_metric); CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection); -CONFIG_PARSER_PROTOTYPE(config_parse_address_netlabel); -CONFIG_PARSER_PROTOTYPE(config_parse_address_ip_nft_set); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index e39c617500..d6a610e958 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -161,16 +161,16 @@ Address.Peer, config_parse_address, Address.Broadcast, config_parse_broadcast, 0, 0 Address.Label, config_parse_label, 0, 0 Address.PreferredLifetime, config_parse_lifetime, 0, 0 -Address.HomeAddress, config_parse_address_flags, IFA_F_HOMEADDRESS, 0 -Address.ManageTemporaryAddress, config_parse_address_flags, IFA_F_MANAGETEMPADDR, 0 -Address.PrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0 /* deprecated */ -Address.AddPrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0 -Address.AutoJoin, config_parse_address_flags, IFA_F_MCAUTOJOIN, 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.RouteMetric, config_parse_address_route_metric, 0, 0 -Address.NetLabel, config_parse_address_netlabel, 0, 0 -Address.NFTSet, config_parse_address_ip_nft_set, NFT_SET_PARSE_NETWORK, 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 IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_PREFIX, 0 IPv6AddressLabel.Label, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL, 0 Neighbor.Address, config_parse_neighbor_address, 0, 0 From c6f2197fcffd8c8ce585837afd66a382015855f0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 6 Sep 2024 10:38:15 +0900 Subject: [PATCH 8/9] network/address: use generic section parser more 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 | 275 +++++++---------------- src/network/networkd-address.h | 12 +- src/network/networkd-network-gperf.gperf | 16 +- src/network/test-networkd-conf.c | 2 +- 4 files changed, 101 insertions(+), 204 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index c2342c641a..18f0234ec3 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -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); - r = address_new_static(network, filename, section_line, &address); + if (streq(section, "Network")) { + assert(streq(lvalue, "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) { diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 0c4a4d166e..083a939e1f 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -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); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index d6a610e958..9f23542493 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -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 diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c index 186d9d3e65..f44383d03a 100644 --- a/src/network/test-networkd-conf.c +++ b/src/network/test-networkd-conf.c @@ -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); From dd1de202d76d8d54e8845bd6abe34d620e9d6a48 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 1 Sep 2024 21:08:57 +0900 Subject: [PATCH 9/9] network/address: use log_section_warning() --- src/network/networkd-address.c | 44 ++++++++++++++++------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 18f0234ec3..7807d83c5a 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -2352,34 +2352,35 @@ static void address_section_adjust_broadcast(Address *address) { address->broadcast.s_addr = 0; } +#define log_address_section(address, fmt, ...) \ + ({ \ + const Address *_address = (address); \ + log_section_warning_errno( \ + _address ? _address->section : NULL, \ + SYNTHETIC_ERRNO(EINVAL), \ + fmt " Ignoring [Address] section.", \ + ##__VA_ARGS__); \ + }) + int address_section_verify(Address *address) { + assert(address); + assert(address->section); + if (section_is_invalid(address->section)) return -EINVAL; - if (address->family == AF_UNSPEC) { - assert(address->section); - - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: Address section without Address= field was configured. " - "Ignoring [Address] section from line %u.", - address->section->filename, address->section->line); - } + if (address->family == AF_UNSPEC) + return log_address_section(address, "Address section without Address= field was configured."); if (address->family == AF_INET6 && !socket_ipv6_is_supported()) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: an IPv6 address was configured, but the kernel does not support IPv6. " - "Ignoring [Address] section from line %u.", - address->section->filename, address->section->line); + 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)); address_section_adjust_broadcast(address); if (address->family == AF_INET6 && address->label) { - log_warning("%s: address label is set for IPv6 address in the [Address] section from line %u. " - "Ignoring Label= setting.", - address->section->filename, address->section->line); - + log_section_warning(address->section, "Address label is set for IPv6 address, ignoring Label= setting."); address->label = mfree(address->label); } @@ -2398,11 +2399,9 @@ int address_section_verify(Address *address) { else address->duplicate_address_detection = ADDRESS_FAMILY_NO; } else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV6 && address->family == AF_INET) - log_warning("%s: DuplicateAddressDetection=ipv6 is specified for IPv4 address, ignoring.", - address->section->filename); + log_section_warning(address->section, "DuplicateAddressDetection=ipv6 is specified for IPv4 address, ignoring."); else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV4 && address->family == AF_INET6) - log_warning("%s: DuplicateAddressDetection=ipv4 is specified for IPv6 address, ignoring.", - address->section->filename); + log_section_warning(address->section, "DuplicateAddressDetection=ipv4 is specified for IPv6 address, ignoring."); if (address->family == AF_INET6 && !FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6)) @@ -2415,10 +2414,7 @@ int address_section_verify(Address *address) { _cleanup_free_ char *str = NULL; (void) address_flags_to_string_alloc(address->flags ^ filtered_flags, address->family, &str); - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), - "%s: unexpected address flags \"%s\" were configured. " - "Ignoring [Address] section from line %u.", - address->section->filename, strna(str), address->section->line); + return log_address_section(address, "unexpected address flags \"%s\" were configured.", strna(str)); } return 0;