summaryrefslogtreecommitdiff
path: root/src/network/networkd-route.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-route.c')
-rw-r--r--src/network/networkd-route.c102
1 files changed, 97 insertions, 5 deletions
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 3eca3cc547..b88c622614 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -28,9 +28,21 @@
#include "conf-parser.h"
#include "net-util.h"
-int route_new(Network *network, Route **ret) {
+int route_new(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);
+ if (route) {
+ *ret = route;
+ route = NULL;
+
+ return 0;
+ }
+ }
+
route = new0(Route, 1);
if (!route)
return -ENOMEM;
@@ -39,6 +51,11 @@ int route_new(Network *network, Route **ret) {
LIST_PREPEND(routes, network->routes, route);
+ if (section) {
+ route->section = section;
+ hashmap_put(network->routes_by_section, &route->section, route);
+ }
+
*ret = route;
route = NULL;
@@ -51,6 +68,10 @@ void route_free(Route *route) {
LIST_REMOVE(routes, route->network->routes, route);
+ if (route->section)
+ hashmap_remove(route->network->routes_by_section,
+ &route->section);
+
free(route);
}
@@ -65,9 +86,9 @@ 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, 0, 0, 0,
- RT_TABLE_MAIN, RT_SCOPE_UNIVERSE, RTPROT_BOOT,
- RTN_UNICAST, 0, &req);
+ 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);
if (r < 0) {
log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
return r;
@@ -79,6 +100,12 @@ int route_configure(Route *route, Link *link,
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;
+ }
+
r = sd_rtnl_message_append(req, RTA_OIF, &link->ifindex);
if (r < 0) {
log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
@@ -106,16 +133,18 @@ 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;
assert(filename);
+ assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
- r = route_new(userdata, &n);
+ r = route_new(network, section_line, &n);
if (r < 0)
return r;
@@ -130,3 +159,66 @@ int config_parse_gateway(const char *unit,
return 0;
}
+
+int config_parse_destination(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;
+ _cleanup_free_ char *address = NULL;
+ const char *e;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = route_new(network, section_line, &n);
+ if (r < 0)
+ return r;
+
+ /* Destination=address/prefixlen */
+
+ /* prefixlen */
+ 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();
+ } else {
+ address = strdup(rvalue);
+ if (!address)
+ return log_oom();
+ }
+
+ r = net_parse_inaddr(address, &n->family, &n->dst_addr);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Destination is invalid, ignoring assignment: %s", address);
+ return 0;
+ }
+
+ n = NULL;
+
+ return 0;
+}