X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-route.c;h=46a4537196aae3695a938446f61a6d12ad815904;hb=12e0f830f592ec4c6bb49ac7ae1e0e84f74105e3;hp=1ea6237cc7e03f15eca7b639c3207d89e1c71997;hpb=92fe133abf2de889659464ae8affd1db1710f72e;p=elogind.git diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 1ea6237cc..46a453719 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -28,7 +28,7 @@ #include "conf-parser.h" #include "net-util.h" -int route_new(Network *network, unsigned section, Route **ret) { +int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; if (section) { @@ -47,9 +47,11 @@ int route_new(Network *network, unsigned section, Route **ret) { if (!route) return -ENOMEM; + route->family = AF_UNSPEC; + route->network = network; - LIST_PREPEND(routes, network->routes, route); + LIST_PREPEND(static_routes, network->static_routes, route); if (section) { route->section = section; @@ -62,22 +64,39 @@ int route_new(Network *network, unsigned section, Route **ret) { return 0; } +int route_new_dynamic(Route **ret) { + _cleanup_route_free_ Route *route = NULL; + + route = new0(Route, 1); + if (!route) + return -ENOMEM; + + route->family = AF_UNSPEC; + + *ret = route; + route = NULL; + + return 0; +} + void route_free(Route *route) { if (!route) return; - LIST_REMOVE(routes, route->network->routes, route); + if (route->network) { + LIST_REMOVE(static_routes, route->network->static_routes, route); - if (route->section) - hashmap_remove(route->network->routes_by_section, - &route->section); + if (route->section) + hashmap_remove(route->network->routes_by_section, + &route->section); + } free(route); } int route_configure(Route *route, Link *link, sd_rtnl_message_handler_t callback) { - _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL; + _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL; int r; assert(link); @@ -86,27 +105,40 @@ int route_configure(Route *route, Link *link, assert(link->ifindex > 0); assert(route->family == AF_INET || route->family == AF_INET6); - r = sd_rtnl_message_route_new(RTM_NEWROUTE, route->family, route->dst_prefixlen, - 0, 0, RT_TABLE_MAIN, RT_SCOPE_UNIVERSE, - RTPROT_BOOT, RTN_UNICAST, 0, &req); + r = sd_rtnl_message_new_route(link->manager->rtnl, &req, + RTM_NEWROUTE, route->family); if (r < 0) { log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r)); return r; } - r = sd_rtnl_message_append(req, RTA_GATEWAY, &route->in_addr); + if (route->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in); + else if (route->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6); if (r < 0) { log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r)); return r; } - r = sd_rtnl_message_append(req, RTA_DST, &route->dst_addr); - if (r < 0) { - log_error("Could not append RTA_DST attribute: %s", strerror(-r)); - return r; + if (route->dst_prefixlen) { + if (route->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in); + else if (route->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6); + if (r < 0) { + log_error("Could not append RTA_DST attribute: %s", strerror(-r)); + return r; + } + + r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); + if (r < 0) { + log_error("Could not set destination prefix length: %s", strerror(-r)); + return r; + } } - r = sd_rtnl_message_append(req, RTA_OIF, &link->ifindex); + r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex); if (r < 0) { log_error("Could not append RTA_OIF attribute: %s", strerror(-r)); return r; @@ -148,7 +180,7 @@ int config_parse_gateway(const char *unit, section_line = 0; } - r = route_new(network, section_line, &n); + r = route_new_static(network, section_line, &n); if (r < 0) return r; @@ -186,26 +218,15 @@ int config_parse_destination(const char *unit, assert(rvalue); assert(data); - r = route_new(network, section_line, &n); + r = route_new_static(network, section_line, &n); if (r < 0) return r; /* Destination=address/prefixlen */ - /* prefixlen */ + /* address */ e = strchr(rvalue, '/'); if (e) { - unsigned i; - r = safe_atou(e + 1, &i); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Route destination prefix length is invalid, " - "ignoring assignment: %s", e + 1); - return 0; - } - - n->dst_prefixlen = (unsigned char) i; - address = strndup(rvalue, e - rvalue); if (!address) return log_oom(); @@ -222,6 +243,30 @@ int config_parse_destination(const char *unit, return 0; } + /* prefixlen */ + if (e) { + unsigned i; + + r = safe_atou(e + 1, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Route destination prefix length is invalid, " + "ignoring assignment: %s", e + 1); + return 0; + } + + n->dst_prefixlen = (unsigned char) i; + } else { + switch (n->family) { + case AF_INET: + n->dst_prefixlen = 32; + break; + case AF_INET6: + n->dst_prefixlen = 128; + break; + } + } + n = NULL; return 0;