1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

Merge pull request #34203 from yuwata/network-conf-parser

network: several cleanups for conf parser
This commit is contained in:
Yu Watanabe 2024-09-06 13:07:39 +09:00 committed by GitHub
commit 74fe65480c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 375 additions and 515 deletions

View File

@ -296,6 +296,16 @@ int manager_request_static_address_labels(Manager *manager) {
return 0; 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) { static int address_label_section_verify(AddressLabel *label) {
assert(label); assert(label);
assert(label->section); assert(label->section);
@ -304,16 +314,10 @@ static int address_label_section_verify(AddressLabel *label) {
return -EINVAL; return -EINVAL;
if (!label->prefix_set) if (!label->prefix_set)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), return log_label_section(label, "[IPv6AddressLabel] section without Prefix= setting specified.");
"%s: [IPv6AddressLabel] section without Prefix= setting specified. "
"Ignoring [IPv6AddressLabel] section from line %u.",
label->section->filename, label->section->line);
if (label->label == UINT32_MAX) if (label->label == UINT32_MAX)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), return log_label_section(label, "[IPv6AddressLabel] section without Label= setting specified.");
"%s: [IPv6AddressLabel] section without Label= setting specified. "
"Ignoring [IPv6AddressLabel] section from line %u.",
label->section->filename, label->section->line);
return 0; return 0;
} }
@ -336,7 +340,7 @@ void manager_drop_invalid_address_labels(Manager *manager) {
drop_invalid_address_labels(manager->address_labels_by_section); 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 *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -348,35 +352,20 @@ int config_parse_address_label_prefix(
void *data, void *data,
void *userdata) { void *userdata) {
_cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; AddressLabel *label = ASSERT_PTR(userdata);
Manager *manager = ltype ? userdata : NULL;
Network *network = ltype ? NULL : userdata;
unsigned char prefixlen; unsigned char prefixlen;
union in_addr_union a; union in_addr_union a;
int r; 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)) { if (isempty(rvalue)) {
n->prefix_set = false; label->prefix_set = false;
TAKE_PTR(n); return 1;
return 0;
} }
r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &prefixlen); r = in_addr_prefix_from_string(rvalue, AF_INET6, &a, &prefixlen);
if (r < 0) { if (r < 0)
log_syntax(unit, LOG_WARNING, filename, line, r, return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
"Invalid prefix for address label, ignoring assignment: %s", rvalue);
return 0;
}
if (in6_addr_is_ipv4_mapped_address(&a.in6) && prefixlen > 96) { if (in6_addr_is_ipv4_mapped_address(&a.in6) && prefixlen > 96) {
/* See ip6addrlbl_alloc() in net/ipv6/addrlabel.c of kernel. */ /* See ip6addrlbl_alloc() in net/ipv6/addrlabel.c of kernel. */
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
@ -385,14 +374,13 @@ int config_parse_address_label_prefix(
return 0; return 0;
} }
n->prefix = a.in6; label->prefix = a.in6;
n->prefixlen = prefixlen; label->prefixlen = prefixlen;
n->prefix_set = true; label->prefix_set = true;
TAKE_PTR(n); return 1;
return 0;
} }
int config_parse_address_label( static int config_parse_ipv6_address_label(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -404,40 +392,67 @@ int config_parse_address_label(
void *data, void *data,
void *userdata) { void *userdata) {
_cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; uint32_t k, *label = ASSERT_PTR(data);
Manager *manager = ltype ? userdata : NULL;
Network *network = ltype ? NULL : userdata;
uint32_t k;
int r; 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)) { if (isempty(rvalue)) {
n->label = UINT32_MAX; *label = UINT32_MAX;
TAKE_PTR(n); return 1;
return 0;
} }
r = safe_atou32(rvalue, &k); r = safe_atou32(rvalue, &k);
if (r < 0) { if (r < 0)
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue); return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
return 0;
}
if (k == UINT32_MAX) { if (k == UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Address label is invalid, ignoring: %s", rvalue); log_syntax(unit, LOG_WARNING, filename, line, 0, "Address label is invalid, ignoring: %s", rvalue);
return 0; return 0;
} }
n->label = k; *label = k;
TAKE_PTR(n); 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; return 0;
} }

