X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-route.c;h=7f110a5217f1cdf7cca923b735ca8a3728f3fcad;hb=80cf9fb2e6f8117f408850cda5c1a8a932226766;hp=77c2daddc50f052339062812b332aa2263d83606;hpb=44e7b9492617408130d11ffa451c2660942974f6;p=elogind.git
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 77c2daddc..7f110a521 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -19,14 +19,12 @@
along with systemd; If not, see .
***/
-#include
#include "networkd.h"
+#include "networkd-link.h"
-#include "utf8.h"
#include "util.h"
#include "conf-parser.h"
-#include "network-internal.h"
int route_new_static(Network *network, unsigned section, Route **ret) {
_cleanup_route_free_ Route *route = NULL;
@@ -112,18 +110,16 @@ int route_drop(Route *route, Link *link,
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
RTM_DELROUTE, route->family,
route->protocol);
- if (r < 0) {
- log_error("Could not create RTM_DELROUTE message: %s", strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not create RTM_DELROUTE message: %m");
- 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;
+ if (!in_addr_is_null(route->family, &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)
+ return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
}
if (route->dst_prefixlen) {
@@ -131,41 +127,51 @@ int route_drop(Route *route, Link *link,
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;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_DST attribute: %m");
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;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not set destination prefix length: %m");
}
- r = sd_rtnl_message_route_set_scope(req, route->scope);
- if (r < 0) {
- log_error("Could not set scope: %s", strerror(-r));
- return r;
+ if (route->src_prefixlen) {
+ if (route->family == AF_INET)
+ r = sd_rtnl_message_append_in_addr(req, RTA_SRC, &route->src_addr.in);
+ else if (route->family == AF_INET6)
+ r = sd_rtnl_message_append_in6_addr(req, RTA_SRC, &route->src_addr.in6);
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_DST attribute: %m");
+
+ r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
+ if (r < 0)
+ return log_error_errno(r, "Could not set source prefix length: %m");
}
- r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
- if (r < 0) {
- log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r));
- return r;
+ 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)
+ return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
}
+ r = sd_rtnl_message_route_set_scope(req, route->scope);
+ if (r < 0)
+ return log_error_errno(r, "Could not set scope: %m");
+
+ r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
+
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;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
- if (r < 0) {
- log_error("Could not send rtnetlink message: %s", strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not send rtnetlink message: %m");
link_ref(link);
@@ -186,18 +192,16 @@ int route_configure(Route *route, Link *link,
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
RTM_NEWROUTE, route->family,
route->protocol);
- if (r < 0) {
- log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
- 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;
+ if (!in_addr_is_null(route->family, &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)
+ return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");
}
if (route->dst_prefixlen) {
@@ -205,41 +209,51 @@ int route_configure(Route *route, Link *link,
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;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_DST attribute: %m");
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;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not set destination prefix length: %m");
}
- r = sd_rtnl_message_route_set_scope(req, route->scope);
- if (r < 0) {
- log_error("Could not set scope: %s", strerror(-r));
- return r;
+ if (route->src_prefixlen) {
+ if (route->family == AF_INET)
+ r = sd_rtnl_message_append_in_addr(req, RTA_SRC, &route->src_addr.in);
+ else if (route->family == AF_INET6)
+ r = sd_rtnl_message_append_in6_addr(req, RTA_SRC, &route->src_addr.in6);
+ if (r < 0)
+ 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)
+ return log_error_errno(r, "Could not set source prefix length: %m");
}
- r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
- if (r < 0) {
- log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r));
- return r;
+ 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)
+ return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
}
+ r = sd_rtnl_message_route_set_scope(req, route->scope);
+ if (r < 0)
+ return log_error_errno(r, "Could not set scope: %m");
+
+ r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
+
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;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
- if (r < 0) {
- log_error("Could not send rtnetlink message: %s", strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Could not send rtnetlink message: %m");
link_ref(link);
@@ -307,6 +321,7 @@ int config_parse_destination(const char *unit,
_cleanup_route_free_ Route *n = NULL;
const char *address, *e;
union in_addr_union buffer;
+ unsigned char prefixlen;
int r, f;
assert(filename);
@@ -319,7 +334,7 @@ int config_parse_destination(const char *unit,
if (r < 0)
return r;
- /* Destination=address/prefixlen */
+ /* Destination|Source=address/prefixlen */
/* address */
e = strchr(rvalue, '/');
@@ -335,31 +350,41 @@ int config_parse_destination(const char *unit,
return 0;
}
+ if (f != AF_INET && f != AF_INET6) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Unknown address family, ignoring assignment: %s", address);
+ return 0;
+ }
+
/* prefixlen */
if (e) {
- unsigned i;
-
- r = safe_atou(e + 1, &i);
+ r = safe_atou8(e + 1, &prefixlen);
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) {
+ switch (f) {
case AF_INET:
- n->dst_prefixlen = 32;
+ prefixlen = 32;
break;
case AF_INET6:
- n->dst_prefixlen = 128;
+ prefixlen = 128;
break;
}
}
n->family = f;
- n->dst_addr = buffer;
+ if (streq(lvalue, "Destination")) {
+ n->dst_addr = buffer;
+ n->dst_prefixlen = prefixlen;
+ } else if (streq(lvalue, "Source")) {
+ n->src_addr = buffer;
+ n->src_prefixlen = prefixlen;
+ } else
+ assert_not_reached(lvalue);
+
n = NULL;
return 0;
@@ -399,3 +424,44 @@ int config_parse_route_priority(const char *unit,
return 0;
}
+
+int config_parse_route_scope(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;
+
+ if (streq(rvalue, "host"))
+ n->scope = RT_SCOPE_HOST;
+ else if (streq(rvalue, "link"))
+ n->scope = RT_SCOPE_LINK;
+ else if (streq(rvalue, "global"))
+ n->scope = RT_SCOPE_UNIVERSE;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ "Unknown route scope: %s", rvalue);
+ return 0;
+ }
+
+ n = NULL;
+
+ return 0;
+}