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

network: several cleanups for conf parsers
This commit is contained in:
Yu Watanabe
2024-10-12 05:22:11 +09:00
committed by GitHub
17 changed files with 394 additions and 639 deletions
+1 -1
View File
@@ -890,7 +890,7 @@ int in_addr_prefix_from_string(
return 0;
}
int in_addr_prefix_from_string_auto_internal(
int in_addr_prefix_from_string_auto_full(
const char *p,
InAddrPrefixLenMode mode,
int *ret_family,
+2 -2
View File
@@ -181,9 +181,9 @@ typedef enum InAddrPrefixLenMode {
PREFIXLEN_REFUSE, /* Fail with -ENOANO if prefixlen is not specified. */
} InAddrPrefixLenMode;
int in_addr_prefix_from_string_auto_internal(const char *p, InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
int in_addr_prefix_from_string_auto_full(const char *p, InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
static inline int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) {
return in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_FULL, ret_family, ret_prefix, ret_prefixlen);
return in_addr_prefix_from_string_auto_full(p, PREFIXLEN_FULL, ret_family, ret_prefix, ret_prefixlen);
}
static inline size_t FAMILY_ADDRESS_SIZE(int family) {
+47 -58
View File
@@ -3,8 +3,10 @@
#include <net/if.h>
#include <net/if_arp.h>
#include "af-list.h"
#include "alloc-util.h"
#include "firewall-util.h"
#include "in-addr-prefix-util.h"
#include "logarithm.h"
#include "memory-util.h"
#include "netlink-util.h"
@@ -2048,12 +2050,6 @@ static int config_parse_broadcast(
return 1;
}
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)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
@@ -2082,53 +2078,33 @@ static int config_parse_address(
void *userdata) {
Address *address = ASSERT_PTR(userdata);
union in_addr_union buffer;
unsigned char prefixlen;
int r, f;
union in_addr_union *a = ASSERT_PTR(data);
struct in_addr_prefix prefix;
int r;
assert(rvalue);
/* Address=address/prefixlen */
r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen);
if (r == -ENOANO) {
r = in_addr_prefix_from_string_auto(rvalue, &f, &buffer, &prefixlen);
if (r >= 0)
log_syntax(unit, LOG_WARNING, filename, line, r,
"Address '%s' is specified without prefix length. Assuming the prefix length is %u. "
"Please specify the prefix length explicitly.", rvalue, prefixlen);
if (isempty(rvalue)) {
/* When an empty string is assigned, clear both Address= and Peer=. */
address->family = AF_UNSPEC;
address->prefixlen = 0;
address->in_addr = IN_ADDR_NULL;
address->in_addr_peer = IN_ADDR_NULL;
return 1;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
if (address->family != AF_UNSPEC && f != address->family) {
r = config_parse_in_addr_prefix(unit, filename, line, section, section_line, lvalue, /* ltype = */ true, rvalue, &prefix, /* userdata = */ NULL);
if (r <= 0)
return r;
if (address->family != AF_UNSPEC && prefix.family != address->family) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue);
return 0;
}
if (in_addr_is_null(f, &buffer)) {
/* Will use address from address pool. Note that for ipv6 case, prefix of the address
* pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
* let's limit the prefix length to 64 or larger. See RFC4193. */
if ((f == AF_INET && prefixlen < 8) ||
(f == AF_INET6 && prefixlen < 64)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Null address with invalid prefixlen='%u', ignoring assignment: %s",
prefixlen, rvalue);
return 0;
}
}
address->family = f;
address->prefixlen = prefixlen;
if (streq_ptr(lvalue, "Address")) {
address->in_addr = buffer;
address->requested_as_null = !in_addr_is_set(address->family, &address->in_addr);
} else if (streq_ptr(lvalue, "Peer"))
address->in_addr_peer = buffer;
else
assert_not_reached();
address->family = prefix.family;
address->prefixlen = prefix.prefixlen;
*a = prefix.address;
return 1;
}
@@ -2269,7 +2245,8 @@ int config_parse_address_section(
void *userdata) {
static const ConfigSectionParser table[_ADDRESS_CONF_PARSER_MAX] = {
[ADDRESS_ADDRESS] = { .parser = config_parse_address, .ltype = 0, .offset = 0, },
[ADDRESS_ADDRESS] = { .parser = config_parse_address, .ltype = 0, .offset = offsetof(Address, in_addr), },
[ADDRESS_PEER] = { .parser = config_parse_address, .ltype = 0, .offset = offsetof(Address, in_addr_peer), },
[ADDRESS_BROADCAST] = { .parser = config_parse_broadcast, .ltype = 0, .offset = 0, },
[ADDRESS_LABEL] = { .parser = config_parse_address_label, .ltype = 0, .offset = offsetof(Address, label), },
[ADDRESS_PREFERRED_LIFETIME] = { .parser = config_parse_address_lifetime, .ltype = 0, .offset = offsetof(Address, lifetime_preferred_usec), },
@@ -2322,6 +2299,15 @@ int config_parse_address_section(
return 0;
}
#define log_broadcast(address, fmt, ...) \
({ \
const Address *_address = (address); \
log_section_warning( \
_address ? _address->section : NULL, \
fmt " Ignoring Broadcast= setting in the [Address] section.", \
##__VA_ARGS__); \
})
static void address_section_adjust_broadcast(Address *address) {
assert(address);
assert(address->section);
@@ -2330,21 +2316,13 @@ static void address_section_adjust_broadcast(Address *address) {
return;
if (address->family == AF_INET6)
log_warning("%s: broadcast address is set for an IPv6 address. "
"Ignoring Broadcast= setting in the [Address] section from line %u.",
address->section->filename, address->section->line);
log_broadcast(address, "Broadcast address is set for an IPv6 address.");
else if (address->prefixlen > 30)
log_warning("%s: broadcast address is set for an IPv4 address with prefix length larger than 30. "
"Ignoring Broadcast= setting in the [Address] section from line %u.",
address->section->filename, address->section->line);
log_broadcast(address, "Broadcast address is set for an IPv4 address with prefix length larger than 30.");
else if (in4_addr_is_set(&address->in_addr_peer.in))
log_warning("%s: broadcast address is set for an IPv4 address with peer address. "
"Ignoring Broadcast= setting in the [Address] section from line %u.",
address->section->filename, address->section->line);
log_broadcast(address, "Broadcast address is set for an IPv4 address with peer address.");
else if (!in4_addr_is_set(&address->in_addr.in))
log_warning("%s: broadcast address is set for an IPv4 address with null address. "
"Ignoring Broadcast= setting in the [Address] section from line %u.",
address->section->filename, address->section->line);
log_broadcast(address, "Broadcast address is set for an IPv4 address with null address.");
else
/* Otherwise, keep the specified broadcast address. */
return;
@@ -2371,11 +2349,22 @@ int address_section_verify(Address *address) {
if (address->family == AF_UNSPEC)
return log_address_section(address, "Address section without Address= field was configured.");
assert(IN_SET(address->family, AF_INET, AF_INET6));
if (address->family == AF_INET6 && !socket_ipv6_is_supported())
return log_address_section(address, "An IPv6 address was configured, but the kernel does not support IPv6.");
assert(IN_SET(address->family, AF_INET, AF_INET6));
if (in_addr_is_null(address->family, &address->in_addr)) {
/* Will use address from address pool. Note that for ipv6 case, prefix of the address
* pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
* let's limit the prefix length to 64 or larger. See RFC4193. */
unsigned min_prefixlen = address->family == AF_INET ? 8 : 64;
if (address->prefixlen < min_prefixlen)
return log_address_section(address, "Prefix length for %s null address must be equal or larger than %u.",
af_to_ipv4_ipv6(address->family), min_prefixlen);
address->requested_as_null = !in_addr_is_set(address->family, &address->in_addr);
}
address_section_adjust_broadcast(address);
+1
View File
@@ -161,6 +161,7 @@ void link_mark_addresses(Link *link, NetworkConfigSource source);
typedef enum AddressConfParserType {
ADDRESS_ADDRESS,
ADDRESS_PEER,
ADDRESS_BROADCAST,
ADDRESS_LABEL,
ADDRESS_PREFERRED_LIFETIME,
+6 -6
View File
@@ -298,12 +298,12 @@ static int routing_policy_rule_append_json(RoutingPolicyRule *rule, sd_json_vari
return sd_json_variant_append_arraybo(
array,
SD_JSON_BUILD_PAIR_INTEGER("Family", rule->family),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("FromPrefix", &rule->from, rule->family),
SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->from),
"FromPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->from_prefixlen)),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ToPrefix", &rule->to, rule->family),
SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->to),
"ToPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->to_prefixlen)),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("FromPrefix", &rule->from.address, rule->family),
SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->from.address),
"FromPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->from.prefixlen)),
JSON_BUILD_PAIR_IN_ADDR_NON_NULL("ToPrefix", &rule->to.address, rule->family),
SD_JSON_BUILD_PAIR_CONDITION(in_addr_is_set(rule->family, &rule->to.address),
"ToPrefixLength", SD_JSON_BUILD_UNSIGNED(rule->to.prefixlen)),
SD_JSON_BUILD_PAIR_UNSIGNED("Protocol", rule->protocol),
SD_JSON_BUILD_PAIR_STRING("ProtocolString", protocol),
SD_JSON_BUILD_PAIR_UNSIGNED("TOS", rule->tos),
+28 -28
View File
@@ -118,7 +118,7 @@ Network.DefaultRouteOnDevice, config_parse_bool,
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_section, ADDRESS_ADDRESS, 0
Network.Gateway, config_parse_gateway, 0, 0
Network.Gateway, config_parse_route_section, ROUTE_GATEWAY_NETWORK, 0
Network.Domains, config_parse_domains, 0, 0
Network.UseDomains, config_parse_use_domains, 0, offsetof(Network, use_domains)
Network.DNS, config_parse_dns, 0, 0
@@ -157,7 +157,7 @@ Network.KeepConfiguration, config_parse_keep_configuration,
Network.IPv6SendRA, config_parse_router_prefix_delegation, 0, offsetof(Network, router_prefix_delegation)
Network.DHCPPrefixDelegation, config_parse_tristate, 0, offsetof(Network, dhcp_pd)
Address.Address, config_parse_address_section, ADDRESS_ADDRESS, 0
Address.Peer, config_parse_address_section, ADDRESS_ADDRESS, 0
Address.Peer, config_parse_address_section, ADDRESS_PEER, 0
Address.Broadcast, config_parse_address_section, ADDRESS_BROADCAST, 0
Address.Label, config_parse_address_section, ADDRESS_LABEL, 0
Address.PreferredLifetime, config_parse_address_section, ADDRESS_PREFERRED_LIFETIME, 0
@@ -177,12 +177,12 @@ Neighbor.Address, config_parse_neighbor_section,
Neighbor.LinkLayerAddress, config_parse_neighbor_section, NEIGHBOR_LINK_LAYER_ADDRESS, 0
Neighbor.MACAddress, config_parse_neighbor_section, NEIGHBOR_LINK_LAYER_ADDRESS, 0 /* deprecated */
RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_TOS, 0
RoutingPolicyRule.Priority, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_PRIORITY, 0
RoutingPolicyRule.Priority, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_PRIORITY, 0
RoutingPolicyRule.GoTo, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_GOTO, 0
RoutingPolicyRule.Table, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_TABLE, 0
RoutingPolicyRule.FirewallMark, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_FWMARK, 0
RoutingPolicyRule.From, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_PREFIX, 0
RoutingPolicyRule.To, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_PREFIX, 0
RoutingPolicyRule.From, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_FROM, 0
RoutingPolicyRule.To, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_TO, 0
RoutingPolicyRule.IncomingInterface, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_IIF, 0
RoutingPolicyRule.OutgoingInterface, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_OIF, 0
RoutingPolicyRule.IPProtocol, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_IP_PROTOCOL, 0
@@ -195,29 +195,29 @@ RoutingPolicyRule.User, config_parse_routing_policy_rule,
RoutingPolicyRule.SuppressInterfaceGroup, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_SUPPRESS_IFGROUP, 0
RoutingPolicyRule.SuppressPrefixLength, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_SUPPRESS_PREFIXLEN, 0
RoutingPolicyRule.Type, config_parse_routing_policy_rule, ROUTING_POLICY_RULE_ACTION, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
Route.Metric, config_parse_route_priority, 0, 0
Route.Scope, config_parse_route_scope, 0, 0
Route.PreferredSource, config_parse_preferred_src, 0, 0
Route.Table, config_parse_route_table, 0, 0
Route.GatewayOnLink, config_parse_route_gateway_onlink, 0, 0
Route.GatewayOnlink, config_parse_route_gateway_onlink, 0, 0
Route.IPv6Preference, config_parse_ipv6_route_preference, 0, 0
Route.Protocol, config_parse_route_protocol, 0, 0
Route.Type, config_parse_route_type, 0, 0
Route.MultiPathRoute, config_parse_multipath_route, 0, 0
Route.NextHop, config_parse_route_nexthop, 0, 0
Route.MTUBytes, config_parse_route_metric_mtu, RTAX_MTU, 0
Route.TCPAdvertisedMaximumSegmentSize, config_parse_route_metric_advmss, RTAX_ADVMSS, 0
Route.HopLimit, config_parse_route_metric_hop_limit, RTAX_HOPLIMIT, 0
Route.InitialCongestionWindow, config_parse_route_metric_tcp_window, RTAX_INITCWND, 0
Route.TCPRetransmissionTimeoutSec, config_parse_route_metric_tcp_rto, RTAX_RTO_MIN, 0
Route.InitialAdvertisedReceiveWindow, config_parse_route_metric_tcp_window, RTAX_INITRWND, 0
Route.QuickAck, config_parse_route_metric_boolean, RTAX_QUICKACK, 0
Route.TCPCongestionControlAlgorithm, config_parse_route_metric_tcp_congestion, RTAX_CC_ALGO, 0
Route.FastOpenNoCookie, config_parse_route_metric_boolean, RTAX_FASTOPEN_NO_COOKIE, 0
Route.Gateway, config_parse_route_section, ROUTE_GATEWAY, 0
Route.Destination, config_parse_route_section, ROUTE_DESTINATION, 0
Route.Source, config_parse_route_section, ROUTE_DESTINATION, 0
Route.Metric, config_parse_route_section, ROUTE_PRIORITY, 0
Route.Scope, config_parse_route_section, ROUTE_SCOPE, 0
Route.PreferredSource, config_parse_route_section, ROUTE_PREFERRED_SOURCE, 0
Route.Table, config_parse_route_section, ROUTE_TABLE, 0
Route.GatewayOnLink, config_parse_route_section, ROUTE_GATEWAY_ONLINK, 0
Route.GatewayOnlink, config_parse_route_section, ROUTE_GATEWAY_ONLINK, 0
Route.IPv6Preference, config_parse_route_section, ROUTE_PREFERENCE, 0
Route.Protocol, config_parse_route_section, ROUTE_PROTOCOL, 0
Route.Type, config_parse_route_section, ROUTE_TYPE, 0
Route.MultiPathRoute, config_parse_route_section, ROUTE_MULTIPATH, 0
Route.NextHop, config_parse_route_section, ROUTE_NEXTHOP, 0
Route.MTUBytes, config_parse_route_section, ROUTE_METRIC_MTU, 0
Route.TCPAdvertisedMaximumSegmentSize, config_parse_route_section, ROUTE_METRIC_ADVMSS, 0
Route.HopLimit, config_parse_route_section, ROUTE_METRIC_HOPLIMIT, 0
Route.InitialCongestionWindow, config_parse_route_section, ROUTE_METRIC_INITCWND, 0
Route.TCPRetransmissionTimeoutSec, config_parse_route_section, ROUTE_METRIC_RTO_MIN, 0
Route.InitialAdvertisedReceiveWindow, config_parse_route_section, ROUTE_METRIC_INITRWND, 0
Route.QuickAck, config_parse_route_section, ROUTE_METRIC_QUICKACK, 0
Route.TCPCongestionControlAlgorithm, config_parse_route_section, ROUTE_METRIC_CC_ALGO, 0
Route.FastOpenNoCookie, config_parse_route_section, ROUTE_METRIC_FASTOPEN_NO_COOKIE, 0
Route.TTLPropagate, config_parse_warn_compat, DISABLED_LEGACY, 0
NextHop.Id, config_parse_nexthop_section, NEXTHOP_ID, 0
NextHop.Gateway, config_parse_nexthop_section, NEXTHOP_GATEWAY, 0
+44 -109
View File
@@ -217,7 +217,7 @@ int route_metric_read_netlink_message(RouteMetric *metric, sd_netlink_message *m
return 0;
}
static int config_parse_route_metric_advmss_impl(
static int config_parse_route_metric_advmss(
const char *unit,
const char *filename,
unsigned line,
@@ -236,11 +236,8 @@ static int config_parse_route_metric_advmss_impl(
assert(rvalue);
r = parse_size(rvalue, 1024, &u);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
if (u == 0 || u > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
@@ -252,7 +249,7 @@ static int config_parse_route_metric_advmss_impl(
return 1;
}
static int config_parse_route_metric_hop_limit_impl(
static int config_parse_route_metric_hop_limit(
const char *unit,
const char *filename,
unsigned line,
@@ -270,11 +267,9 @@ static int config_parse_route_metric_hop_limit_impl(
assert(rvalue);
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
if (k == 0 || k > 255) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
@@ -303,11 +298,9 @@ int config_parse_tcp_window(
assert(rvalue);
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
if (k == 0 || k >= 1024) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
@@ -318,7 +311,7 @@ int config_parse_tcp_window(
return 1;
}
static int config_parse_route_metric_tcp_rto_impl(
static int config_parse_route_metric_tcp_rto(
const char *unit,
const char *filename,
unsigned line,
@@ -337,11 +330,8 @@ static int config_parse_route_metric_tcp_rto_impl(
assert(rvalue);
r = parse_sec(rvalue, &usec);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
if (!timestamp_is_set(usec) ||
DIV_ROUND_UP(usec, USEC_PER_MSEC) > UINT32_MAX) {
@@ -354,7 +344,7 @@ static int config_parse_route_metric_tcp_rto_impl(
return 1;
}
static int config_parse_route_metric_boolean_impl(
static int config_parse_route_metric_boolean(
const char *unit,
const char *filename,
unsigned line,
@@ -372,80 +362,14 @@ static int config_parse_route_metric_boolean_impl(
assert(rvalue);
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
*val = r;
return 1;
}
#define DEFINE_CONFIG_PARSE_ROUTE_METRIC(name, parser) \
int config_parse_route_metric_##name( \
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 = ASSERT_PTR(userdata); \
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL; \
uint16_t attr_type = ltype; \
int r; \
\
assert(filename); \
assert(section); \
assert(lvalue); \
assert(rvalue); \
\
r = route_new_static(network, filename, section_line, &route); \
if (r == -ENOMEM) \
return log_oom(); \
if (r < 0) { \
log_syntax(unit, LOG_WARNING, filename, line, r, \
"Failed to allocate route, ignoring assignment: %m"); \
return 0; \
} \
\
if (isempty(rvalue)) { \
route_metric_unset(&route->metric, attr_type); \
TAKE_PTR(route); \
return 0; \
} \
\
uint32_t k; \
r = parser(unit, filename, line, section, section_line, \
lvalue, /* ltype = */ 0, rvalue, \
&k, userdata); \
if (r <= 0) \
return r; \
\
if (route_metric_set_full( \
&route->metric, \
attr_type, \
k, \
/* force = */ true) < 0) \
return log_oom(); \
\
TAKE_PTR(route); \
return 0; \
}
DEFINE_CONFIG_PARSE_ROUTE_METRIC(mtu, config_parse_mtu);
DEFINE_CONFIG_PARSE_ROUTE_METRIC(advmss, config_parse_route_metric_advmss_impl);
DEFINE_CONFIG_PARSE_ROUTE_METRIC(hop_limit, config_parse_route_metric_hop_limit_impl);
DEFINE_CONFIG_PARSE_ROUTE_METRIC(tcp_window, config_parse_tcp_window);
DEFINE_CONFIG_PARSE_ROUTE_METRIC(tcp_rto, config_parse_route_metric_tcp_rto_impl);
DEFINE_CONFIG_PARSE_ROUTE_METRIC(boolean, config_parse_route_metric_boolean_impl);
int config_parse_route_metric_tcp_congestion(
int config_parse_route_metric(
const char *unit,
const char *filename,
unsigned line,
@@ -457,27 +381,38 @@ int config_parse_route_metric_tcp_congestion(
void *data,
void *userdata) {
Network *network = ASSERT_PTR(userdata);
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
static const ConfigSectionParser table[__RTAX_MAX] = {
[RTAX_MTU] = { .parser = config_parse_mtu, .ltype = 0, .offset = 0, },
[RTAX_ADVMSS] = { .parser = config_parse_route_metric_advmss, .ltype = 0, .offset = 0, },
[RTAX_HOPLIMIT] = { .parser = config_parse_route_metric_hop_limit, .ltype = 0, .offset = 0, },
[RTAX_INITCWND] = { .parser = config_parse_tcp_window, .ltype = 0, .offset = 0, },
[RTAX_RTO_MIN] = { .parser = config_parse_route_metric_tcp_rto, .ltype = 0, .offset = 0, },
[RTAX_INITRWND] = { .parser = config_parse_tcp_window, .ltype = 0, .offset = 0, },
[RTAX_QUICKACK] = { .parser = config_parse_route_metric_boolean, .ltype = 0, .offset = 0, },
[RTAX_FASTOPEN_NO_COOKIE] = { .parser = config_parse_route_metric_boolean, .ltype = 0, .offset = 0, },
};
Route *route = ASSERT_PTR(userdata);
int r;
assert(filename);
assert(rvalue);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
if (isempty(rvalue)) {
route_metric_unset(&route->metric, ltype);
TAKE_PTR(route);
return 1;
}
r = config_parse_string(unit, filename, line, section, section_line, lvalue, 0,
rvalue, &route->metric.tcp_congestion_control_algo, userdata);
uint32_t k;
r = config_section_parse(table, ELEMENTSOF(table),
unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k);
if (r <= 0)
return r;
TAKE_PTR(route);
return 0;
if (route_metric_set_full(
&route->metric,
ltype,
k,
/* force = */ true) < 0)
return log_oom();
return 1;
}
+1 -7
View File
@@ -37,11 +37,5 @@ uint32_t route_metric_get(const RouteMetric *metric, uint16_t attr);
int route_metric_set_netlink_message(const RouteMetric *metric, sd_netlink_message *m);
int route_metric_read_netlink_message(RouteMetric *metric, sd_netlink_message *message);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_advmss);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_hop_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_tcp_window);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_tcp_rto);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_boolean);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric_tcp_congestion);
CONFIG_PARSER_PROTOTYPE(config_parse_route_metric);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
+53 -181
View File
@@ -804,6 +804,16 @@ int route_nexthops_read_netlink_message(Route *route, sd_netlink_message *messag
return 0;
}
#define log_route_section(route, fmt, ...) \
({ \
const Route *_route = (route); \
log_section_warning_errno( \
_route ? _route->section : NULL, \
SYNTHETIC_ERRNO(EINVAL), \
fmt " Ignoring [Route] section.", \
##__VA_ARGS__); \
})
int route_section_verify_nexthops(Route *route) {
assert(route);
assert(route->section);
@@ -815,37 +825,30 @@ int route_section_verify_nexthops(Route *route) {
/* When deprecated Gateway=_dhcp is set, then assume gateway family based on other settings. */
switch (route->family) {
case AF_UNSPEC:
log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
"Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".",
route->section->filename, route->section->line);
log_section_warning(route->section,
"Deprecated value \"_dhcp\" is specified for Gateway=. "
"Please use \"_dhcp4\" or \"_ipv6ra\" instead. Assuming \"_dhcp4\".");
route->nexthop.family = route->family = AF_INET;
break;
case AF_INET:
case AF_INET6:
log_warning("%s: Deprecated value \"_dhcp\" is specified for Gateway= in [Route] section from line %u. "
"Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
route->section->filename, route->section->line, route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
log_section_warning(route->section,
"Deprecated value \"_dhcp\" is specified for Gateway=. "
"Assuming \"%s\" based on Destination=, Source=, or PreferredSource= setting.",
route->family == AF_INET ? "_dhcp4" : "_ipv6ra");
route->nexthop.family = route->family;
break;
default:
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Invalid route family. Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "Invalid route family.");
}
if (route->nexthop.family == AF_INET && !FLAGS_SET(route->network->dhcp, ADDRESS_FAMILY_IPV4))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "Gateway=\"_dhcp4\" is specified but DHCPv4 client is disabled.");
if (route->nexthop.family == AF_INET6 && route->network->ndisc == 0)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "Gateway=\"_ipv6ra\" is specified but IPv6AcceptRA= is disabled.");
}
/* When only Gateway= is specified, assume the route family based on the Gateway address. */
@@ -855,20 +858,14 @@ int route_section_verify_nexthops(Route *route) {
if (route->family == AF_UNSPEC) {
assert(route->section);
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Route section without Gateway=, Destination=, Source=, "
"or PreferredSource= field configured. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "Route section without Gateway=, Destination=, Source=, or PreferredSource= field configured.");
}
if (route->gateway_onlink < 0 && in_addr_is_set(route->nexthop.family, &route->nexthop.gw) &&
route->network && ordered_hashmap_isempty(route->network->addresses_by_section)) {
/* If no address is configured, in most cases the gateway cannot be reachable.
* TODO: we may need to improve the condition above. */
log_warning("%s: Gateway= without static address configured. "
"Enabling GatewayOnLink= option.",
route->section->filename);
log_section_warning(route->section, "Gateway= without static address configured. Enabling GatewayOnLink= option.");
route->gateway_onlink = true;
}
@@ -877,45 +874,30 @@ int route_section_verify_nexthops(Route *route) {
if (route->family == AF_INET6) {
if (route->nexthop.family == AF_INET)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: IPv4 gateway is configured for IPv6 route. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "IPv4 gateway is configured for IPv6 route.");
RouteNextHop *nh;
ORDERED_SET_FOREACH(nh, route->nexthops)
if (nh->family == AF_INET)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: IPv4 multipath route is specified for IPv6 route. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "IPv4 multipath route is specified for IPv6 route.");
}
if (route->nexthop_id != 0 &&
(route->gateway_from_dhcp_or_ra ||
in_addr_is_set(route->nexthop.family, &route->nexthop.gw) ||
!ordered_set_isempty(route->nexthops)))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: NextHopId= cannot be specified with Gateway= or MultiPathRoute=. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "NextHopId= cannot be specified with Gateway= or MultiPathRoute=.");
if (route_is_reject(route) &&
(route->gateway_from_dhcp_or_ra ||
in_addr_is_set(route->nexthop.family, &route->nexthop.gw) ||
!ordered_set_isempty(route->nexthops)))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: reject type route cannot be specified with Gateway= or MultiPathRoute=. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "Reject type route cannot be specified with Gateway= or MultiPathRoute=.");
if ((route->gateway_from_dhcp_or_ra ||
in_addr_is_set(route->nexthop.family, &route->nexthop.gw)) &&
!ordered_set_isempty(route->nexthops))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: Gateway= cannot be specified with MultiPathRoute=. "
"Ignoring [Route] section from line %u.",
route->section->filename, route->section->line);
return log_route_section(route, "Gateway= cannot be specified with MultiPathRoute=.");
if (ordered_set_size(route->nexthops) == 1) {
_cleanup_(route_nexthop_freep) RouteNextHop *nh = ordered_set_steal_first(route->nexthops);
@@ -937,124 +919,52 @@ int config_parse_gateway(
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
int ltype, /* 0 : only address is accepted, 1 : also supports an empty string, _dhcp, and friends. */
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Route *route = ASSERT_PTR(userdata);
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
if (streq(section, "Network")) {
/* we are not in an Route section, so use line number instead */
r = route_new_static(network, filename, line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
} else {
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (ltype) {
if (isempty(rvalue)) {
route->gateway_from_dhcp_or_ra = false;
route->nexthop.family = AF_UNSPEC;
route->nexthop.gw = IN_ADDR_NULL;
TAKE_PTR(route);
return 0;
return 1;
}
if (streq(rvalue, "_dhcp")) {
route->gateway_from_dhcp_or_ra = true;
route->nexthop.family = AF_UNSPEC;
route->nexthop.gw = IN_ADDR_NULL;
TAKE_PTR(route);
return 0;
return 1;
}
if (streq(rvalue, "_dhcp4")) {
route->gateway_from_dhcp_or_ra = true;
route->nexthop.family = AF_INET;
route->nexthop.gw = IN_ADDR_NULL;
TAKE_PTR(route);
return 0;
return 1;
}
if (streq(rvalue, "_ipv6ra")) {
route->gateway_from_dhcp_or_ra = true;
route->nexthop.family = AF_INET6;
route->nexthop.gw = IN_ADDR_NULL;
TAKE_PTR(route);
return 0;
return 1;
}
}
assert(rvalue);
r = in_addr_from_string_auto(rvalue, &route->nexthop.family, &route->nexthop.gw);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
route->gateway_from_dhcp_or_ra = false;
TAKE_PTR(route);
return 0;
}
int config_parse_route_gateway_onlink(
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_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = config_parse_tristate(unit, filename, line, section, section_line, lvalue, ltype, rvalue,
&route->gateway_onlink, network);
if (r <= 0)
return r;
TAKE_PTR(route);
return 0;
return 1;
}
int config_parse_route_nexthop(
@@ -1069,45 +979,24 @@ int config_parse_route_nexthop(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
uint32_t id;
uint32_t id, *p = ASSERT_PTR(data);
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (isempty(rvalue)) {
route->nexthop_id = 0;
TAKE_PTR(route);
return 0;
*p = 0;
return 1;
}
r = safe_atou32(rvalue, &id);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse nexthop ID, ignoring assignment: %s", rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
if (id == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid nexthop ID, ignoring assignment: %s", rvalue);
return 0;
}
route->nexthop_id = id;
TAKE_PTR(route);
return 0;
*p = id;
return 1;
}
int config_parse_multipath_route(
@@ -1123,9 +1012,8 @@ int config_parse_multipath_route(
void *userdata) {
_cleanup_(route_nexthop_freep) RouteNextHop *nh = NULL;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
_cleanup_free_ char *word = NULL;
Network *network = userdata;
OrderedSet **nexthops = ASSERT_PTR(data);
const char *p;
char *dev;
int r;
@@ -1136,19 +1024,9 @@ int config_parse_multipath_route(
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (isempty(rvalue)) {
route->nexthops = ordered_set_free(route->nexthops);
TAKE_PTR(route);
return 0;
*nexthops = ordered_set_free(*nexthops);
return 1;
}
nh = new0(RouteNextHop, 1);
@@ -1157,13 +1035,8 @@ int config_parse_multipath_route(
p = rvalue;
r = extract_first_word(&p, &word, NULL, 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route option, ignoring assignment: %s", rvalue);
return 0;
}
if (r <= 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
dev = strchr(word, '@');
if (dev) {
@@ -1211,7 +1084,7 @@ int config_parse_multipath_route(
nh->weight--;
}
r = ordered_set_ensure_put(&route->nexthops, &route_nexthop_hash_ops, nh);
r = ordered_set_ensure_put(nexthops, &route_nexthop_hash_ops, nh);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -1221,6 +1094,5 @@ int config_parse_multipath_route(
}
TAKE_PTR(nh);
TAKE_PTR(route);
return 0;
return 1;
}
-1
View File
@@ -52,6 +52,5 @@ int route_nexthops_read_netlink_message(Route *route, sd_netlink_message *messag
int route_section_verify_nexthops(Route *route);
CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
CONFIG_PARSER_PROTOTYPE(config_parse_route_gateway_onlink);
CONFIG_PARSER_PROTOTYPE(config_parse_route_nexthop);
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
+108 -167
View File
@@ -1628,7 +1628,7 @@ int network_add_default_route_on_device(Network *network) {
return 0;
}
int config_parse_preferred_src(
static int config_parse_preferred_src(
const char *unit,
const char *filename,
unsigned line,
@@ -1640,40 +1640,22 @@ int config_parse_preferred_src(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Route *route = ASSERT_PTR(userdata);
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (route->family == AF_UNSPEC)
r = in_addr_from_string_auto(rvalue, &route->family, &route->prefsrc);
else
r = in_addr_from_string(route->family, rvalue, &route->prefsrc);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
TAKE_PTR(route);
return 0;
return 1;
}
int config_parse_destination(
static int config_parse_route_destination(
const char *unit,
const char *filename,
unsigned line,
@@ -1685,26 +1667,13 @@ int config_parse_destination(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Route *route = ASSERT_PTR(userdata);
union in_addr_union *buffer;
unsigned char *prefixlen;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (streq(lvalue, "Destination")) {
buffer = &route->dst;
@@ -1719,19 +1688,14 @@ int config_parse_destination(
r = in_addr_prefix_from_string_auto(rvalue, &route->family, buffer, prefixlen);
else
r = in_addr_prefix_from_string(rvalue, route->family, buffer, prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
(void) in_addr_mask(route->family, buffer, *prefixlen);
TAKE_PTR(route);
return 0;
return 1;
}
int config_parse_route_priority(
static int config_parse_route_priority(
const char *unit,
const char *filename,
unsigned line,
@@ -1743,38 +1707,20 @@ int config_parse_route_priority(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Route *route = ASSERT_PTR(userdata);
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = safe_atou32(rvalue, &route->priority);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
route->priority_set = true;
TAKE_PTR(route);
return 0;
return 1;
}
int config_parse_route_scope(
static int config_parse_route_scope(
const char *unit,
const char *filename,
unsigned line,
@@ -1786,38 +1732,21 @@ int config_parse_route_scope(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Route *route = ASSERT_PTR(userdata);
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = route_scope_from_string(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Unknown route scope: %s", rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
route->scope = r;
route->scope_set = true;
TAKE_PTR(route);
return 0;
return 1;
}
int config_parse_route_table(
static int config_parse_route_table(
const char *unit,
const char *filename,
unsigned line,
@@ -1829,38 +1758,21 @@ int config_parse_route_table(
void *data,
void *userdata) {
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
Route *route = ASSERT_PTR(userdata);
Manager *manager = ASSERT_PTR(ASSERT_PTR(route->network)->manager);
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = manager_get_route_table_from_string(network->manager, rvalue, &route->table);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route table \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
r = manager_get_route_table_from_string(manager, rvalue, &route->table);
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
route->table_set = true;
TAKE_PTR(route);
return 0;
return 1;
}
int config_parse_ipv6_route_preference(
static int config_parse_route_preference(
const char *unit,
const char *filename,
unsigned line,
@@ -1872,18 +1784,9 @@ int config_parse_ipv6_route_preference(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int r;
Route *route = ASSERT_PTR(userdata);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
assert(rvalue);
if (streq(rvalue, "low"))
route->pref = SD_NDISC_PREFERENCE_LOW;
@@ -1891,17 +1794,14 @@ int config_parse_ipv6_route_preference(
route->pref = SD_NDISC_PREFERENCE_MEDIUM;
else if (streq(rvalue, "high"))
route->pref = SD_NDISC_PREFERENCE_HIGH;
else {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route preference: %s", rvalue);
return 0;
}
else
return log_syntax_parse_error(unit, filename, line, 0, lvalue, rvalue);
route->pref_set = true;
TAKE_PTR(route);
return 0;
return 1;
}
int config_parse_route_protocol(
static int config_parse_route_protocol(
const char *unit,
const char *filename,
unsigned line,
@@ -1913,33 +1813,20 @@ int config_parse_route_protocol(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
unsigned char *p = ASSERT_PTR(data);
int r;
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
assert(rvalue);
r = route_protocol_from_string(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse route protocol \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
route->protocol = r;
TAKE_PTR(route);
return 0;
*p = (unsigned char) r;
return 1;
}
int config_parse_route_type(
static int config_parse_route_type(
const char *unit,
const char *filename,
unsigned line,
@@ -1951,11 +1838,69 @@ int config_parse_route_type(
void *data,
void *userdata) {
Network *network = userdata;
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
int t, r;
unsigned char *p = ASSERT_PTR(data);
int r;
r = route_new_static(network, filename, section_line, &route);
assert(rvalue);
r = route_type_from_string(rvalue);
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
*p = (unsigned char) r;
return 1;
}
int config_parse_route_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[_ROUTE_CONF_PARSER_MAX] = {
[ROUTE_DESTINATION] = { .parser = config_parse_route_destination, .ltype = 0, .offset = 0, },
[ROUTE_PREFERRED_SOURCE] = { .parser = config_parse_preferred_src, .ltype = 0, .offset = 0, },
[ROUTE_PRIORITY] = { .parser = config_parse_route_priority, .ltype = 0, .offset = 0, },
[ROUTE_SCOPE] = { .parser = config_parse_route_scope, .ltype = 0, .offset = 0, },
[ROUTE_TABLE] = { .parser = config_parse_route_table, .ltype = 0, .offset = 0, },
[ROUTE_PREFERENCE] = { .parser = config_parse_route_preference, .ltype = 0, .offset = 0, },
[ROUTE_PROTOCOL] = { .parser = config_parse_route_protocol, .ltype = 0, .offset = offsetof(Route, protocol), },
[ROUTE_TYPE] = { .parser = config_parse_route_type, .ltype = 0, .offset = offsetof(Route, type), },
[ROUTE_GATEWAY_NETWORK] = { .parser = config_parse_gateway, .ltype = 0, .offset = 0, },
[ROUTE_GATEWAY] = { .parser = config_parse_gateway, .ltype = 1, .offset = 0, },
[ROUTE_GATEWAY_ONLINK] = { .parser = config_parse_tristate, .ltype = 0, .offset = offsetof(Route, gateway_onlink), },
[ROUTE_MULTIPATH] = { .parser = config_parse_multipath_route, .ltype = 0, .offset = offsetof(Route, nexthops), },
[ROUTE_NEXTHOP] = { .parser = config_parse_route_nexthop, .ltype = 0, .offset = offsetof(Route, nexthop_id), },
[ROUTE_METRIC_MTU] = { .parser = config_parse_route_metric, .ltype = RTAX_MTU, .offset = 0, },
[ROUTE_METRIC_ADVMSS] = { .parser = config_parse_route_metric, .ltype = RTAX_ADVMSS, .offset = 0, },
[ROUTE_METRIC_HOPLIMIT] = { .parser = config_parse_route_metric, .ltype = RTAX_HOPLIMIT, .offset = 0, },
[ROUTE_METRIC_INITCWND] = { .parser = config_parse_route_metric, .ltype = RTAX_INITCWND, .offset = 0, },
[ROUTE_METRIC_RTO_MIN] = { .parser = config_parse_route_metric, .ltype = RTAX_RTO_MIN, .offset = 0, },
[ROUTE_METRIC_INITRWND] = { .parser = config_parse_route_metric, .ltype = RTAX_INITRWND, .offset = 0, },
[ROUTE_METRIC_QUICKACK] = { .parser = config_parse_route_metric, .ltype = RTAX_QUICKACK, .offset = 0, },
[ROUTE_METRIC_CC_ALGO] = { .parser = config_parse_string, .ltype = 0, .offset = offsetof(Route, metric.tcp_congestion_control_algo), },
[ROUTE_METRIC_FASTOPEN_NO_COOKIE] = { .parser = config_parse_route_metric, .ltype = RTAX_FASTOPEN_NO_COOKIE, .offset = 0, },
};
_cleanup_(route_unref_or_set_invalidp) Route *route = NULL;
Network *network = ASSERT_PTR(userdata);
int r;
assert(filename);
if (streq(section, "Network")) {
assert(streq_ptr(lvalue, "Gateway"));
/* we are not in an Route section, so use line number instead */
r = route_new_static(network, filename, line, &route);
} else
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -1964,14 +1909,10 @@ int config_parse_route_type(
return 0;
}
t = route_type_from_string(rvalue);
if (t < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
route->type = (unsigned char) t;
r = config_section_parse(table, ELEMENTSOF(table),
unit, filename, line, section, section_line, lvalue, ltype, rvalue, route);
if (r <= 0)
return r;
TAKE_PTR(route);
return 0;
@@ -2019,7 +1960,7 @@ int route_section_verify(Route *route) {
/* IPv6 route */
if (route->family == AF_INET6) {
if (route->scope != RT_SCOPE_UNIVERSE) {
log_warning("%s: Scope= is specified for IPv6 route. It will be ignored.", route->section->filename);
log_section_warning(route->section, "Scope= is specified for IPv6 route. It will be ignored.");
route->scope = RT_SCOPE_UNIVERSE;
}
+28 -8
View File
@@ -126,11 +126,31 @@ int route_section_verify(Route *route);
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(Route, route);
void manager_mark_routes(Manager *manager, Link *link, NetworkConfigSource source);
CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
CONFIG_PARSER_PROTOTYPE(config_parse_destination);
CONFIG_PARSER_PROTOTYPE(config_parse_route_priority);
CONFIG_PARSER_PROTOTYPE(config_parse_route_scope);
CONFIG_PARSER_PROTOTYPE(config_parse_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_route_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol);
CONFIG_PARSER_PROTOTYPE(config_parse_route_type);
typedef enum RouteConfParserType {
ROUTE_DESTINATION,
ROUTE_PREFERRED_SOURCE,
ROUTE_PRIORITY,
ROUTE_SCOPE,
ROUTE_TABLE,
ROUTE_PREFERENCE,
ROUTE_PROTOCOL,
ROUTE_TYPE,
ROUTE_GATEWAY_NETWORK,
ROUTE_GATEWAY,
ROUTE_GATEWAY_ONLINK,
ROUTE_MULTIPATH,
ROUTE_NEXTHOP,
ROUTE_METRIC_MTU,
ROUTE_METRIC_ADVMSS,
ROUTE_METRIC_HOPLIMIT,
ROUTE_METRIC_INITCWND,
ROUTE_METRIC_RTO_MIN,
ROUTE_METRIC_INITRWND,
ROUTE_METRIC_QUICKACK,
ROUTE_METRIC_CC_ALGO,
ROUTE_METRIC_FASTOPEN_NO_COOKIE,
_ROUTE_CONF_PARSER_MAX,
_ROUTE_CONF_PARSER_INVALID = -EINVAL,
} RouteConfParserType;
CONFIG_PARSER_PROTOTYPE(config_parse_route_section);
+28 -61
View File
@@ -215,12 +215,12 @@ static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct
siphash24_compress_typesafe(rule->dport, state);
/* See fib4_rule_compare() in net/ipv4/fib_rules.c, and fib6_rule_compare() in net/ipv6/fib6_rules.c. */
siphash24_compress_typesafe(rule->from_prefixlen, state);
siphash24_compress_typesafe(rule->to_prefixlen, state);
siphash24_compress_typesafe(rule->from.prefixlen, state);
siphash24_compress_typesafe(rule->to.prefixlen, state);
siphash24_compress_typesafe(rule->tos, state);
siphash24_compress_typesafe(rule->realms, state);
in_addr_hash_func(&rule->from, rule->family, state);
in_addr_hash_func(&rule->to, rule->family, state);
in_addr_hash_func(&rule->from.address, rule->family, state);
in_addr_hash_func(&rule->to.address, rule->family, state);
}
static int routing_policy_rule_compare_func_full(const RoutingPolicyRule *a, const RoutingPolicyRule *b, bool all) {
@@ -301,11 +301,11 @@ static int routing_policy_rule_compare_func_full(const RoutingPolicyRule *a, con
if (r != 0)
return r;
r = CMP(a->from_prefixlen, b->from_prefixlen);
r = CMP(a->from.prefixlen, b->from.prefixlen);
if (r != 0)
return r;
r = CMP(a->to_prefixlen, b->to_prefixlen);
r = CMP(a->to.prefixlen, b->to.prefixlen);
if (r != 0)
return r;
@@ -318,11 +318,11 @@ static int routing_policy_rule_compare_func_full(const RoutingPolicyRule *a, con
return r;
if (all) {
r = memcmp(&a->from, &b->from, FAMILY_ADDRESS_SIZE(a->family));
r = memcmp(&a->from.address, &b->from.address, FAMILY_ADDRESS_SIZE(a->family));
if (r != 0)
return r;
r = memcmp(&a->to, &b->to, FAMILY_ADDRESS_SIZE(a->family));
r = memcmp(&a->to.address, &b->to.address, FAMILY_ADDRESS_SIZE(a->family));
if (r != 0)
return r;
}
@@ -544,8 +544,8 @@ static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, const c
"%s %s routing policy rule (%s): priority: %"PRIu32", %s -> %s, iif: %s, oif: %s, table: %s",
str, strna(network_config_source_to_string(rule->source)), strna(state),
rule->priority,
IN_ADDR_PREFIX_TO_STRING(rule->family, &rule->from, rule->from_prefixlen),
IN_ADDR_PREFIX_TO_STRING(rule->family, &rule->to, rule->to_prefixlen),
IN_ADDR_PREFIX_TO_STRING(rule->family, &rule->from.address, rule->from.prefixlen),
IN_ADDR_PREFIX_TO_STRING(rule->family, &rule->to.address, rule->to.prefixlen),
strna(rule->iif), strna(rule->oif), strna(table));
}
@@ -555,22 +555,22 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule
assert(rule);
assert(m);
if (rule->from_prefixlen > 0) {
r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
if (rule->from.prefixlen > 0) {
r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from.address);
if (r < 0)
return r;
r = sd_rtnl_message_routing_policy_rule_set_src_prefixlen(m, rule->from_prefixlen);
r = sd_rtnl_message_routing_policy_rule_set_src_prefixlen(m, rule->from.prefixlen);
if (r < 0)
return r;
}
if (rule->to_prefixlen > 0) {
r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to);
if (rule->to.prefixlen > 0) {
r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to.address);
if (r < 0)
return r;
r = sd_rtnl_message_routing_policy_rule_set_dst_prefixlen(m, rule->to_prefixlen);
r = sd_rtnl_message_routing_policy_rule_set_dst_prefixlen(m, rule->to.prefixlen);
if (r < 0)
return r;
}
@@ -1100,24 +1100,24 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
return 0;
}
r = netlink_message_read_in_addr_union(message, FRA_SRC, tmp->family, &tmp->from);
r = netlink_message_read_in_addr_union(message, FRA_SRC, tmp->family, &tmp->from.address);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
return 0;
} else if (r >= 0) {
r = sd_rtnl_message_routing_policy_rule_get_src_prefixlen(message, &tmp->from_prefixlen);
r = sd_rtnl_message_routing_policy_rule_get_src_prefixlen(message, &tmp->from.prefixlen);
if (r < 0) {
log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
return 0;
}
}
r = netlink_message_read_in_addr_union(message, FRA_DST, tmp->family, &tmp->to);
r = netlink_message_read_in_addr_union(message, FRA_DST, tmp->family, &tmp->to.address);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
return 0;
} else if (r >= 0) {
r = sd_rtnl_message_routing_policy_rule_get_dst_prefixlen(message, &tmp->to_prefixlen);
r = sd_rtnl_message_routing_policy_rule_get_dst_prefixlen(message, &tmp->to.prefixlen);
if (r < 0) {
log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
return 0;
@@ -1469,46 +1469,6 @@ static int config_parse_routing_policy_rule_fwmark(
return 1;
}
static int config_parse_routing_policy_rule_prefix(
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) {
RoutingPolicyRule *rule = ASSERT_PTR(userdata);
union in_addr_union *buffer;
uint8_t *prefixlen;
int r;
assert(rvalue);
if (streq_ptr(lvalue, "To")) {
buffer = &rule->to;
prefixlen = &rule->to_prefixlen;
} else if (streq_ptr(lvalue, "From")) {
buffer = &rule->from;
prefixlen = &rule->from_prefixlen;
} else
assert_not_reached();
if (rule->family == AF_UNSPEC)
r = in_addr_prefix_from_string_auto(rvalue, &rule->family, buffer, prefixlen);
else
r = in_addr_prefix_from_string(rvalue, rule->family, buffer, prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue);
return 0;
}
return 1;
}
static int config_parse_routing_policy_rule_port_range(
const char *unit,
const char *filename,
@@ -1662,7 +1622,8 @@ int config_parse_routing_policy_rule(
[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_FROM] = { .parser = config_parse_in_addr_prefix, .ltype = 0, .offset = offsetof(RoutingPolicyRule, from), },
[ROUTING_POLICY_RULE_TO] = { .parser = config_parse_in_addr_prefix, .ltype = 0, .offset = offsetof(RoutingPolicyRule, to), },
[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), },
@@ -1707,6 +1668,12 @@ static int routing_policy_rule_section_verify(RoutingPolicyRule *rule) {
if (section_is_invalid(rule->section))
return -EINVAL;
rule->family = rule->from.family;
if (rule->family == AF_UNSPEC)
rule->family = rule->to.family;
else if (rule->to.family != AF_UNSPEC && rule->to.family != rule->family)
return log_rule_section(rule, "From= and To= settings for routing policy rule contradict each other.");
if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) ||
(rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)))
return log_rule_section(rule, "Address family specified by Family= conflicts with To= and/or From=.");
+7 -8
View File
@@ -6,7 +6,7 @@
#include <stdbool.h>
#include "conf-parser.h"
#include "in-addr-util.h"
#include "in-addr-prefix-util.h"
#include "networkd-util.h"
typedef struct Link Link;
@@ -23,17 +23,15 @@ typedef struct RoutingPolicyRule {
unsigned n_ref;
/* struct fib_rule_hdr */
AddressFamily address_family; /* Specified by Family= */
int family; /* Automatically determined by From= or To= */
uint8_t to_prefixlen;
uint8_t from_prefixlen;
AddressFamily address_family; /* Used when parsing Family= */
int family; /* Automatically determined by From=, To=, and Family= */
uint8_t tos;
uint8_t action;
uint32_t flags;
/* attributes */
union in_addr_union to; /* FRA_DST */
union in_addr_union from; /* FRA_SRC */
struct in_addr_prefix to; /* FRA_DST */
struct in_addr_prefix from; /* FRA_SRC */
char *iif; /* FRA_IIFNAME */
uint32_t priority_goto; /* FRA_GOTO */
bool priority_set;
@@ -88,7 +86,8 @@ typedef enum RoutingPolicyRuleConfParserType {
ROUTING_POLICY_RULE_L3MDEV,
ROUTING_POLICY_RULE_SPORT,
ROUTING_POLICY_RULE_DPORT,
ROUTING_POLICY_RULE_PREFIX,
ROUTING_POLICY_RULE_FROM,
ROUTING_POLICY_RULE_TO,
ROUTING_POLICY_RULE_PRIORITY,
ROUTING_POLICY_RULE_SUPPRESS_IFGROUP,
ROUTING_POLICY_RULE_SUPPRESS_PREFIXLEN,
+38 -1
View File
@@ -24,7 +24,7 @@
#include "hash-funcs.h"
#include "hostname-util.h"
#include "id128-util.h"
#include "in-addr-util.h"
#include "in-addr-prefix-util.h"
#include "ip-protocol-list.h"
#include "log.h"
#include "macro.h"
@@ -2002,6 +2002,43 @@ int config_parse_in_addr_data(
return 1;
}
int config_parse_in_addr_prefix(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype, /* takes boolean, whether we warn about missing prefixlen */
const char *rvalue,
void *data,
void *userdata) {
struct in_addr_prefix *p = ASSERT_PTR(data);
int r;
assert(filename);
assert(lvalue);
if (isempty(rvalue)) {
*p = (struct in_addr_prefix) {};
return 1;
}
r = in_addr_prefix_from_string_auto_full(rvalue, ltype ? PREFIXLEN_REFUSE : PREFIXLEN_FULL, &p->family, &p->address, &p->prefixlen);
if (r == -ENOANO) {
r = in_addr_prefix_from_string_auto(rvalue, &p->family, &p->address, &p->prefixlen);
if (r >= 0)
log_syntax(unit, LOG_WARNING, filename, line, r,
"%s=%s is specified without prefix length. Assuming the prefix length is %u. "
"Please specify the prefix length explicitly.", lvalue, rvalue, p->prefixlen);
}
if (r < 0)
return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue);
return 1;
}
int config_parse_unsigned_bounded(
const char *unit,
const char *filename,
+1
View File
@@ -305,6 +305,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ether_addr);
CONFIG_PARSER_PROTOTYPE(config_parse_ether_addrs);
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_non_null);
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_data);
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_prefix);
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
CONFIG_PARSER_PROTOTYPE(config_parse_pid);
+1 -1
View File
@@ -36,7 +36,7 @@ static void test_in_addr_prefix_from_string_one(
assert_se(in_addr_equal(family, &q, u));
assert_se(l == prefixlen);
r = in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_REFUSE, &f, &q, &l);
r = in_addr_prefix_from_string_auto_full(p, PREFIXLEN_REFUSE, &f, &q, &l);
assert_se(r == ret_refuse);
if (r >= 0) {