View File

@ -30,5 +30,16 @@ void manager_drop_invalid_address_labels(Manager *manager);
int link_request_static_address_labels(Link *link); int link_request_static_address_labels(Link *link);
int manager_request_static_address_labels(Manager *manager); int manager_request_static_address_labels(Manager *manager);
CONFIG_PARSER_PROTOTYPE(config_parse_address_label); typedef enum IPv6AddressLabelConfParserType {
CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix); 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);

View File

@ -2015,7 +2015,7 @@ finalize:
return 1; return 1;
} }
int config_parse_broadcast( static int config_parse_broadcast(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -2027,72 +2027,49 @@ int config_parse_broadcast(
void *data, void *data,
void *userdata) { void *userdata) {
Network *network = userdata; Address *address = ASSERT_PTR(userdata);
_cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
union in_addr_union u; union in_addr_union u;
int r; 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)) { if (isempty(rvalue)) {
/* The broadcast address will be calculated based on Address=, and set if the link is /* 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. */ * not a wireguard interface. Here, we do not check or set address->family. */
n->broadcast = (struct in_addr) {}; address->broadcast = (struct in_addr) {};
n->set_broadcast = -1; address->set_broadcast = -1;
TAKE_PTR(n); return 1;
return 0;
} }
r = parse_boolean(rvalue); r = parse_boolean(rvalue);
if (r >= 0) { if (r >= 0) {
/* The broadcast address will be calculated based on Address=. Here, we do not check or /* The broadcast address will be calculated based on Address=. Here, we do not check or
* set n->family. */ * set address->family. */
n->broadcast = (struct in_addr) {}; address->broadcast = (struct in_addr) {};
n->set_broadcast = r; address->set_broadcast = r;
TAKE_PTR(n); return 1;
return 0;
} }
if (n->family == AF_INET6) { if (address->family == AF_INET6) {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue); "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
return 0; return 0;
} }
r = in_addr_from_string(AF_INET, rvalue, &u); r = in_addr_from_string(AF_INET, rvalue, &u);
if (r < 0) { if (r < 0)
log_syntax(unit, LOG_WARNING, filename, line, r, return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
"Broadcast is invalid, ignoring assignment: %s", rvalue);
return 0;
}
if (in4_addr_is_null(&u.in)) { if (in4_addr_is_null(&u.in)) {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Broadcast cannot be ANY address, ignoring assignment: %s", rvalue); "Broadcast cannot be ANY address, ignoring assignment: %s", rvalue);
return 0; return 0;
} }
n->broadcast = u.in; address->broadcast = u.in;
n->set_broadcast = true; address->set_broadcast = true;
n->family = AF_INET; address->family = AF_INET;
TAKE_PTR(n); return 1;
return 0;
} }
int config_parse_address( static int config_parse_address(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -2104,36 +2081,12 @@ int config_parse_address(
void *data, void *data,
void *userdata) { void *userdata) {
Network *network = userdata; Address *address = ASSERT_PTR(userdata);
_cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
union in_addr_union buffer; union in_addr_union buffer;
unsigned char prefixlen; unsigned char prefixlen;
int r, f; int r, f;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue); 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 */ /* Address=address/prefixlen */
r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &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. " "Address '%s' is specified without prefix length. Assuming the prefix length is %u. "
"Please specify the prefix length explicitly.", rvalue, prefixlen); "Please specify the prefix length explicitly.", rvalue, prefixlen);
} }
if (r < 0) { if (r < 0)
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue); return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
return 0;
}
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); log_syntax(unit, LOG_WARNING, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue);
return 0; return 0;
} }
@ -2167,20 +2118,21 @@ int config_parse_address(
} }
} }
n->family = f; address->family = f;
n->prefixlen = prefixlen; address->prefixlen = prefixlen;
if (streq(lvalue, "Address")) { if (streq_ptr(lvalue, "Address")) {
n->in_addr = buffer; address->in_addr = buffer;
n->requested_as_null = !in_addr_is_set(n->family, &n->in_addr); address->requested_as_null = !in_addr_is_set(address->family, &address->in_addr);
} else } else if (streq_ptr(lvalue, "Peer"))
n->in_addr_peer = buffer; address->in_addr_peer = buffer;
else
assert_not_reached();
TAKE_PTR(n); return 1;
return 0;
} }
int config_parse_label( static int config_parse_address_label(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -2192,46 +2144,23 @@ int config_parse_label(
void *data, void *data,
void *userdata) { void *userdata) {
_cleanup_(address_unref_or_set_invalidp) Address *n = NULL; char **label = ASSERT_PTR(data);
Network *network = userdata;
int r; int r;
assert(filename); if (!isempty(rvalue) && !address_label_valid(rvalue)) {
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)) {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Interface label is too long or invalid, ignoring assignment: %s", rvalue); "Interface label is too long or invalid, ignoring assignment: %s", rvalue);
return 0; return 0;
} }
r = free_and_strdup(&n->label, rvalue); r = free_and_strdup_warn(label, empty_to_null(rvalue));
if (r < 0) if (r < 0)
return log_oom(); return r;
TAKE_PTR(n); return 1;
return 0;
} }
int config_parse_lifetime( static int config_parse_address_lifetime(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -2243,44 +2172,23 @@ int config_parse_lifetime(
void *data, void *data,
void *userdata) { void *userdata) {
Network *network = userdata; usec_t *usec = ASSERT_PTR(data);
_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;
}
/* We accept only "forever", "infinity", empty, or "0". */ /* We accept only "forever", "infinity", empty, or "0". */
if (STR_IN_SET(rvalue, "forever", "infinity", "")) if (isempty(rvalue) || STR_IN_SET(rvalue, "forever", "infinity"))
k = USEC_INFINITY; *usec = USEC_INFINITY;
else if (streq(rvalue, "0")) else if (streq(rvalue, "0"))
k = 0; *usec = 0;
else { else {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid PreferredLifetime= value, ignoring: %s", rvalue); "Invalid PreferredLifetime= value, ignoring: %s", rvalue);
return 0; return 0;
} }
n->lifetime_preferred_usec = k; return 1;
TAKE_PTR(n);
return 0;
} }
int config_parse_address_flags( static int config_parse_address_scope(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -2292,86 +2200,25 @@ int config_parse_address_flags(
void *data, void *data,
void *userdata) { void *userdata) {
Network *network = userdata; Address *address = ASSERT_PTR(userdata);
_cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r; int r;
assert(filename); if (isempty(rvalue)) {
assert(section); address->scope = RT_SCOPE_UNIVERSE;
assert(lvalue); address->scope_set = false;
assert(rvalue); return 1;
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,
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 = route_scope_from_string(rvalue); r = route_scope_from_string(rvalue);
if (r < 0) { if (r < 0)
log_syntax(unit, LOG_WARNING, filename, line, r, return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
"Could not parse address scope \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
n->scope = r; address->scope = r;
n->scope_set = true; address->scope_set = true;
TAKE_PTR(n); return 1;
return 0;
} }
int config_parse_address_route_metric( static int config_parse_address_dad(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -2383,65 +2230,12 @@ int config_parse_address_route_metric(
void *data, void *data,
void *userdata) { void *userdata) {
Network *network = userdata; AddressFamily *p = ASSERT_PTR(data);
_cleanup_(address_unref_or_set_invalidp) Address *n = NULL;
int r; int r;
assert(filename); if (isempty(rvalue)) {
assert(section); *p = _ADDRESS_FAMILY_INVALID;
assert(lvalue); return 1;
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,
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); r = parse_boolean(rvalue);
@ -2450,24 +2244,19 @@ int config_parse_duplicate_address_detection(
"For historical reasons, %s=%s means %s=%s. " "For historical reasons, %s=%s means %s=%s. "
"Please use 'both', 'ipv4', 'ipv6' or 'none' instead.", "Please use 'both', 'ipv4', 'ipv6' or 'none' instead.",
lvalue, rvalue, lvalue, r ? "none" : "both"); lvalue, rvalue, lvalue, r ? "none" : "both");
n->duplicate_address_detection = r ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_YES; *p = r ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_YES;
n = NULL; return 1;
return 0;
} }
AddressFamily a = duplicate_address_detection_address_family_from_string(rvalue); AddressFamily a = duplicate_address_detection_address_family_from_string(rvalue);
if (a < 0) { if (a < 0)
log_syntax(unit, LOG_WARNING, filename, line, a, return log_syntax_parse_error(unit, filename, line, a, lvalue, rvalue);
"Failed to parse %s=, ignoring: %s", lvalue, rvalue);
return 0;
}
n->duplicate_address_detection = a;
TAKE_PTR(n); *p = a;
return 0; return 1;
} }
int config_parse_address_netlabel( int config_parse_address_section(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -2479,18 +2268,43 @@ int config_parse_address_netlabel(
void *data, void *data,
void *userdata) { void *userdata) {
Network *network = userdata; static const ConfigSectionParser table[_ADDRESS_CONF_PARSER_MAX] = {
_cleanup_(address_unref_or_set_invalidp) Address *n = NULL; [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), },
};
_cleanup_(address_unref_or_set_invalidp) Address *address = NULL;
Network *network = ASSERT_PTR(userdata);
int r; int r;
assert(filename); assert(filename);
assert(section); assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
assert(network);
r = address_new_static(network, filename, section_line, &n); 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) if (r == -ENOMEM)
return log_oom(); return log_oom();
if (r < 0) { if (r < 0) {
@ -2499,12 +2313,12 @@ int config_parse_address_netlabel(
return 0; return 0;
} }
r = config_parse_string(unit, filename, line, section, section_line, r = config_section_parse(table, ELEMENTSOF(table),
lvalue, CONFIG_PARSE_STRING_SAFE, rvalue, &n->netlabel, network); unit, filename, line, section, section_line, lvalue, ltype, rvalue, address);
if (r < 0) if (r <= 0)
return r; return r;
TAKE_PTR(n); TAKE_PTR(address);
return 0; return 0;
} }
@ -2538,34 +2352,35 @@ static void address_section_adjust_broadcast(Address *address) {
address->broadcast.s_addr = 0; 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) { int address_section_verify(Address *address) {
assert(address);
assert(address->section);
if (section_is_invalid(address->section)) if (section_is_invalid(address->section))
return -EINVAL; return -EINVAL;
if (address->family == AF_UNSPEC) { if (address->family == AF_UNSPEC)
assert(address->section); return log_address_section(address, "Address section without Address= field was configured.");
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_INET6 && !socket_ipv6_is_supported()) if (address->family == AF_INET6 && !socket_ipv6_is_supported())
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), return log_address_section(address, "An IPv6 address was configured, but the kernel does not support IPv6.");
"%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);
assert(IN_SET(address->family, AF_INET, AF_INET6)); assert(IN_SET(address->family, AF_INET, AF_INET6));
address_section_adjust_broadcast(address); address_section_adjust_broadcast(address);
if (address->family == AF_INET6 && address->label) { if (address->family == AF_INET6 && address->label) {
log_warning("%s: address label is set for IPv6 address in the [Address] section from line %u. " log_section_warning(address->section, "Address label is set for IPv6 address, ignoring Label= setting.");
"Ignoring Label= setting.",
address->section->filename, address->section->line);
address->label = mfree(address->label); address->label = mfree(address->label);
} }
@ -2584,11 +2399,9 @@ int address_section_verify(Address *address) {
else else
address->duplicate_address_detection = ADDRESS_FAMILY_NO; address->duplicate_address_detection = ADDRESS_FAMILY_NO;
} else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV6 && address->family == AF_INET) } else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV6 && address->family == AF_INET)
log_warning("%s: DuplicateAddressDetection=ipv6 is specified for IPv4 address, ignoring.", log_section_warning(address->section, "DuplicateAddressDetection=ipv6 is specified for IPv4 address, ignoring.");
address->section->filename);
else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV4 && address->family == AF_INET6) else if (address->duplicate_address_detection == ADDRESS_FAMILY_IPV4 && address->family == AF_INET6)
log_warning("%s: DuplicateAddressDetection=ipv4 is specified for IPv6 address, ignoring.", log_section_warning(address->section, "DuplicateAddressDetection=ipv4 is specified for IPv6 address, ignoring.");
address->section->filename);
if (address->family == AF_INET6 && if (address->family == AF_INET6 &&
!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6)) !FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6))
@ -2601,10 +2414,7 @@ int address_section_verify(Address *address) {
_cleanup_free_ char *str = NULL; _cleanup_free_ char *str = NULL;
(void) address_flags_to_string_alloc(address->flags ^ filtered_flags, address->family, &str); (void) address_flags_to_string_alloc(address->flags ^ filtered_flags, address->family, &str);
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), return log_address_section(address, "unexpected address flags \"%s\" were configured.", strna(str));
"%s: unexpected address flags \"%s\" were configured. "
"Ignoring [Address] section from line %u.",
address->section->filename, strna(str), address->section->line);
} }
return 0; return 0;
@ -2655,41 +2465,3 @@ int network_drop_invalid_addresses(Network *network) {
return 0; 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;
}

