]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: route - support unicast,blackhole,unreachable and prohibited (#6861)
authorSusant Sahani <ssahani@users.noreply.github.com>
Tue, 19 Sep 2017 14:28:26 +0000 (19:58 +0530)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 19 Sep 2017 14:28:26 +0000 (16:28 +0200)
Resolves issues #797 and #967.

Conf

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

ip route

```
blackhole 202.54.1.2 proto static

man/systemd.network.xml
src/libsystemd/sd-netlink/rtnl-message.c
src/network/networkd-manager.c
src/network/networkd-network-gperf.gperf
src/network/networkd-route.c
src/network/networkd-route.h
src/systemd/sd-netlink.h

index 6f01dac5932496db12a30f1964b9b53b8c9254fd..97509026619b983b87fe50df5611fac5905ff71a 100644 (file)
             </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>
 
index 586d94f624a35273e1640844b19014578a02e551..d6c52b5b437f860143f50718d88714c2ec0d8640 100644 (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;
 
index 82b9663019a6fd896331ab093d3373ee63d942dd..b9cf42d72f3b53fd6e6493d949852074c195befc 100644 (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;
 
index 274d2a8bbee6b188b8b5544be09f2bbafc19b4cc..5947f6dc15652c2d719a915ad0bfd222c944081c 100644 (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)
index e5d61ce8cc6452560a42816758b0f4a74de5b36e..5b4874795a7dfd78a1cba054779756fda8c43000 100644 (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;
+}
index 3f389489da921a782a568fda7ba1d38bf218badc..89d32e921449e492931bfce0f90467a9eb3c9ca2 100644 (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);
index 2289269eef9b0d182b342fffc598bad168ad1bc7..b28fc0da00ce6b48635cfcf597626da63ebd97cf 100644 (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);