if (r < 0)
return r;
- r = route_dup(rt, &route);
+ r = route_dup(rt, NULL, &route);
if (r < 0)
return r;
if (route_gw->nexthop.family != AF_INET6)
continue;
- r = route_dup(route_gw, &route);
+ r = route_dup(route_gw, NULL, &route);
if (r < 0)
return r;
}}
}
+static int route_nexthop_copy(const RouteNextHop *src, RouteNextHop *dest) {
+ assert(src);
+ assert(dest);
+
+ *dest = *src;
+
+ /* unset pointer copied in the above. */
+ dest->ifname = NULL;
+
+ return strdup_or_null(src->ifindex == 0 ? NULL : src->ifname, &dest->ifname);
+}
+
+int route_nexthops_copy(const Route *src, const RouteNextHop *nh, Route *dest) {
+ assert(src);
+ assert(dest);
+
+ if (src->nexthop_id != 0 || route_type_is_reject(src))
+ return 0;
+
+ if (nh)
+ return route_nexthop_copy(nh, &dest->nexthop);
+
+ if (ordered_set_isempty(src->nexthops))
+ return route_nexthop_copy(&src->nexthop, &dest->nexthop);
+
+ /* Currently, this does not copy multipath routes. */
+
+ return 0;
+}
+
int route_nexthop_get_link(Manager *manager, Link *link, const RouteNextHop *nh, Link **ret) {
assert(manager);
assert(nh);
/* unsupported attributes: RTA_FLOW (IPv4 only), RTA_ENCAP_TYPE, RTA_ENCAP. */
} RouteNextHop;
+#define ROUTE_NEXTHOP_NULL ((const RouteNextHop) {})
+
RouteNextHop* route_nexthop_free(RouteNextHop *nh);
DEFINE_TRIVIAL_CLEANUP_FUNC(RouteNextHop*, route_nexthop_free);
void route_nexthops_hash_func(const Route *route, struct siphash *state);
int route_nexthops_compare_func(const Route *a, const Route *b);
+int route_nexthops_copy(const Route *src, const RouteNextHop *nh, Route *dest);
+
int route_nexthop_get_link(Manager *manager, Link *link, const RouteNextHop *nh, Link **ret);
int route_nexthops_is_ready_to_configure(const Route *route, Link *link);
return route_nexthop_get_link(manager, NULL, &route->nexthop, ret);
}
-int route_dup(const Route *src, Route **ret) {
+int route_dup(const Route *src, const RouteNextHop *nh, Route **ret) {
_cleanup_(route_freep) Route *dest = NULL;
int r;
- /* This does not copy mulipath routes. */
-
assert(src);
assert(ret);
dest->wireguard = NULL;
dest->section = NULL;
dest->link = NULL;
+ dest->nexthop = ROUTE_NEXTHOP_NULL;
dest->nexthops = NULL;
dest->metric = ROUTE_METRIC_NULL;
dest->expire = NULL;
+ r = route_nexthops_copy(src, nh, dest);
+ if (r < 0)
+ return r;
+
r = route_metric_copy(&src->metric, &dest->metric);
if (r < 0)
return r;
if (r < 0)
return r;
- r = route_dup(route, &c->routes[0]);
+ r = route_dup(route, NULL, &c->routes[0]);
if (r < 0)
return r;
if (r < 0)
return r;
- r = route_dup(route, &c->routes[i]);
+ r = route_dup(route, NULL, &c->routes[i]);
if (r < 0)
return r;
size_t i = 0;
RouteNextHop *nh;
ORDERED_SET_FOREACH(nh, route->nexthops) {
- r = route_dup(route, &c->routes[i]);
+ r = route_dup(route, NULL, &c->routes[i]);
if (r < 0)
return r;
if (route_get(link->manager, converted->links[i] ?: link, converted->routes[i], &existing) < 0) {
_cleanup_(route_freep) Route *tmp = NULL;
- r = route_dup(converted->routes[i], &tmp);
+ r = route_dup(converted->routes[i], NULL, &tmp);
if (r < 0)
return log_oom();
if (consume_object)
tmp = route;
else {
- r = route_dup(route, &tmp);
+ r = route_dup(route, NULL, &tmp);
if (r < 0)
return r;
}
int route_new(Route **ret);
int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret);
-int route_dup(const Route *src, Route **ret);
+int route_dup(const Route *src, const RouteNextHop *nh, Route **ret);
int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, Route *route, const char *error_msg);
int route_remove(Route *route);