networkd: route - support unicast,blackhole,unreachable and prohibited (#6861)

Resolves issues #797 and #967.

Conf

```
[Route]
Type=blackhole
Destination=202.54.1.2
```

ip route

```
blackhole 202.54.1.2 proto static
This commit is contained in:
Susant Sahani 2017-09-19 19:58:26 +05:30 committed by Zbigniew Jędrzejewski-Szmek
parent 6349cda20f
commit 983226f35a
7 changed files with 112 additions and 8 deletions

View File

@ -1015,6 +1015,19 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>Type=</varname></term>
<listitem>
<para>The Type identifier for special route types, which can be
<literal>unicast</literal> route to a destination network address which describes the path to the destination,
<literal>blackhole</literal> packets are discarded silently,
<literal>unreachable</literal> packets are discarded and the ICMP message host unreachable is generated,
<literal>prohibit</literal> packets are discarded and the ICMP message communication administratively
prohibited is generated. Defaults to <literal>unicast</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -155,6 +155,35 @@ int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family) {
return 0;
}
int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
assert_return(type, -EINVAL);
rtm = NLMSG_DATA(m->hdr);
*type = rtm->rtm_type;
return 0;
}
int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type) {
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);
rtm->rtm_type = type;
return 0;
}
int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) {
struct rtmsg *rtm;

View File

@ -296,7 +296,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
Link *link = NULL;
uint16_t type;
uint32_t ifindex, priority = 0;
unsigned char protocol, scope, tos, table;
unsigned char protocol, scope, tos, table, rt_type;
int family;
unsigned char dst_prefixlen, src_prefixlen;
union in_addr_union dst = {}, gw = {}, src = {}, prefsrc = {};
@ -441,6 +441,12 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
return 0;
}
r = sd_rtnl_message_route_get_type(message, &rt_type);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received route with invalid type, ignoring: %m");
return 0;
}
r = sd_rtnl_message_route_get_table(message, &table);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received route with invalid table, ignoring: %m");
@ -464,7 +470,7 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
return 0;
}
route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, protocol);
route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, rt_type, protocol);
break;

View File

@ -100,6 +100,7 @@ Route.Table, config_parse_route_table,
Route.GatewayOnlink, config_parse_gateway_onlink, 0, 0
Route.IPv6Preference, config_parse_ipv6_route_preference, 0, 0
Route.Protocol, config_parse_route_protocol, 0, 0
Route.Type, config_parse_route_type, 0, 0
DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp)

View File

@ -70,6 +70,7 @@ int route_new(Route **ret) {
route->family = AF_UNSPEC;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_UNSPEC;
route->type = RTN_UNICAST;
route->table = RT_TABLE_MAIN;
route->lifetime = USEC_INFINITY;
@ -372,7 +373,8 @@ int route_update(Route *route,
const union in_addr_union *gw,
const union in_addr_union *prefsrc,
unsigned char scope,
unsigned char protocol) {
unsigned char protocol,
unsigned char type) {
assert(route);
assert(src);
@ -385,6 +387,7 @@ int route_update(Route *route,
route->prefsrc = *prefsrc;
route->scope = scope;
route->protocol = protocol;
route->type = type;
return 0;
}
@ -458,9 +461,15 @@ int route_remove(Route *route, Link *link,
if (r < 0)
return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
return log_error_errno(r, "Could not set route type: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE)) {
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
}
r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
if (r < 0)
@ -612,9 +621,15 @@ int route_configure(
if (r < 0)
return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
return log_error_errno(r, "Could not set route type: %m");
if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE)) {
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
if (r < 0)
return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
}
r = sd_netlink_message_open_container(req, RTA_METRICS);
if (r < 0)
@ -1023,3 +1038,39 @@ int config_parse_route_protocol(const char *unit,
return 0;
}
int config_parse_route_type(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;
r = route_new_static(network, filename, section_line, &n);
if (r < 0)
return r;
if (streq(rvalue, "unicast"))
n->type = RTN_UNICAST;
else if (streq(rvalue, "blackhole"))
n->type = RTN_BLACKHOLE;
else if (streq(rvalue, "unreachable"))
n->type = RTN_UNREACHABLE;
else if (streq(rvalue, "prohibit"))
n->type = RTN_PROHIBIT;
else {
log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
return 0;
}
n = NULL;
return 0;
}

View File

@ -35,6 +35,7 @@ struct Route {
unsigned char src_prefixlen;
unsigned char scope;
unsigned char protocol; /* RTPROT_* */
unsigned char type; /* RTN_* */
unsigned char tos;
uint32_t priority; /* note that ip(8) calls this 'metric' */
uint32_t table;
@ -62,7 +63,7 @@ int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback
int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, uint32_t table, Route **ret);
int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);
int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol, unsigned char type);
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
@ -78,3 +79,4 @@ int config_parse_route_table(const char *unit, const char *filename, unsigned li
int config_parse_gateway_onlink(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);
int config_parse_ipv6_route_preference(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);
int config_parse_route_protocol(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);
int config_parse_route_type(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);

View File

@ -138,6 +138,7 @@ int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char
int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope);
int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags);
int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table);
int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type);
int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags);
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family);
int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family);
@ -147,6 +148,7 @@ int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos);
int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table);
int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len);
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len);
int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type);
int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags);
int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state);