From f1368755493c73734c830150f0c9cd1c928ac29c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 10 Sep 2019 00:16:41 +0900 Subject: [PATCH] network: make route_get() or friends take Route object --- src/network/networkd-dhcp6.c | 56 ++++++++------- src/network/networkd-link.c | 27 ++++--- src/network/networkd-manager.c | 85 +++++++++++----------- src/network/networkd-route.c | 124 ++++++++------------------------- src/network/networkd-route.h | 7 +- 5 files changed, 119 insertions(+), 180 deletions(-) diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index 5e9535a1e7..e61eeda7d0 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -134,22 +134,21 @@ int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) { &lifetime_preferred, &lifetime_valid) >= 0) { _cleanup_free_ char *buf = NULL; - Route *route; + _cleanup_(route_freep) Route *route = NULL; if (pd_prefix_len >= 64) continue; (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf); - r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, NULL, 0, 0, 0, &route); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to add unreachable route to delete for DHCPv6 delegated subnet %s/%u: %m", - strnull(buf), - pd_prefix_len); - continue; - } + r = route_new(&route); + if (r < 0) + return r; - route_update(route, NULL, 0, NULL, NULL, 0, 0, RTN_UNREACHABLE); + route->family = AF_INET6; + route->dst = pd_prefix; + route->dst_prefixlen = pd_prefix_len; + route->type = RTN_UNREACHABLE; r = route_remove(route, link, dhcp6_route_remove_handler); if (r < 0) { @@ -290,20 +289,17 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { strnull(buf), pd_prefix_len); if (pd_prefix_len < 64) { - uint32_t table; - Route *route; + _cleanup_(route_freep) Route *route = NULL; - table = link_get_dhcp_route_table(link); + r = route_new(&route); + if (r < 0) + return r; - r = route_add(link, AF_INET6, &pd_prefix, pd_prefix_len, NULL, 0, 0, table, &route); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to add unreachable route for DHCPv6 delegated subnet %s/%u: %m", - strnull(buf), - pd_prefix_len); - continue; - } - - route_update(route, NULL, 0, NULL, NULL, 0, 0, RTN_UNREACHABLE); + route->family = AF_INET6; + route->dst = pd_prefix; + route->dst_prefixlen = pd_prefix_len; + route->table = link_get_dhcp_route_table(link); + route->type = RTN_UNREACHABLE; r = route_configure(route, link, dhcp6_route_handler); if (r < 0) { @@ -721,20 +717,23 @@ static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link * } static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) { + _cleanup_(route_freep) Route *route = NULL; _cleanup_free_ struct in6_addr *a = NULL; _cleanup_free_ char *buf = NULL; Link *assigned_link; - Route *route; int r; assert_return(m, -EINVAL); assert_return(addr, -EINVAL); - r = route_add(link, AF_INET6, (union in_addr_union *) addr, 64, - NULL, 0, 0, 0, &route); + r = route_new(&route); if (r < 0) return r; + route->family = AF_INET6; + route->dst.in6 = *addr; + route->dst_prefixlen = 64; + r = route_configure(route, link, dhcp6_route_add_handler); if (r < 0) return r; @@ -786,8 +785,8 @@ static int dhcp6_prefix_remove_handler(sd_netlink *nl, sd_netlink_message *m, Li int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) { _cleanup_free_ struct in6_addr *a = NULL; _cleanup_(link_unrefp) Link *l = NULL; + _cleanup_(route_freep) Route *route = NULL; _cleanup_free_ char *buf = NULL; - Route *route; int r; assert_return(m, -EINVAL); @@ -798,10 +797,15 @@ int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) { return -EINVAL; (void) sd_radv_remove_prefix(l->radv, addr, 64); - r = route_get(l, AF_INET6, (union in_addr_union *) addr, 64, NULL, 0, 0, 0, &route); + + r = route_new(&route); if (r < 0) return r; + route->family = AF_INET6; + route->dst.in6 = *addr; + route->dst_prefixlen = 64; + r = route_remove(route, l, dhcp6_prefix_remove_handler); if (r < 0) return r; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index f1aeb7287e..da1d406618 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2444,7 +2444,7 @@ static int link_drop_foreign_config(Link *link) { continue; if (link_is_static_route_configured(link, route)) { - r = route_add(link, route->family, &route->dst, route->dst_prefixlen, &route->gw, route->tos, route->priority, route->table, NULL); + r = route_add(link, route, NULL); if (r < 0) return r; } else { @@ -2906,7 +2906,6 @@ static int link_load(Link *link) { *dhcp4_address = NULL, *ipv4ll_address = NULL; union in_addr_union address; - union in_addr_union route_dst; const char *p; int r; @@ -2993,14 +2992,11 @@ network_file_fail: p = routes; for (;;) { - Route *route; - _cleanup_free_ char *route_str = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; - usec_t lifetime; + _cleanup_(route_freep) Route *tmp = NULL; + _cleanup_free_ char *route_str = NULL; char *prefixlen_str; - int family; - unsigned char prefixlen, tos, table; - uint32_t priority; + Route *route; r = extract_first_word(&p, &route_str, NULL, 0); if (r < 0) { @@ -3018,7 +3014,11 @@ network_file_fail: *prefixlen_str++ = '\0'; - r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime); + r = route_new(&tmp); + if (r < 0) + return log_oom(); + + r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%"PRIu32"/"USEC_FMT, &tmp->dst_prefixlen, &tmp->tos, &tmp->priority, &tmp->table, &tmp->lifetime); if (r != 5) { log_link_debug(link, "Failed to parse destination prefix length, tos, priority, table or expiration %s", @@ -3026,24 +3026,23 @@ network_file_fail: continue; } - r = in_addr_from_string_auto(route_str, &family, &route_dst); + r = in_addr_from_string_auto(route_str, &tmp->family, &tmp->dst); if (r < 0) { log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str); continue; } - r = route_add(link, family, &route_dst, prefixlen, NULL, tos, priority, table, &route); + r = route_add(link, tmp, &route); if (r < 0) return log_link_error_errno(link, r, "Failed to add route: %m"); - if (lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { - r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime, + if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { + r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), route->lifetime, 0, route_expire_handler, route); if (r < 0) log_link_warning_errno(link, r, "Could not arm route expiration handler: %m"); } - route->lifetime = lifetime; sd_event_source_unref(route->expire); route->expire = TAKE_PTR(expire); } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index a164d6163e..8095de960e 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -265,15 +265,13 @@ static int manager_connect_udev(Manager *m) { } int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + _cleanup_(route_freep) Route *tmp = NULL; + Route *route = NULL; Manager *m = userdata; Link *link = NULL; + uint32_t ifindex; uint16_t type; - uint32_t ifindex, priority = 0; - unsigned char protocol, scope, tos, table, rt_type; - int family; - unsigned char dst_prefixlen, src_prefixlen; - union in_addr_union dst = IN_ADDR_NULL, gw = IN_ADDR_NULL, src = IN_ADDR_NULL, prefsrc = IN_ADDR_NULL; - Route *route = NULL; + unsigned char table; int r; assert(rtnl); @@ -318,39 +316,43 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo return 0; } - r = sd_rtnl_message_route_get_family(message, &family); - if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { + r = route_new(&tmp); + if (r < 0) + return log_oom(); + + r = sd_rtnl_message_route_get_family(message, &tmp->family); + if (r < 0 || !IN_SET(tmp->family, AF_INET, AF_INET6)) { log_link_warning(link, "rtnl: received route message with invalid family, ignoring"); return 0; } - r = sd_rtnl_message_route_get_protocol(message, &protocol); + r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol); if (r < 0) { log_warning_errno(r, "rtnl: received route message with invalid route protocol: %m"); return 0; } - switch (family) { + switch (tmp->family) { case AF_INET: - r = sd_netlink_message_read_in_addr(message, RTA_DST, &dst.in); + r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &gw.in); + r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in_addr(message, RTA_SRC, &src.in); + r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &prefsrc.in); + r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); return 0; @@ -359,25 +361,25 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo break; case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, RTA_DST, &dst.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &gw.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &src.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); return 0; } - r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &prefsrc.in6); + r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); return 0; @@ -390,31 +392,31 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo return 0; } - r = sd_rtnl_message_route_get_dst_prefixlen(message, &dst_prefixlen); + r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_src_prefixlen(message, &src_prefixlen); + r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_scope(message, &scope); + r = sd_rtnl_message_route_get_scope(message, &tmp->scope); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_tos(message, &tos); + r = sd_rtnl_message_route_get_tos(message, &tmp->tos); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m"); return 0; } - r = sd_rtnl_message_route_get_type(message, &rt_type); + r = sd_rtnl_message_route_get_type(message, &tmp->type); if (r < 0) { log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m"); return 0; @@ -425,14 +427,15 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m"); return 0; } + tmp->table = table; - r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &priority); + r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority); if (r < 0 && r != -ENODATA) { log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m"); return 0; } - (void) route_get(link, family, &dst, dst_prefixlen, &gw, tos, priority, table, &route); + (void) route_get(link, tmp, &route); if (DEBUG_LOGGING) { _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL, @@ -440,41 +443,39 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX], buf_protocol[ROUTE_PROTOCOL_STR_MAX]; - if (!in_addr_is_null(family, &dst)) { - (void) in_addr_to_string(family, &dst, &buf_dst); - (void) asprintf(&buf_dst_prefixlen, "/%u", dst_prefixlen); + if (!in_addr_is_null(tmp->family, &tmp->dst)) { + (void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst); + (void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen); } - if (!in_addr_is_null(family, &src)) - (void) in_addr_to_string(family, &src, &buf_src); - if (!in_addr_is_null(family, &gw)) - (void) in_addr_to_string(family, &gw, &buf_gw); - if (!in_addr_is_null(family, &prefsrc)) - (void) in_addr_to_string(family, &prefsrc, &buf_prefsrc); + if (!in_addr_is_null(tmp->family, &tmp->src)) + (void) in_addr_to_string(tmp->family, &tmp->src, &buf_src); + if (!in_addr_is_null(tmp->family, &tmp->gw)) + (void) in_addr_to_string(tmp->family, &tmp->gw, &buf_gw); + if (!in_addr_is_null(tmp->family, &tmp->prefsrc)) + (void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc); log_link_debug(link, "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", - type == RTM_DELROUTE ? "Forgetting" : route ? "Updating remembered" : "Remembering", + type == RTM_DELROUTE ? "Forgetting" : route ? "Received remembered" : "Remembering", strna(buf_dst), strempty(buf_dst_prefixlen), strna(buf_src), strna(buf_gw), strna(buf_prefsrc), - format_route_scope(scope, buf_scope, sizeof buf_scope), - format_route_table(table, buf_table, sizeof buf_table), - format_route_protocol(protocol, buf_protocol, sizeof buf_protocol), - strna(route_type_to_string(rt_type))); + format_route_scope(tmp->scope, buf_scope, sizeof buf_scope), + format_route_table(tmp->table, buf_table, sizeof buf_table), + format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol), + strna(route_type_to_string(tmp->type))); } switch (type) { case RTM_NEWROUTE: if (!route) { /* A route appeared that we did not request */ - r = route_add_foreign(link, family, &dst, dst_prefixlen, &gw, tos, priority, table, &route); + r = route_add_foreign(link, tmp, &route); if (r < 0) { log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m"); return 0; } } - route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, protocol, rt_type); - break; case RTM_DELROUTE: diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index dd1469d0df..c95737e7ab 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -318,39 +318,21 @@ bool route_equal(Route *r1, Route *r2) { return route_compare_func(r1, r2) == 0; } -int route_get(Link *link, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - const union in_addr_union *gw, - unsigned char tos, - uint32_t priority, - uint32_t table, - Route **ret) { +int route_get(Link *link, Route *in, Route **ret) { - Route route, *existing; + Route *existing; assert(link); - assert(dst); + assert(in); - route = (Route) { - .family = family, - .dst = *dst, - .dst_prefixlen = dst_prefixlen, - .gw = gw ? *gw : IN_ADDR_NULL, - .tos = tos, - .priority = priority, - .table = table, - }; - - existing = set_get(link->routes, &route); + existing = set_get(link->routes, in); if (existing) { if (ret) *ret = existing; return 1; } - existing = set_get(link->routes_foreign, &route); + existing = set_get(link->routes_foreign, in); if (existing) { if (ret) *ret = existing; @@ -360,37 +342,35 @@ int route_get(Link *link, return -ENOENT; } -static int route_add_internal( - Link *link, - Set **routes, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - const union in_addr_union *gw, - unsigned char tos, - uint32_t priority, - uint32_t table, - Route **ret) { +static int route_add_internal(Link *link, Set **routes, Route *in, Route **ret) { _cleanup_(route_freep) Route *route = NULL; int r; assert(link); assert(routes); - assert(dst); + assert(in); r = route_new(&route); if (r < 0) return r; - route->family = family; - route->dst = *dst; - route->dst_prefixlen = dst_prefixlen; - route->dst = *dst; - route->gw = gw ? *gw : IN_ADDR_NULL; - route->tos = tos; - route->priority = priority; - route->table = table; + route->family = in->family; + route->src = in->src; + route->src_prefixlen = in->src_prefixlen; + route->dst = in->dst; + route->dst_prefixlen = in->dst_prefixlen; + route->gw = in->gw; + route->prefsrc = in->prefsrc; + route->scope = in->scope; + route->protocol = in->protocol; + route->type = in->type; + route->tos = in->tos; + route->priority = in->priority; + route->table = in->table; + route->initcwnd = in->initcwnd; + route->initrwnd = in->initrwnd; + route->lifetime = in->lifetime; r = set_ensure_allocated(routes, &route_hash_ops); if (r < 0) @@ -412,37 +392,19 @@ static int route_add_internal( return 0; } -int route_add_foreign( - Link *link, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - const union in_addr_union *gw, - unsigned char tos, - uint32_t priority, - uint32_t table, - Route **ret) { - - return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, gw, tos, priority, table, ret); +int route_add_foreign(Link *link, Route *in, Route **ret) { + return route_add_internal(link, &link->routes_foreign, in, ret); } -int route_add(Link *link, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - const union in_addr_union *gw, - unsigned char tos, - uint32_t priority, - uint32_t table, - Route **ret) { +int route_add(Link *link, Route *in, Route **ret) { Route *route; int r; - r = route_get(link, family, dst, dst_prefixlen, gw, tos, priority, table, &route); + r = route_get(link, in, &route); if (r == -ENOENT) { /* Route does not exist, create a new one */ - r = route_add_internal(link, &link->routes, family, dst, dst_prefixlen, gw, tos, priority, table, &route); + r = route_add_internal(link, &link->routes, in, &route); if (r < 0) return r; } else if (r == 0) { @@ -468,27 +430,6 @@ int route_add(Link *link, return 0; } -void route_update(Route *route, - const union in_addr_union *src, - unsigned char src_prefixlen, - const union in_addr_union *gw, - const union in_addr_union *prefsrc, - unsigned char scope, - unsigned char protocol, - unsigned char type) { - - assert(route); - assert(src || src_prefixlen == 0); - - route->src = src ? *src : IN_ADDR_NULL; - route->src_prefixlen = src_prefixlen; - route->gw = gw ? *gw : IN_ADDR_NULL; - route->prefsrc = prefsrc ? *prefsrc : IN_ADDR_NULL; - route->scope = scope; - route->protocol = protocol; - route->type = type; -} - static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -626,7 +567,6 @@ int route_configure( _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; - usec_t lifetime; int r; assert(link); @@ -636,7 +576,7 @@ int route_configure( assert(IN_SET(route->family, AF_INET, AF_INET6)); assert(callback); - if (route_get(link, route->family, &route->dst, route->dst_prefixlen, &route->gw, route->tos, route->priority, route->table, NULL) <= 0 && + if (route_get(link, route, NULL) <= 0 && set_size(link->routes) >= routes_max()) return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG), "Too many routes are configured, refusing: %m"); @@ -810,15 +750,11 @@ int route_configure( link_ref(link); - lifetime = route->lifetime; - - r = route_add(link, route->family, &route->dst, route->dst_prefixlen, &route->gw, route->tos, route->priority, route->table, &route); + r = route_add(link, route, &route); if (r < 0) return log_link_error_errno(link, r, "Could not add route: %m"); /* TODO: drop expiration handling once it can be pushed into the kernel */ - route->lifetime = lifetime; - if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), route->lifetime, 0, route_expire_handler, route); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index 9bd4991520..a246843625 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -56,10 +56,9 @@ void route_free(Route *route); int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback); int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); -int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, const union in_addr_union *gw, unsigned char tos, uint32_t priority, uint32_t table, Route **ret); -int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, const union in_addr_union *gw, unsigned char tos, uint32_t priority, uint32_t table, Route **ret); -int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, const union in_addr_union *gw, unsigned char tos, uint32_t priority, uint32_t table, Route **ret); -void route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol, unsigned char type); +int route_get(Link *link, Route *in, Route **ret); +int route_add(Link *link, Route *in, Route **ret); +int route_add_foreign(Link *link, Route *in, Route **ret); bool route_equal(Route *r1, Route *r2); int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);