View File

@ -159,13 +159,23 @@ DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Address, address);
void link_mark_addresses(Link *link, NetworkConfigSource source); void link_mark_addresses(Link *link, NetworkConfigSource source);
CONFIG_PARSER_PROTOTYPE(config_parse_address); typedef enum AddressConfParserType {
CONFIG_PARSER_PROTOTYPE(config_parse_broadcast); ADDRESS_ADDRESS,
CONFIG_PARSER_PROTOTYPE(config_parse_label); ADDRESS_BROADCAST,
CONFIG_PARSER_PROTOTYPE(config_parse_lifetime); ADDRESS_LABEL,
CONFIG_PARSER_PROTOTYPE(config_parse_address_flags); ADDRESS_PREFERRED_LIFETIME,
CONFIG_PARSER_PROTOTYPE(config_parse_address_scope); ADDRESS_HOME_ADDRESS,
CONFIG_PARSER_PROTOTYPE(config_parse_address_route_metric); ADDRESS_MANAGE_TEMPORARY_ADDRESS,
CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection); ADDRESS_PREFIX_ROUTE,
CONFIG_PARSER_PROTOTYPE(config_parse_address_netlabel); ADDRESS_ADD_PREFIX_ROUTE,
CONFIG_PARSER_PROTOTYPE(config_parse_address_ip_nft_set); ADDRESS_AUTO_JOIN,
ADDRESS_DAD,
ADDRESS_SCOPE,
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);

