#include "networkd-route.h"
#include "parse-util.h"
#include "set.h"
+#include "socket-netlink.h"
#include "string-table.h"
#include "string-util.h"
+#include "strv.h"
#include "strxcpyx.h"
#include "sysctl-util.h"
-#include "util.h"
+#include "vrf.h"
#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
route->initrwnd = in->initrwnd;
route->lifetime = in->lifetime;
- r = set_ensure_allocated(routes, &route_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(*routes, route);
+ r = set_ensure_put(routes, &route_hash_ops, route);
if (r < 0)
return r;
if (r == 0)
return r;
} else if (r == 0) {
/* Take over a foreign route */
- r = set_ensure_allocated(&link->routes, &route_hash_ops);
- if (r < 0)
- return r;
-
- r = set_put(link->routes, route);
+ r = set_ensure_put(&link->routes, &route_hash_ops, route);
if (r < 0)
return r;
r = route_remove(route, route->link, NULL);
if (r < 0)
- log_warning_errno(r, "Could not remove route: %m");
+ log_link_warning_errno(route->link, r, "Could not remove route: %m");
else
route_free(route);
int route_configure(
Route *route,
Link *link,
- link_netlink_message_handler_t callback) {
+ link_netlink_message_handler_t callback,
+ Route **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
_cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
sd_event_source_unref(route->expire);
route->expire = TAKE_PTR(expire);
+ if (ret)
+ *ret = route;
+
return 1;
}
/* we are not in an Route section, so treat
* this as the special '0' section */
r = route_new_static(network, NULL, 0, &n);
- if (r < 0)
- return r;
+ 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, &n);
- if (r < 0)
- return r;
+ 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(rvalue, "dhcp")) {
+ if (streq(rvalue, "_dhcp")) {
n->gateway_from_dhcp = true;
TAKE_PTR(n);
return 0;
else
r = in_addr_from_string(n->family, rvalue, &n->gw);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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 (n->family == AF_UNSPEC)
r = in_addr_from_string_auto(rvalue, &n->family, &n->prefsrc);
else
r = in_addr_from_string(n->family, rvalue, &n->prefsrc);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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 = &n->dst;
else
r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
"Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue);
return 0;
}
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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, &n->priority);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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_ERR, filename, line, 0, "Unknown route scope: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route scope: %s", rvalue);
return 0;
}
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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_table_from_string(rvalue);
if (r >= 0)
else {
r = safe_atou32(rvalue, &n->table);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route table number \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
return 0;
}
-int config_parse_gateway_onlink(
+int config_parse_route_boolean(
const char *unit,
const char *filename,
unsigned line,
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse %s=\"%s\", ignoring assignment: %m", lvalue, rvalue);
return 0;
}
- n->gateway_onlink = r;
+ 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 if (streq(lvalue, "TTLPropagate"))
+ n->ttl_propagate = r;
+ else
+ assert_not_reached("Invalid lvalue");
TAKE_PTR(n);
return 0;
int r;
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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(rvalue, "low"))
n->pref = ICMPV6_ROUTER_PREF_LOW;
else if (streq(rvalue, "high"))
n->pref = ICMPV6_ROUTER_PREF_HIGH;
else {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route preference: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown route preference: %s", rvalue);
return 0;
}
int r;
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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_protocol_from_string(rvalue);
if (r >= 0)
else {
r = safe_atou8(rvalue , &n->protocol);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
int t, r;
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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;
+ }
t = route_type_from_string(rvalue);
if (t < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
"Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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_size(rvalue, 1024, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue);
return 0;
}
if (k > UINT32_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
"Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue, rvalue);
return 0;
}
return 0;
}
-int config_parse_quickack(
- 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;
- int k, r;
-
- assert(filename);
- assert(section);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
-
- k = parse_boolean(rvalue);
- if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k,
- "Failed to parse TCP quickack, ignoring: %s", rvalue);
- return 0;
- }
-
- n->quickack = !!k;
- TAKE_PTR(n);
- return 0;
-}
-
-int config_parse_fast_open_no_cookie(
- 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;
- int k, r;
-
- assert(filename);
- assert(section);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
-
- k = parse_boolean(rvalue);
- if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k,
- "Failed to parse TCP fastopen no cookie, ignoring: %s", rvalue);
- return 0;
- }
-
- n->fast_open_no_cookie = k;
- TAKE_PTR(n);
- return 0;
-}
-
int config_parse_route_mtu(
const char *unit,
const char *filename,
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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 0;
}
-int config_parse_route_ttl_propagate(
- 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, k;
-
- assert(filename);
- assert(section);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
-
- k = parse_boolean(rvalue);
- if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k,
- "Failed to parse TTLPropagate= value, ignoring: %s", rvalue);
- return 0;
- }
-
- n->ttl_propagate = k;
-
- TAKE_PTR(n);
- return 0;
-}
-
int config_parse_multipath_route(
const char *unit,
const char *filename,
assert(data);
r = route_new_static(network, filename, section_line, &n);
- if (r < 0)
- return r;
+ 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_free(n->multipath_routes);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route option, ignoring assignment: %s", rvalue);
return 0;
}
r = in_addr_from_string_auto(ip, &family, &a);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
return 0;
}
m->gateway.family = family;
if (dev) {
- r = parse_ifindex_or_ifname(dev, &m->ifindex);
+ r = resolve_interface(NULL, dev);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid interface name or index, ignoring assignment: %s", dev);
return 0;
}
+ m->ifindex = r;
}
if (!isempty(p)) {
r = safe_atou32(p, &m->weight);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
if (m->weight == 0 || m->weight > 256) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid multipath route weight, ignoring assignment: %s", p);
return 0;
}
r = ordered_set_put(n->multipath_routes, m);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
+ log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to store multipath route, ignoring assignment: %m");
return 0;
}
route->section->filename, route->section->line);
}
+ if (!route->table_set && network->vrf) {
+ route->table = VRF(network->vrf)->table;
+ route->table_set = true;
+ }
+
if (!route->table_set && IN_SET(route->type, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, RTN_NAT))
route->table = RT_TABLE_LOCAL;