diff options
Diffstat (limited to 'src/network/networkd-route.c')
-rw-r--r-- | src/network/networkd-route.c | 119 |
1 files changed, 103 insertions, 16 deletions
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index e065a5a5a9..f001de772a 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -52,8 +52,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) { int r; if (section) { - route = hashmap_get(network->routes_by_section, - UINT_TO_PTR(section)); + route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section)); if (route) { *ret = route; route = NULL; @@ -67,16 +66,18 @@ int route_new_static(Network *network, unsigned section, Route **ret) { return r; route->protocol = RTPROT_STATIC; - route->network = network; - - LIST_PREPEND(routes, network->static_routes, route); if (section) { route->section = section; - hashmap_put(network->routes_by_section, - UINT_TO_PTR(route->section), route); + + r = hashmap_put(network->routes_by_section, UINT_TO_PTR(route->section), route); + if (r < 0) + return r; } + route->network = network; + LIST_PREPEND(routes, network->static_routes, route); + *ret = route; route = NULL; @@ -323,12 +324,6 @@ int route_update(Route *route, return 0; } -void route_drop(Route *route) { - assert(route); - - route_free(route); -} - int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; @@ -374,7 +369,7 @@ int route_remove(Route *route, Link *link, else if (route->family == AF_INET6) r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src.in6); if (r < 0) - return log_error_errno(r, "Could not append RTA_DST attribute: %m"); + return log_error_errno(r, "Could not append RTA_SRC attribute: %m"); r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen); if (r < 0) @@ -411,15 +406,45 @@ int route_remove(Route *route, Link *link, return 0; } +static int route_expire_callback(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + Link *link = userdata; + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->ifname); + assert(link->link_messages > 0); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + link->link_messages--; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + log_link_warning_errno(link, r, "could not remove route: %m"); + + if (link->link_messages == 0) + log_link_debug(link, "route removed"); + + return 1; +} + int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { Route *route = userdata; int r; assert(route); - r = route_remove(route, route->link, NULL); + r = route_remove(route, route->link, route_expire_callback); if (r < 0) log_warning_errno(r, "Could not remove route: %m"); + else { + /* route may not be exist in kernel. If we fail still remove it */ + route->link->link_messages++; + route_free(route); + } return 1; } @@ -450,6 +475,10 @@ int route_configure(Route *route, Link *link, r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->gw.in6); if (r < 0) return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); + + r = sd_rtnl_message_route_set_family(req, route->family); + if (r < 0) + return log_error_errno(r, "Could not set route family: %m"); } if (route->dst_prefixlen) { @@ -493,7 +522,26 @@ int route_configure(Route *route, Link *link, r = sd_rtnl_message_route_set_flags(req, route->flags); if (r < 0) - return log_error_errno(r, "Colud not set flags: %m"); + return log_error_errno(r, "Could not set flags: %m"); + + if (route->table != RT_TABLE_DEFAULT) { + + if (route->table < 256) { + r = sd_rtnl_message_route_set_table(req, route->table); + if (r < 0) + return log_error_errno(r, "Could not set route table: %m"); + } else { + + r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC); + if (r < 0) + return log_error_errno(r, "Could not set route table: %m"); + + /* Table attribute to allow more than 256. */ + r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table)); + if (r < 0) + return log_error_errno(r, "Could not append RTA_TABLE attribute: %m"); + } + } r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority); if (r < 0) @@ -776,3 +824,42 @@ int config_parse_route_scope(const char *unit, return 0; } + +int config_parse_route_table(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_ 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, section_line, &n); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + + n->table = k; + + n = NULL; + + return 0; +} |