View File

@ -23,26 +23,26 @@ struct ConfigPerfItem;
%struct-type %struct-type
%includes %includes
%% %%
Network.SpeedMeter, config_parse_bool, 0, offsetof(Manager, use_speed_meter) Network.SpeedMeter, config_parse_bool, 0, offsetof(Manager, use_speed_meter)
Network.SpeedMeterIntervalSec, config_parse_sec, 0, offsetof(Manager, speed_meter_interval_usec) Network.SpeedMeterIntervalSec, config_parse_sec, 0, offsetof(Manager, speed_meter_interval_usec)
Network.ManageForeignRoutingPolicyRules, config_parse_bool, 0, offsetof(Manager, manage_foreign_rules) Network.ManageForeignRoutingPolicyRules, config_parse_bool, 0, offsetof(Manager, manage_foreign_rules)
Network.ManageForeignRoutes, config_parse_bool, 0, offsetof(Manager, manage_foreign_routes) Network.ManageForeignRoutes, config_parse_bool, 0, offsetof(Manager, manage_foreign_routes)
Network.ManageForeignNextHops, config_parse_bool, 0, offsetof(Manager, manage_foreign_nexthops) Network.ManageForeignNextHops, config_parse_bool, 0, offsetof(Manager, manage_foreign_nexthops)
Network.RouteTable, config_parse_route_table_names, 0, 0 Network.RouteTable, config_parse_route_table_names, 0, 0
Network.IPv4Forwarding, config_parse_tristate, 0, offsetof(Manager, ip_forwarding[0]) Network.IPv4Forwarding, config_parse_tristate, 0, offsetof(Manager, ip_forwarding[0])
Network.IPv6Forwarding, config_parse_tristate, 0, offsetof(Manager, ip_forwarding[1]) 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.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Manager, ipv6_privacy_extensions)
Network.UseDomains, config_parse_use_domains, 0, offsetof(Manager, use_domains) Network.UseDomains, config_parse_use_domains, 0, offsetof(Manager, use_domains)
IPv6AcceptRA.UseDomains, config_parse_use_domains, 0, offsetof(Manager, ndisc_use_domains) IPv6AcceptRA.UseDomains, config_parse_use_domains, 0, offsetof(Manager, ndisc_use_domains)
IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 1, 0 IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_BY_MANAGER | IPV6_ADDRESS_LABEL_PREFIX, 0
IPv6AddressLabel.Label, config_parse_address_label, 1, 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.UseDomains, config_parse_use_domains, 0, offsetof(Manager, dhcp_use_domains)
DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp_duid) DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp_duid)
DHCPv4.DUIDRawData, config_parse_duid_rawdata, 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.UseDomains, config_parse_use_domains, 0, offsetof(Manager, dhcp6_use_domains)
DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp6_duid) DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp6_duid)
DHCPv6.DUIDRawData, config_parse_duid_rawdata, 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) DHCPServer.PersistLeases, config_parse_bool, 0, offsetof(Manager, dhcp_server_persist_leases)
/* Deprecated */ /* Deprecated */
DHCP.DUIDType, config_parse_manager_duid_type, 0, 0 DHCP.DUIDType, config_parse_manager_duid_type, 0, 0
DHCP.DUIDRawData, config_parse_manager_duid_rawdata, 0, 0 DHCP.DUIDRawData, config_parse_manager_duid_rawdata, 0, 0

