diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index c077f0aa7d..fa28d79dcb 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -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, diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index 9cd0aca9a4..2efe9aec01 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -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) { diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 7807d83c5a..deffa4dead 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -3,8 +3,10 @@ #include #include +#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); diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index 083a939e1f..f799d59460 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -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, diff --git a/src/network/networkd-json.c b/src/network/networkd-json.c index d1a7bd586c..452df9a17f 100644 --- a/src/network/networkd-json.c +++ b/src/network/networkd-json.c @@ -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), diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 1f9e6eafc0..b223ccaccd 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -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 diff --git a/src/network/networkd-route-metric.c b/src/network/networkd-route-metric.c index 31a2bdea24..409e403ff1 100644 --- a/src/network/networkd-route-metric.c +++ b/src/network/networkd-route-metric.c @@ -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; } diff --git a/src/network/networkd-route-metric.h b/src/network/networkd-route-metric.h index 212f9079cb..c85eef58b3 100644 --- a/src/network/networkd-route-metric.h +++ b/src/network/networkd-route-metric.h @@ -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); diff --git a/src/network/networkd-route-nexthop.c b/src/network/networkd-route-nexthop.c index ee837d73fa..bf0271807b 100644 --- a/src/network/networkd-route-nexthop.c +++ b/src/network/networkd-route-nexthop.c @@ -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; } diff --git a/src/network/networkd-route-nexthop.h b/src/network/networkd-route-nexthop.h index f9a147839d..f3f1d7e7a0 100644 --- a/src/network/networkd-route-nexthop.h +++ b/src/network/networkd-route-nexthop.h @@ -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); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 859a3cf4cd..3be737ae49 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -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; } diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 744cad2f1a..504252187a 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -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); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c index c03493b7e0..ec050e3a2d 100644 --- a/src/network/networkd-routing-policy-rule.c +++ b/src/network/networkd-routing-policy-rule.c @@ -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=."); diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h index 443df39dd2..3b106c11d3 100644 --- a/src/network/networkd-routing-policy-rule.h +++ b/src/network/networkd-routing-policy-rule.h @@ -6,7 +6,7 @@ #include #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, diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 8b32f2a9bb..8c5a4a7013 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -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, diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 8767902a50..1599738f84 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -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); diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c index fcc9a0a72d..769cb8f083 100644 --- a/src/test/test-in-addr-util.c +++ b/src/test/test-in-addr-util.c @@ -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) {