]> git.puffer.fish Git - mirror/frr.git/commitdiff
staticd: Accept full blackhole typed keywords for ip_route_cmd 14274/head
authorDonatas Abraitis <donatas@opensourcerouting.org>
Thu, 24 Aug 2023 15:06:17 +0000 (18:06 +0300)
committerDonatas Abraitis <donatas@opensourcerouting.org>
Fri, 25 Aug 2023 09:00:33 +0000 (12:00 +0300)
Before this patch we allow entering next-hop interface address as any string.

Like, we can type: `ip route 10.10.10.10/32 bla`, but this will create a blackhole
route instead of using an interface `bla`.

The same is with reject.

After the patch:

```
$ vtysh -c 'con' -c 'ip route 10.10.10.100/32 bla'
ERROR: SET_CONFIG request failed, Error: nexthop interface name must be (reject, blackhole)

$ ip link show dev bla
472: bla: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000
    link/ether fa:45:bd:f1:f8:f0 brd ff:ff:ff:ff:ff:ff

$ vtysh -c 'sh run | include ip route'
$ vtysh -c 'con' -c 'ip route 10.10.10.100/32 blac'
$ vtysh -c 'sh run | include ip route'
ip route 10.10.10.100/32 blackhole

$ vtysh -c 'con' -c 'no ip route 10.10.10.100/32 blac'
$ vtysh -c 'sh run | include ip route'
$ vtysh -c 'con' -c 'ip route 10.10.10.100/32 blackhole'
$ vtysh -c 'sh run | include ip route'
ip route 10.10.10.100/32 blackhole

$ vtysh -c 'con' -c 'no ip route 10.10.10.100/32 blackhole'
$ vtysh -c 'sh run | include ip route'
$ vtysh -c 'con' -c 'ip route 10.10.10.100/32 Null0'
$ vtysh -c 'sh run | include ip route'
ip route 10.10.10.100/32 Null0

$ vtysh -c 'con' -c 'no ip route 10.10.10.100/32 Null0'
$ vtysh -c 'sh run | include ip route'
$
```

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
staticd/static_nb_config.c
staticd/static_vty.c

