Resolves issues #797 and #967.
Conf
```
[Route]
Type=blackhole
Destination=202.54.1.2
```
ip route
```
blackhole 202.54.1.2 proto static
</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>
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;
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 = {};
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");
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;
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)
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;
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);
route->prefsrc = *prefsrc;
route->scope = scope;
route->protocol = protocol;
+ route->type = type;
return 0;
}
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)
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)
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;
+}
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;
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);
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);
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);
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);