'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',
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
--- /dev/null
+/* 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_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, ltype, rvalue, &route->mtu, userdata);
+ if (r <= 0)
+ return r;
+
+ TAKE_PTR(route);
+ 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 *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 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;
+ }
+
+ route->advmss = u;
+
+ TAKE_PTR(route);
+ 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 *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 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;
+ }
+
+ 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 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 *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_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 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;
+ }
+
+ route->tcp_rto_usec = usec;
+
+ TAKE_PTR(route);
+ return 0;
+}
+
+int config_parse_route_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=\"%s\", ignoring assignment: %m", 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_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, ltype,
+ rvalue, &route->tcp_congestion_control_algo, userdata);
+ if (r < 0)
+ return r;
+
+ TAKE_PTR(route);
+ return 0;
+}
--- /dev/null
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "conf-parser.h"
+
+CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
+CONFIG_PARSER_PROTOTYPE(config_parse_tcp_advmss);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_hop_limit);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_window);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_tcp_rto);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_boolean);
+CONFIG_PARSER_PROTOTYPE(config_parse_tcp_congestion);
+CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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);
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;
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 *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_route_table(
const char *unit,
const char *filename,
return 0;
}
-int config_parse_route_boolean(
+int config_parse_route_gateway_onlink(
const char *unit,
const char *filename,
unsigned line,
return 0;
}
- if (STR_IN_SET(lvalue, "GatewayOnLink", "GatewayOnlink"))
- route->gateway_onlink = r;
- else if (streq(lvalue, "QuickAck"))
- route->quickack = r;
- else if (streq(lvalue, "FastOpenNoCookie"))
- route->fast_open_no_cookie = r;
- else
- assert_not_reached();
+ route->gateway_onlink = r;
TAKE_PTR(route);
return 0;
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 *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 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;
- }
-
- route->hop_limit = k;
-
- TAKE_PTR(route);
- 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 *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, ltype,
- rvalue, &route->tcp_congestion_control_algo, userdata);
- if (r < 0)
- return r;
-
- TAKE_PTR(route);
- 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 *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 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;
- }
-
- route->advmss = u;
-
- 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 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 *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_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, ltype, rvalue, &route->mtu, userdata);
- if (r <= 0)
- return r;
-
- TAKE_PTR(route);
- 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 *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 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;
- }
-
- route->tcp_rto_usec = usec;
-
- 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;
-}
-
static int route_section_verify(Route *route, Network *network) {
if (section_is_invalid(route->section))
return -EINVAL;
#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;
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);
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);