Merge pull request #30803 from yuwata/network-route-parser-trivial-cleanups

network/route: trivial cleanups for conf parsers
This commit is contained in:
Yu Watanabe
2024-01-07 05:26:06 +09:00
committed by GitHub
8 changed files with 694 additions and 628 deletions
+3 -1
View File
@@ -67,8 +67,10 @@ sources = files(
'networkd-nexthop.c',
'networkd-queue.c',
'networkd-radv.c',
'networkd-route-util.c',
'networkd-route.c',
'networkd-route-metric.c',
'networkd-route-nexthop.c',
'networkd-route-util.c',
'networkd-routing-policy-rule.c',
'networkd-setlink.c',
'networkd-speed-meter.c',
+12 -12
View File
@@ -192,23 +192,23 @@ Route.Metric, config_parse_route_priority,
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.MTUBytes, config_parse_route_mtu, AF_UNSPEC, 0
Route.GatewayOnLink, config_parse_route_boolean, 0, 0
Route.GatewayOnlink, config_parse_route_boolean, 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.TCPRetransmissionTimeoutSec, config_parse_route_tcp_rto, 0, 0
Route.HopLimit, config_parse_route_hop_limit, 0, 0
Route.InitialCongestionWindow, config_parse_route_tcp_window, 0, 0
Route.InitialAdvertisedReceiveWindow, config_parse_route_tcp_window, 0, 0
Route.TCPAdvertisedMaximumSegmentSize, config_parse_tcp_advmss, 0, 0
Route.TCPCongestionControlAlgorithm, config_parse_tcp_congestion, 0, 0
Route.QuickAck, config_parse_route_boolean, 0, 0
Route.FastOpenNoCookie, config_parse_route_boolean, 0, 0
Route.TTLPropagate, config_parse_warn_compat, DISABLED_LEGACY, 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.TTLPropagate, config_parse_warn_compat, DISABLED_LEGACY, 0
NextHop.Id, config_parse_nexthop_id, 0, 0
NextHop.Gateway, config_parse_nexthop_gateway, 0, 0
NextHop.Family, config_parse_nexthop_family, 0, 0
+384
View File
@@ -0,0 +1,384 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "networkd-route.h"
#include "networkd-route-metric.h"
#include "parse-util.h"
#include "string-util.h"
int config_parse_route_metric_mtu(
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_free_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_mtu(unit, filename, line, section, section_line, lvalue, AF_UNSPEC, rvalue, &route->mtu, userdata);
if (r <= 0)
return r;
TAKE_PTR(route);
return 0;
}
int config_parse_route_metric_advmss(
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) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
uint64_t u;
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->advmss = 0;
TAKE_PTR(route);
return 0;
}
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 (u == 0 || u > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
route->advmss = u;
TAKE_PTR(route);
return 0;
}
int config_parse_route_metric_hop_limit(
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) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
uint32_t k;
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->hop_limit = 0;
TAKE_PTR(route);
return 0;
}
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 (k == 0 || k > 255) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
route->hop_limit = k;
TAKE_PTR(route);
return 0;
}
int config_parse_tcp_window(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint32_t *window = ASSERT_PTR(data);
uint32_t k;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
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 (k == 0 || k >= 1024) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
*window = k;
return 0;
}
int config_parse_route_metric_tcp_window(
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) {
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
uint32_t *d;
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, "InitialCongestionWindow"))
d = &route->initcwnd;
else if (streq(lvalue, "InitialAdvertisedReceiveWindow"))
d = &route->initrwnd;
else
assert_not_reached();
r = config_parse_tcp_window(unit, filename, line, section, section_line, lvalue, ltype, rvalue, d, userdata);
if (r < 0)
return r;
TAKE_PTR(route);
return 0;
}
int config_parse_route_metric_tcp_rto(
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_free_or_set_invalidp) Route *route = NULL;
usec_t usec;
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 = 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 (!timestamp_is_set(usec) ||
DIV_ROUND_UP(usec, USEC_PER_MSEC) > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
route->tcp_rto_usec = usec;
TAKE_PTR(route);
return 0;
}
int config_parse_route_metric_boolean(
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_free_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 = 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 (streq(lvalue, "QuickAck"))
route->quickack = r;
else if (streq(lvalue, "FastOpenNoCookie"))
route->fast_open_no_cookie = r;
else
assert_not_reached();
TAKE_PTR(route);
return 0;
}
int config_parse_route_metric_tcp_congestion(
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_free_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_string(unit, filename, line, section, section_line, lvalue, 0,
rvalue, &route->tcp_congestion_control_algo, userdata);
if (r < 0)
return r;
TAKE_PTR(route);
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser.h"
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_tcp_window);
+182
View File
@@ -0,0 +1,182 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/nexthop.h>
#include "alloc-util.h"
#include "extract-word.h"
#include "netlink-util.h"
#include "networkd-route.h"
#include "networkd-route-nexthop.h"
#include "parse-util.h"
#include "string-util.h"
int config_parse_route_nexthop(
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_free_or_set_invalidp) Route *route = NULL;
uint32_t id;
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;
}
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 (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;
}
int config_parse_multipath_route(
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) {
_cleanup_(multipath_route_freep) MultipathRoute *m = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
_cleanup_free_ char *word = NULL;
Network *network = userdata;
union in_addr_union a;
int family, r;
const char *p;
char *dev;
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->multipath_routes = ordered_set_free_with_destructor(route->multipath_routes, multipath_route_free);
TAKE_PTR(route);
return 0;
}
m = new0(MultipathRoute, 1);
if (!m)
return log_oom();
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;
}
dev = strchr(word, '@');
if (dev) {
*dev++ = '\0';
r = parse_ifindex(dev);
if (r > 0)
m->ifindex = r;
else {
if (!ifname_valid_full(dev, IFNAME_VALID_ALTERNATIVE)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid interface name '%s' in %s=, ignoring: %s", dev, lvalue, rvalue);
return 0;
}
m->ifname = strdup(dev);
if (!m->ifname)
return log_oom();
}
}
r = in_addr_from_string_auto(word, &family, &a);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
return 0;
}
m->gateway.address = a;
m->gateway.family = family;
if (!isempty(p)) {
r = safe_atou32(p, &m->weight);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
/* ip command takes weight in the range 1…255, while kernel takes the value in the
* range 0…254. MultiPathRoute= setting also takes weight in the same range which ip
* command uses, then networkd decreases by one and stores it to match the range which
* kernel uses. */
if (m->weight == 0 || m->weight > 256) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
m->weight--;
}
r = ordered_set_ensure_put(&route->multipath_routes, NULL, m);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to store multipath route, ignoring assignment: %m");
return 0;
}
TAKE_PTR(m);
TAKE_PTR(route);
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser.h"
CONFIG_PARSER_PROTOTYPE(config_parse_route_nexthop);
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
+89 -605
View File
@@ -45,7 +45,7 @@ int route_new(Route **ret) {
return 0;
}
static int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) {
_cleanup_(config_section_freep) ConfigSection *n = NULL;
_cleanup_(route_freep) Route *route = NULL;
int r;
@@ -1930,7 +1930,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
}
int network_add_ipv4ll_route(Network *network) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
unsigned section_line;
int r;
@@ -1944,28 +1944,28 @@ int network_add_ipv4ll_route(Network *network) {
return r;
/* IPv4LLRoute= is in [Network] section. */
r = route_new_static(network, network->filename, section_line, &n);
r = route_new_static(network, network->filename, section_line, &route);
if (r < 0)
return r;
r = in_addr_from_string(AF_INET, "169.254.0.0", &n->dst);
r = in_addr_from_string(AF_INET, "169.254.0.0", &route->dst);
if (r < 0)
return r;
n->family = AF_INET;
n->dst_prefixlen = 16;
n->scope = RT_SCOPE_LINK;
n->scope_set = true;
n->table_set = true;
n->priority = IPV4LL_ROUTE_METRIC;
n->protocol = RTPROT_STATIC;
route->family = AF_INET;
route->dst_prefixlen = 16;
route->scope = RT_SCOPE_LINK;
route->scope_set = true;
route->table_set = true;
route->priority = IPV4LL_ROUTE_METRIC;
route->protocol = RTPROT_STATIC;
TAKE_PTR(n);
TAKE_PTR(route);
return 0;
}
int network_add_default_route_on_device(Network *network) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
unsigned section_line;
int r;
@@ -1979,16 +1979,16 @@ int network_add_default_route_on_device(Network *network) {
return r;
/* DefaultRouteOnDevice= is in [Network] section. */
r = route_new_static(network, network->filename, section_line, &n);
r = route_new_static(network, network->filename, section_line, &route);
if (r < 0)
return r;
n->family = AF_INET;
n->scope = RT_SCOPE_LINK;
n->scope_set = true;
n->protocol = RTPROT_STATIC;
route->family = AF_INET;
route->scope = RT_SCOPE_LINK;
route->scope_set = true;
route->protocol = RTPROT_STATIC;
TAKE_PTR(n);
TAKE_PTR(route);
return 0;
}
@@ -2005,7 +2005,7 @@ int config_parse_gateway(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@@ -2016,7 +2016,7 @@ int config_parse_gateway(
if (streq(section, "Network")) {
/* we are not in an Route section, so use line number instead */
r = route_new_static(network, filename, line, &n);
r = route_new_static(network, filename, line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2025,7 +2025,7 @@ int config_parse_gateway(
return 0;
}
} else {
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2035,43 +2035,43 @@ int config_parse_gateway(
}
if (isempty(rvalue)) {
n->gateway_from_dhcp_or_ra = false;
n->gw_family = AF_UNSPEC;
n->gw = IN_ADDR_NULL;
TAKE_PTR(n);
route->gateway_from_dhcp_or_ra = false;
route->gw_family = AF_UNSPEC;
route->gw = IN_ADDR_NULL;
TAKE_PTR(route);
return 0;
}
if (streq(rvalue, "_dhcp")) {
n->gateway_from_dhcp_or_ra = true;
TAKE_PTR(n);
route->gateway_from_dhcp_or_ra = true;
TAKE_PTR(route);
return 0;
}
if (streq(rvalue, "_dhcp4")) {
n->gw_family = AF_INET;
n->gateway_from_dhcp_or_ra = true;
TAKE_PTR(n);
route->gw_family = AF_INET;
route->gateway_from_dhcp_or_ra = true;
TAKE_PTR(route);
return 0;
}
if (streq(rvalue, "_ipv6ra")) {
n->gw_family = AF_INET6;
n->gateway_from_dhcp_or_ra = true;
TAKE_PTR(n);
route->gw_family = AF_INET6;
route->gateway_from_dhcp_or_ra = true;
TAKE_PTR(route);
return 0;
}
}
r = in_addr_from_string_auto(rvalue, &n->gw_family, &n->gw);
r = in_addr_from_string_auto(rvalue, &route->gw_family, &route->gw);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
n->gateway_from_dhcp_or_ra = false;
TAKE_PTR(n);
route->gateway_from_dhcp_or_ra = false;
TAKE_PTR(route);
return 0;
}
@@ -2088,7 +2088,7 @@ int config_parse_preferred_src(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@@ -2097,7 +2097,7 @@ int config_parse_preferred_src(
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2106,17 +2106,17 @@ int config_parse_preferred_src(
return 0;
}
if (n->family == AF_UNSPEC)
r = in_addr_from_string_auto(rvalue, &n->family, &n->prefsrc);
if (route->family == AF_UNSPEC)
r = in_addr_from_string_auto(rvalue, &route->family, &route->prefsrc);
else
r = in_addr_from_string(n->family, rvalue, &n->prefsrc);
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;
}
TAKE_PTR(n);
TAKE_PTR(route);
return 0;
}
@@ -2133,7 +2133,7 @@ int config_parse_destination(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
union in_addr_union *buffer;
unsigned char *prefixlen;
int r;
@@ -2144,7 +2144,7 @@ int config_parse_destination(
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2154,27 +2154,27 @@ int config_parse_destination(
}
if (streq(lvalue, "Destination")) {
buffer = &n->dst;
prefixlen = &n->dst_prefixlen;
buffer = &route->dst;
prefixlen = &route->dst_prefixlen;
} else if (streq(lvalue, "Source")) {
buffer = &n->src;
prefixlen = &n->src_prefixlen;
buffer = &route->src;
prefixlen = &route->src_prefixlen;
} else
assert_not_reached();
if (n->family == AF_UNSPEC)
r = in_addr_prefix_from_string_auto(rvalue, &n->family, buffer, prefixlen);
if (route->family == AF_UNSPEC)
r = in_addr_prefix_from_string_auto(rvalue, &route->family, buffer, prefixlen);
else
r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen);
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;
}
(void) in_addr_mask(n->family, buffer, *prefixlen);
(void) in_addr_mask(route->family, buffer, *prefixlen);
TAKE_PTR(n);
TAKE_PTR(route);
return 0;
}
@@ -2191,7 +2191,7 @@ int config_parse_route_priority(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@@ -2200,7 +2200,7 @@ int config_parse_route_priority(
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2209,15 +2209,15 @@ int config_parse_route_priority(
return 0;
}
r = safe_atou32(rvalue, &n->priority);
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;
}
n->priority_set = true;
TAKE_PTR(n);
route->priority_set = true;
TAKE_PTR(route);
return 0;
}
@@ -2234,7 +2234,7 @@ int config_parse_route_scope(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@@ -2243,7 +2243,7 @@ int config_parse_route_scope(
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2258,62 +2258,9 @@ int config_parse_route_scope(
return 0;
}
n->scope = r;
n->scope_set = true;
TAKE_PTR(n);
return 0;
}
int config_parse_route_nexthop(
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_free_or_set_invalidp) Route *n = NULL;
uint32_t id;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (isempty(rvalue)) {
n->nexthop_id = 0;
TAKE_PTR(n);
return 0;
}
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 (id == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid nexthop ID, ignoring assignment: %s", rvalue);
return 0;
}
n->nexthop_id = id;
TAKE_PTR(n);
route->scope = r;
route->scope_set = true;
TAKE_PTR(route);
return 0;
}
@@ -2329,7 +2276,7 @@ int config_parse_route_table(
void *data,
void *userdata) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
Network *network = userdata;
int r;
@@ -2339,7 +2286,7 @@ int config_parse_route_table(
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2348,19 +2295,19 @@ int config_parse_route_table(
return 0;
}
r = manager_get_route_table_from_string(network->manager, rvalue, &n->table);
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;
}
n->table_set = true;
TAKE_PTR(n);
route->table_set = true;
TAKE_PTR(route);
return 0;
}
int config_parse_route_boolean(
int config_parse_route_gateway_onlink(
const char *unit,
const char *filename,
unsigned line,
@@ -2373,7 +2320,7 @@ int config_parse_route_boolean(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int r;
assert(filename);
@@ -2382,7 +2329,7 @@ int config_parse_route_boolean(
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2398,16 +2345,9 @@ int config_parse_route_boolean(
return 0;
}
if (STR_IN_SET(lvalue, "GatewayOnLink", "GatewayOnlink"))
n->gateway_onlink = r;
else if (streq(lvalue, "QuickAck"))
n->quickack = r;
else if (streq(lvalue, "FastOpenNoCookie"))
n->fast_open_no_cookie = r;
else
assert_not_reached();
route->gateway_onlink = r;
TAKE_PTR(n);
TAKE_PTR(route);
return 0;
}
@@ -2424,10 +2364,10 @@ int config_parse_ipv6_route_preference(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2437,18 +2377,18 @@ int config_parse_ipv6_route_preference(
}
if (streq(rvalue, "low"))
n->pref = ICMPV6_ROUTER_PREF_LOW;
route->pref = ICMPV6_ROUTER_PREF_LOW;
else if (streq(rvalue, "medium"))
n->pref = ICMPV6_ROUTER_PREF_MEDIUM;
route->pref = ICMPV6_ROUTER_PREF_MEDIUM;
else if (streq(rvalue, "high"))
n->pref = ICMPV6_ROUTER_PREF_HIGH;
route->pref = ICMPV6_ROUTER_PREF_HIGH;
else {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route preference: %s", rvalue);
return 0;
}
n->pref_set = true;
TAKE_PTR(n);
route->pref_set = true;
TAKE_PTR(route);
return 0;
}
@@ -2465,10 +2405,10 @@ int config_parse_route_protocol(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int r;
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2484,9 +2424,9 @@ int config_parse_route_protocol(
return 0;
}
n->protocol = r;
route->protocol = r;
TAKE_PTR(n);
TAKE_PTR(route);
return 0;
}
@@ -2503,10 +2443,10 @@ int config_parse_route_type(
void *userdata) {
Network *network = userdata;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_(route_free_or_set_invalidp) Route *route = NULL;
int t, r;
r = route_new_static(network, filename, section_line, &n);
r = route_new_static(network, filename, section_line, &route);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@@ -2522,465 +2462,9 @@ int config_parse_route_type(
return 0;
}
n->type = (unsigned char) t;
route->type = (unsigned char) t;
TAKE_PTR(n);
return 0;
}
int config_parse_route_hop_limit(
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) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
Network *network = userdata;
uint32_t k;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (isempty(rvalue)) {
n->hop_limit = 0;
TAKE_PTR(n);
return 0;
}
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse per route hop limit, ignoring assignment: %s", rvalue);
return 0;
}
if (k > 255) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Specified per route hop limit \"%s\" is too large, ignoring assignment: %m", rvalue);
return 0;
}
if (k == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid per route hop limit \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
n->hop_limit = k;
TAKE_PTR(n);
return 0;
}
int config_parse_tcp_congestion(
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_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype,
rvalue, &n->tcp_congestion_control_algo, userdata);
if (r < 0)
return r;
TAKE_PTR(n);
return 0;
}
int config_parse_tcp_advmss(
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) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
Network *network = userdata;
uint64_t u;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (isempty(rvalue)) {
n->advmss = 0;
TAKE_PTR(n);
return 0;
}
r = parse_size(rvalue, 1024, &u);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
if (u == 0 || u > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid TCPAdvertisedMaximumSegmentSize= \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
n->advmss = u;
TAKE_PTR(n);
return 0;
}
int config_parse_tcp_window(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint32_t *window = ASSERT_PTR(data);
uint32_t k;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (k >= 1024) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (k == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
return 0;
}
*window = k;
return 0;
}
int config_parse_route_tcp_window(
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) {
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
Network *network = userdata;
uint32_t *d;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (streq(lvalue, "InitialCongestionWindow"))
d = &n->initcwnd;
else if (streq(lvalue, "InitialAdvertisedReceiveWindow"))
d = &n->initrwnd;
else
assert_not_reached();
r = config_parse_tcp_window(unit, filename, line, section, section_line, lvalue, ltype, rvalue, d, userdata);
if (r < 0)
return r;
TAKE_PTR(n);
return 0;
}
int config_parse_route_mtu(
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_free_or_set_invalidp) Route *n = NULL;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->mtu, userdata);
if (r <= 0)
return r;
TAKE_PTR(n);
return 0;
}
int config_parse_route_tcp_rto(
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_free_or_set_invalidp) Route *n = NULL;
usec_t usec;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
r = parse_sec(rvalue, &usec);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse route TCP retransmission timeout (RTO), ignoring assignment: %s", rvalue);
return 0;
}
if (!timestamp_is_set(usec) ||
DIV_ROUND_UP(usec, USEC_PER_MSEC) > UINT32_MAX) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Route TCP retransmission timeout (RTO) must be in the range 0…%"PRIu32"ms, ignoring assignment: %s", UINT32_MAX, rvalue);
return 0;
}
n->tcp_rto_usec = usec;
TAKE_PTR(n);
return 0;
}
int config_parse_multipath_route(
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) {
_cleanup_(multipath_route_freep) MultipathRoute *m = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_free_ char *word = NULL;
Network *network = userdata;
union in_addr_union a;
int family, r;
const char *p;
char *dev;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = route_new_static(network, filename, section_line, &n);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to allocate route, ignoring assignment: %m");
return 0;
}
if (isempty(rvalue)) {
n->multipath_routes = ordered_set_free_with_destructor(n->multipath_routes, multipath_route_free);
return 0;
}
m = new0(MultipathRoute, 1);
if (!m)
return log_oom();
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;
}
dev = strchr(word, '@');
if (dev) {
*dev++ = '\0';
r = parse_ifindex(dev);
if (r > 0)
m->ifindex = r;
else {
if (!ifname_valid_full(dev, IFNAME_VALID_ALTERNATIVE)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid interface name '%s' in %s=, ignoring: %s", dev, lvalue, rvalue);
return 0;
}
m->ifname = strdup(dev);
if (!m->ifname)
return log_oom();
}
}
r = in_addr_from_string_auto(word, &family, &a);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
return 0;
}
m->gateway.address = a;
m->gateway.family = family;
if (!isempty(p)) {
r = safe_atou32(p, &m->weight);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
/* ip command takes weight in the range 1…255, while kernel takes the value in the
* range 0…254. MultiPathRoute= setting also takes weight in the same range which ip
* command uses, then networkd decreases by one and stores it to match the range which
* kernel uses. */
if (m->weight == 0 || m->weight > 256) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
m->weight--;
}
r = ordered_set_ensure_put(&n->multipath_routes, NULL, m);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to store multipath route, ignoring assignment: %m");
return 0;
}
TAKE_PTR(m);
TAKE_PTR(n);
TAKE_PTR(route);
return 0;
}
+4 -10
View File
@@ -9,6 +9,8 @@
#include "conf-parser.h"
#include "in-addr-util.h"
#include "networkd-link.h"
#include "networkd-route-metric.h"
#include "networkd-route-nexthop.h"
#include "networkd-util.h"
typedef struct Manager Manager;
@@ -80,6 +82,7 @@ struct Route {
extern const struct hash_ops route_hash_ops;
int route_new(Route **ret);
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret);
Route *route_free(Route *route);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Route, route_free);
int route_dup(const Route *src, Route **ret);
@@ -119,16 +122,7 @@ 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_route_boolean);
CONFIG_PARSER_PROTOTYPE(config_parse_route_gateway_onlink);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_route_preference);
CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol);
CONFIG_PARSER_PROTOTYPE(config_parse_route_type);
CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_window);
CONFIG_PARSER_PROTOTYPE(config_parse_route_hop_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_rto);
CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
CONFIG_PARSER_PROTOTYPE(config_parse_multipath_route);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_congestion);
CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss);
CONFIG_PARSER_PROTOTYPE(config_parse_route_nexthop);