Merge pull request #34700 from yuwata/network-conf-parser
network: several cleanups for conf parsers
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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=.");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user