View File

@ -117,7 +117,7 @@ Network.IPv4LLRoute, config_parse_bool,
Network.DefaultRouteOnDevice, config_parse_bool, 0, offsetof(Network, default_route_on_device) Network.DefaultRouteOnDevice, config_parse_bool, 0, offsetof(Network, default_route_on_device)
Network.LLDP, config_parse_lldp_mode, 0, offsetof(Network, lldp_mode) 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.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.Gateway, config_parse_gateway, 0, 0
Network.Domains, config_parse_domains, 0, 0 Network.Domains, config_parse_domains, 0, 0
Network.UseDomains, config_parse_use_domains, 0, offsetof(Network, use_domains) Network.UseDomains, config_parse_use_domains, 0, offsetof(Network, use_domains)
@ -156,23 +156,23 @@ Network.IgnoreCarrierLoss, config_parse_ignore_carrier_loss,
Network.KeepConfiguration, config_parse_keep_configuration, 0, offsetof(Network, keep_configuration) 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.IPv6SendRA, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
Network.DHCPPrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp_pd) Network.DHCPPrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp_pd)
Address.Address, config_parse_address, 0, 0 Address.Address, config_parse_address_section, ADDRESS_ADDRESS, 0
Address.Peer, config_parse_address, 0, 0 Address.Peer, config_parse_address_section, ADDRESS_ADDRESS, 0
Address.Broadcast, config_parse_broadcast, 0, 0 Address.Broadcast, config_parse_address_section, ADDRESS_BROADCAST, 0
Address.Label, config_parse_label, 0, 0 Address.Label, config_parse_address_section, ADDRESS_LABEL, 0
Address.PreferredLifetime, config_parse_lifetime, 0, 0 Address.PreferredLifetime, config_parse_address_section, ADDRESS_PREFERRED_LIFETIME, 0
Address.HomeAddress, config_parse_address_flags, IFA_F_HOMEADDRESS, 0 Address.HomeAddress, config_parse_address_section, ADDRESS_HOME_ADDRESS, 0
Address.ManageTemporaryAddress, config_parse_address_flags, IFA_F_MANAGETEMPADDR, 0 Address.ManageTemporaryAddress, config_parse_address_section, ADDRESS_MANAGE_TEMPORARY_ADDRESS, 0
Address.PrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0 /* deprecated */ Address.PrefixRoute, config_parse_address_section, ADDRESS_PREFIX_ROUTE, 0 /* deprecated */
Address.AddPrefixRoute, config_parse_address_flags, IFA_F_NOPREFIXROUTE, 0 Address.AddPrefixRoute, config_parse_address_section, ADDRESS_ADD_PREFIX_ROUTE, 0
Address.AutoJoin, config_parse_address_flags, IFA_F_MCAUTOJOIN, 0 Address.AutoJoin, config_parse_address_section, ADDRESS_AUTO_JOIN, 0
Address.DuplicateAddressDetection, config_parse_duplicate_address_detection, 0, 0 Address.DuplicateAddressDetection, config_parse_address_section, ADDRESS_DAD, 0
Address.Scope, config_parse_address_scope, 0, 0 Address.Scope, config_parse_address_section, ADDRESS_SCOPE, 0
Address.RouteMetric, config_parse_address_route_metric, 0, 0 Address.RouteMetric, config_parse_address_section, ADDRESS_ROUTE_METRIC, 0
Address.NetLabel, config_parse_address_netlabel, 0, 0 Address.NetLabel, config_parse_address_section, ADDRESS_NET_LABEL, 0
Address.NFTSet, config_parse_address_ip_nft_set, NFT_SET_PARSE_NETWORK, 0 Address.NFTSet, config_parse_address_section, ADDRESS_NFT_SET, 0
IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0 IPv6AddressLabel.Prefix, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL_PREFIX, 0
IPv6AddressLabel.Label, config_parse_address_label, 0, 0 IPv6AddressLabel.Label, config_parse_ipv6_address_label_section, IPV6_ADDRESS_LABEL, 0
Neighbor.Address, config_parse_neighbor_address, 0, 0 Neighbor.Address, config_parse_neighbor_address, 0, 0
Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0 Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0
Neighbor.MACAddress, config_parse_neighbor_lladdr, 0, 0 /* deprecated */ Neighbor.MACAddress, config_parse_neighbor_lladdr, 0, 0 /* deprecated */