index 01cd281d9c6b07c6746c9bc0efc39954ebddedac..6673cce108b34cd30d8eefb233aa460bc476e088 100644 (file)
@@ -135,7 +135,8 @@ static bool static_nexthop_create(struct nb_cb_create_args *args)
        switch (args->event) {
        case NB_EV_VALIDATE:
                ifname = yang_dnode_get_string(args->dnode, "./interface");
-               if (ifname != NULL) {
+               nh_type = yang_dnode_get_enum(args->dnode, "./nh-type");
+               if (ifname != NULL && nh_type != STATIC_BLACKHOLE) {
                        if (strcasecmp(ifname, "Null0") == 0
                            || strcasecmp(ifname, "reject") == 0
                            || strcasecmp(ifname, "blackhole") == 0) {
@@ -371,10 +372,26 @@ static int static_nexthop_bh_type_modify(struct nb_cb_modify_args *args)
 {
        struct static_nexthop *nh;
        enum static_nh_type nh_type;
+       const char *nh_ifname;
+       const char *nh_vrf;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
                nh_type = yang_dnode_get_enum(args->dnode, "../nh-type");
+               nh_ifname = yang_dnode_get_string(args->dnode, "../interface");
+               nh_vrf = yang_dnode_get_string(args->dnode, "../vrf");
+               if (nh_ifname && nh_vrf) {
+                       struct vrf *vrf = vrf_lookup_by_name(nh_vrf);
+                       struct interface *ifp = if_lookup_by_name(nh_ifname,
+                                                                 vrf->vrf_id);
+
+                       if (ifp && (!strmatch(nh_ifname, "blackhole") ||
+                                   !strmatch(nh_ifname, "reject"))) {
+                               snprintf(args->errmsg, args->errmsg_len,
+                                        "nexthop interface name must be (reject, blackhole)");
+                               return NB_ERR_VALIDATION;
+                       }
+               }
                if (nh_type != STATIC_BLACKHOLE) {
                        snprintf(args->errmsg, args->errmsg_len,
                                 "nexthop type is not the blackhole type");
index d5fd0e3a2e0fea6a7f83d5c2b1bd8d45f81ddde6..16e4cb7d83bcc6bb3f1fee458b884ce15fa3f8be 100644 (file)
@@ -58,6 +58,8 @@ struct static_route_args {
        bool bfd_multi_hop;
        const char *bfd_source;
        const char *bfd_profile;
+
+       const char *input;
 };
 
 static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
@@ -145,9 +147,20 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
        else
                buf_gate_str = "";
 
-       if (args->gateway == NULL && args->interface_name == NULL)
+       if (args->gateway == NULL && args->interface_name == NULL) {
                type = STATIC_BLACKHOLE;
-       else if (args->gateway && args->interface_name) {
+               /* If this is blackhole/reject flagged route, then
+                * specify interface_name with the value of what was really
+                * entered.
+                * interface_name will be validated later in NB functions
+                * to check if we don't create blackhole/reject routes that
+                * match the real interface names.
+                * E.g.: `ip route 10.0.0.1/32 bla` will create a blackhole
+                * route despite the real interface named `bla` exists.
+                */
+               if (args->input)
+                       args->interface_name = args->input;
+       } else if (args->gateway && args->interface_name) {
                if (args->afi == AFI_IP)
                        type = STATIC_IPV4_GATEWAY_IFNAME;
                else
@@ -499,6 +512,8 @@ DEFPY_YANG(ip_route_blackhole,
       "Table to configure\n"
       "The table number to configure\n")
 {
+       int idx_flag = 0;
+
        struct static_route_args args = {
                .delete = !!no,
                .afi = AFI_IP,
@@ -513,6 +528,9 @@ DEFPY_YANG(ip_route_blackhole,
                .vrf = vrf,
        };
 
+       if (flag && argv_find(argv, argc, flag, &idx_flag))
+               args.input = argv[idx_flag]->arg;
+
        return static_route_nb_run(vty, &args);
 }
 
@@ -541,6 +559,8 @@ DEFPY_YANG(ip_route_blackhole_vrf,
       "Table to configure\n"
       "The table number to configure\n")
 {
+       int idx_flag = 0;
+
        struct static_route_args args = {
                .delete = !!no,
                .afi = AFI_IP,
@@ -562,6 +582,9 @@ DEFPY_YANG(ip_route_blackhole_vrf,
         */
        assert(args.prefix);
 
+       if (flag && argv_find(argv, argc, flag, &idx_flag))
+               args.input = argv[idx_flag]->arg;
+
        return static_route_nb_run(vty, &args);
 }
 
@@ -852,6 +875,8 @@ DEFPY_YANG(ipv6_route_blackhole,
       "Table to configure\n"
       "The table number to configure\n")
 {
+       int idx_flag = 0;
+
        struct static_route_args args = {
                .delete = !!no,
                .afi = AFI_IP6,
@@ -866,6 +891,9 @@ DEFPY_YANG(ipv6_route_blackhole,
                .vrf = vrf,
        };
 
+       if (flag && argv_find(argv, argc, flag, &idx_flag))
+               args.input = argv[idx_flag]->arg;
+
        return static_route_nb_run(vty, &args);
 }
 
@@ -894,6 +922,8 @@ DEFPY_YANG(ipv6_route_blackhole_vrf,
       "Table to configure\n"
       "The table number to configure\n")
 {
+       int idx_flag = 0;
+
        struct static_route_args args = {
                .delete = !!no,
                .afi = AFI_IP6,
@@ -915,6 +945,9 @@ DEFPY_YANG(ipv6_route_blackhole_vrf,
         */
        assert(args.prefix);
 
+       if (flag && argv_find(argv, argc, flag, &idx_flag))
+               args.input = argv[idx_flag]->arg;
+
        return static_route_nb_run(vty, &args);
 }