mirror of
https://github.com/systemd/systemd.git
synced 2025-03-09 12:58:26 +03:00
networkd: add support for source routing
This commit is contained in:
parent
66bba0e701
commit
9e7e440835
@ -415,6 +415,13 @@
|
||||
prefixlength. If omitted, a full-length host route is assumed.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Source=</varname></term>
|
||||
<listitem>
|
||||
<para>The source prefix of the route. Possibly followed by a slash and the
|
||||
prefixlength. If omitted, a full-length host route is assumed.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Metric=</varname></term>
|
||||
<listitem>
|
||||
|
@ -114,6 +114,24 @@ int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char pr
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
|
||||
struct rtmsg *rtm;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
|
||||
|
||||
rtm = NLMSG_DATA(m->hdr);
|
||||
|
||||
if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
|
||||
(rtm->rtm_family == AF_INET6 && prefixlen > 128))
|
||||
return -ERANGE;
|
||||
|
||||
rtm->rtm_src_len = prefixlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
|
||||
struct rtmsg *rtm;
|
||||
|
||||
|
@ -47,6 +47,7 @@ Address.Broadcast, config_parse_broadcast, 0,
|
||||
Address.Label, config_parse_label, 0, 0
|
||||
Route.Gateway, config_parse_gateway, 0, 0
|
||||
Route.Destination, config_parse_destination, 0, 0
|
||||
Route.Source, config_parse_destination, 0, 0
|
||||
Route.Metric, config_parse_route_priority, 0, 0
|
||||
DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
|
||||
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
|
||||
|
@ -138,6 +138,19 @@ int route_drop(Route *route, Link *link,
|
||||
return log_error_errno(r, "Could not set destination prefix length: %m");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
@ -207,6 +220,19 @@ int route_configure(Route *route, Link *link,
|
||||
return log_error_errno(r, "Could not set destination prefix length: %m");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
@ -298,6 +324,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);
|
||||
@ -310,7 +337,7 @@ int config_parse_destination(const char *unit,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Destination=address/prefixlen */
|
||||
/* Destination|Source=address/prefixlen */
|
||||
|
||||
/* address */
|
||||
e = strchr(rvalue, '/');
|
||||
@ -328,29 +355,33 @@ int config_parse_destination(const char *unit,
|
||||
|
||||
/* 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) {
|
||||
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;
|
||||
|
@ -147,12 +147,14 @@ struct Route {
|
||||
|
||||
int family;
|
||||
unsigned char dst_prefixlen;
|
||||
unsigned char src_prefixlen;
|
||||
unsigned char scope;
|
||||
uint32_t metrics;
|
||||
unsigned char protocol; /* RTPROT_* */
|
||||
|
||||
union in_addr_union in_addr;
|
||||
union in_addr_union dst_addr;
|
||||
union in_addr_union src_addr;
|
||||
union in_addr_union prefsrc_addr;
|
||||
|
||||
LIST_FIELDS(Route, routes);
|
||||
|
@ -102,6 +102,7 @@ int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags);
|
||||
int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type);
|
||||
|
||||
int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen);
|
||||
int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen);
|
||||
int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope);
|
||||
int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family);
|
||||
int sd_rtnl_message_route_get_dst_len(sd_rtnl_message *m, unsigned char *dst_len);
|
||||
|
Loading…
x
Reference in New Issue
Block a user