From: Donatas Abraitis Date: Thu, 24 Aug 2023 15:06:17 +0000 (+0300) Subject: staticd: Accept full blackhole typed keywords for ip_route_cmd X-Git-Tag: base_9.1~121^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=76b2bc97e73874d882d5cf021972cfca84656cef;p=matthieu%2Ffrr.git staticd: Accept full blackhole typed keywords for ip_route_cmd 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: 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 --- diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c index 01cd281d9c..6673cce108 100644 --- a/staticd/static_nb_config.c +++ b/staticd/static_nb_config.c @@ -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"); diff --git a/staticd/static_vty.c b/staticd/static_vty.c index d5fd0e3a2e..16e4cb7d83 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -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); }