X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-route.c;h=10d8cd902a8c16147eb52bb4aa0d01781054ed1b;hb=9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22;hp=0cb7239ca04182945015d28aa4192383529e697a;hpb=5c1d3fc93d91384bbac29adf01074fa4375317ea;p=elogind.git diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 0cb7239ca..10d8cd902 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -22,19 +22,19 @@ #include #include "networkd.h" +#include "networkd-link.h" #include "utf8.h" #include "util.h" #include "conf-parser.h" -#include "net-util.h" +#include "network-internal.h" int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; if (section) { - uint64_t key = section; - - route = hashmap_get(network->routes_by_section, &key); + route = hashmap_get(network->routes_by_section, + UINT_TO_PTR(section)); if (route) { *ret = route; route = NULL; @@ -49,14 +49,16 @@ int route_new_static(Network *network, unsigned section, Route **ret) { route->family = AF_UNSPEC; route->scope = RT_SCOPE_UNIVERSE; + route->protocol = RTPROT_STATIC; route->network = network; - LIST_PREPEND(static_routes, network->static_routes, route); + LIST_PREPEND(routes, network->static_routes, route); if (section) { route->section = section; - hashmap_put(network->routes_by_section, &route->section, route); + hashmap_put(network->routes_by_section, + UINT_TO_PTR(route->section), route); } *ret = route; @@ -65,7 +67,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) { return 0; } -int route_new_dynamic(Route **ret) { +int route_new_dynamic(Route **ret, unsigned char rtm_protocol) { _cleanup_route_free_ Route *route = NULL; route = new0(Route, 1); @@ -74,6 +76,7 @@ int route_new_dynamic(Route **ret) { route->family = AF_UNSPEC; route->scope = RT_SCOPE_UNIVERSE; + route->protocol = rtm_protocol; *ret = route; route = NULL; @@ -86,11 +89,11 @@ void route_free(Route *route) { return; if (route->network) { - LIST_REMOVE(static_routes, route->network->static_routes, route); + LIST_REMOVE(routes, route->network->static_routes, route); if (route->section) hashmap_remove(route->network->routes_by_section, - &route->section); + UINT_TO_PTR(route->section)); } free(route); @@ -108,7 +111,8 @@ int route_drop(Route *route, Link *link, assert(route->family == AF_INET || route->family == AF_INET6); r = sd_rtnl_message_new_route(link->manager->rtnl, &req, - RTM_DELROUTE, route->family); + RTM_DELROUTE, route->family, + route->protocol); if (r < 0) { log_error("Could not create RTM_DELROUTE message: %s", strerror(-r)); return r; @@ -140,6 +144,17 @@ int route_drop(Route *route, Link *link, } } + if (!in_addr_is_null(route->family, &route->prefsrc_addr)) { + if (route->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in); + else if (route->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in6); + if (r < 0) { + log_error("Could not append RTA_PREFSRC attribute: %s", strerror(-r)); + return r; + } + } + r = sd_rtnl_message_route_set_scope(req, route->scope); if (r < 0) { log_error("Could not set scope: %s", strerror(-r)); @@ -164,6 +179,8 @@ int route_drop(Route *route, Link *link, return r; } + link_ref(link); + return 0; } @@ -179,7 +196,8 @@ int route_configure(Route *route, Link *link, assert(route->family == AF_INET || route->family == AF_INET6); r = sd_rtnl_message_new_route(link->manager->rtnl, &req, - RTM_NEWROUTE, route->family); + RTM_NEWROUTE, route->family, + route->protocol); if (r < 0) { log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r)); return r; @@ -211,6 +229,17 @@ int route_configure(Route *route, Link *link, } } + if (!in_addr_is_null(route->family, &route->prefsrc_addr)) { + if (route->family == AF_INET) + r = sd_rtnl_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in); + else if (route->family == AF_INET6) + r = sd_rtnl_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc_addr.in6); + if (r < 0) { + log_error("Could not append RTA_PREFSRC attribute: %s", strerror(-r)); + return r; + } + } + r = sd_rtnl_message_route_set_scope(req, route->scope); if (r < 0) { log_error("Could not set scope: %s", strerror(-r)); @@ -235,6 +264,8 @@ int route_configure(Route *route, Link *link, return r; } + link_ref(link); + return 0; } @@ -248,10 +279,11 @@ int config_parse_gateway(const char *unit, const char *rvalue, void *data, void *userdata) { + Network *network = userdata; _cleanup_route_free_ Route *n = NULL; - _cleanup_free_ char *route = NULL; - int r; + union in_addr_union buffer; + int r, f; assert(filename); assert(section); @@ -269,13 +301,15 @@ int config_parse_gateway(const char *unit, if (r < 0) return r; - r = net_parse_inaddr(rvalue, &n->family, &n->in_addr); + r = in_addr_from_string_auto(rvalue, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Route is invalid, ignoring assignment: %s", route); + "Route is invalid, ignoring assignment: %s", rvalue); return 0; } + n->family = f; + n->in_addr = buffer; n = NULL; return 0; @@ -291,11 +325,12 @@ int config_parse_destination(const char *unit, const char *rvalue, void *data, void *userdata) { + Network *network = userdata; _cleanup_route_free_ Route *n = NULL; - _cleanup_free_ char *address = NULL; - const char *e; - int r; + const char *address, *e; + union in_addr_union buffer; + int r, f; assert(filename); assert(section); @@ -311,17 +346,12 @@ int config_parse_destination(const char *unit, /* address */ e = strchr(rvalue, '/'); - if (e) { - address = strndup(rvalue, e - rvalue); - if (!address) - return log_oom(); - } else { - address = strdup(rvalue); - if (!address) - return log_oom(); - } + if (e) + address = strndupa(rvalue, e - rvalue); + else + address = rvalue; - r = net_parse_inaddr(address, &n->family, &n->dst_addr); + r = in_addr_from_string_auto(address, &f, &buffer); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Destination is invalid, ignoring assignment: %s", address); @@ -335,8 +365,7 @@ int config_parse_destination(const char *unit, 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); + "Route destination prefix length is invalid, ignoring assignment: %s", e + 1); return 0; } @@ -352,6 +381,43 @@ int config_parse_destination(const char *unit, } } + n->family = f; + n->dst_addr = buffer; + n = NULL; + + return 0; +} + +int config_parse_route_priority(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_ Route *n = NULL; + 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 = config_parse_unsigned(unit, filename, line, section, + section_line, lvalue, ltype, + rvalue, &n->metrics, userdata); + if (r < 0) + return r; + n = NULL; return 0;