View File

@ -1639,33 +1639,6 @@ static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(
AddressFamily, AddressFamily,
ADDRESS_FAMILY_NO); 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( int config_parse_routing_policy_rule(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -1678,24 +1651,39 @@ int config_parse_routing_policy_rule(
void *data, void *data,
void *userdata) { 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; _cleanup_(routing_policy_rule_unref_or_set_invalidp) RoutingPolicyRule *rule = NULL;
Network *network = ASSERT_PTR(userdata); Network *network = ASSERT_PTR(userdata);
int r; int r;
assert(filename); assert(filename);
assert(ltype >= 0);
assert(ltype < _ROUTING_POLICY_RULE_CONF_PARSER_MAX);
r = routing_policy_rule_new_static(network, filename, section_line, &rule); r = routing_policy_rule_new_static(network, filename, section_line, &rule);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
RoutingPolicyRuleConfParser *e = routing_policy_rule_conf_parser_table + ltype; r = config_section_parse(table, ELEMENTSOF(table),
assert(e->parser); unit, filename, line, section, section_line, lvalue, ltype, rvalue, rule);
assert(e->offset < sizeof(RoutingPolicyRule));
r = e->parser(unit, filename, line, section, section_line, lvalue, e->ltype, rvalue,
(uint8_t*) rule + e->offset, rule);
if (r <= 0) /* 0 means non-critical error, but the section will be ignored. */ if (r <= 0) /* 0 means non-critical error, but the section will be ignored. */
return r; return r;

View 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(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_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(ordered_hashmap_size(network->addresses_by_section) == 1);
assert_se(network_verify(network) >= 0); assert_se(network_verify(network) >= 0);
assert_se(ordered_hashmap_size(network->addresses_by_section) == n_addresses); assert_se(ordered_hashmap_size(network->addresses_by_section) == n_addresses);

View File

@ -793,6 +793,37 @@ bool stats_by_path_equal(Hashmap *a, Hashmap *b) {
return true; 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) { void config_section_hash_func(const ConfigSection *c, struct siphash *state) {
siphash24_compress_string(c->filename, state); siphash24_compress_string(c->filename, state);
siphash24_compress_typesafe(c->line, state); siphash24_compress_typesafe(c->line, state);
@ -1030,6 +1061,31 @@ int config_parse_uint32_flag(
return 1; 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( int config_parse_id128(
const char *unit, const char *unit,
const char *filename, const char *filename,

View File

@ -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); 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); 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 { typedef struct ConfigSection {
unsigned line; unsigned line;
bool invalid; bool invalid;
@ -255,6 +274,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64);
CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64_infinity); CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64_infinity);
CONFIG_PARSER_PROTOTYPE(config_parse_bool); CONFIG_PARSER_PROTOTYPE(config_parse_bool);
CONFIG_PARSER_PROTOTYPE(config_parse_uint32_flag); 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_id128);
CONFIG_PARSER_PROTOTYPE(config_parse_tristate); CONFIG_PARSER_PROTOTYPE(config_parse_tristate);
CONFIG_PARSER_PROTOTYPE(config_parse_string); CONFIG_PARSER_PROTOTYPE(config_parse_string);

View File

@ -1284,16 +1284,11 @@ int config_parse_nft_set(
NFTSetContext *nft_set_context = ASSERT_PTR(data); NFTSetContext *nft_set_context = ASSERT_PTR(data);
int r; int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(nft_set_context);
assert(IN_SET(ltype, NFT_SET_PARSE_NETWORK, NFT_SET_PARSE_CGROUP)); assert(IN_SET(ltype, NFT_SET_PARSE_NETWORK, NFT_SET_PARSE_CGROUP));
if (isempty(rvalue)) { if (isempty(rvalue)) {
nft_set_context_clear(nft_set_context); nft_set_context_clear(nft_set_context);
return 1;
return 0;
} }
for (const char *p = rvalue;;) { for (const char *p = rvalue;;) {
@ -1303,17 +1298,10 @@ int config_parse_nft_set(
NFTSetSource source; NFTSetSource source;
r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
if (r == -ENOMEM) if (r < 0)
return log_oom(); return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
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) if (r == 0)
return 0; return 1;
q = tuple; q = tuple;
r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE, &source_str, &family_str, &table, &set); 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); r = nft_set_add(nft_set_context, source, nfproto, table, set);
if (r < 0) if (r < 0)
return r; return log_oom();
} }
assert_not_reached(); assert_not_reached();