3 * Copyright (C) 2018 Cumulus Networks, Inc.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "srcdest_table.h"
31 #include "static_vrf.h"
32 #include "static_memory.h"
33 #include "static_vty.h"
34 #include "static_routes.h"
35 #ifndef VTYSH_EXTRACT_PL
36 #include "staticd/static_vty_clippy.c"
39 static struct static_vrf
*static_vty_get_unknown_vrf(struct vty
*vty
,
42 struct static_vrf
*svrf
;
45 svrf
= static_vrf_lookup_by_name(vrf_name
);
50 vrf
= vrf_get(VRF_UNKNOWN
, vrf_name
);
52 vty_out(vty
, "%% Could not create vrf %s\n", vrf_name
);
57 vty_out(vty
, "%% Could not create vrf-info %s\n",
61 /* Mark as having FRR configuration */
62 vrf_set_user_cfged(vrf
);
67 struct static_hold_route
{
83 /* processed & masked destination, used for config display */
87 static struct list
*static_list
;
89 static int static_list_compare_helper(const char *s1
, const char *s2
)
101 return strcmp(s1
, s2
);
104 static void static_list_delete(struct static_hold_route
*shr
)
107 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
109 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
111 XFREE(MTYPE_STATIC_ROUTE
, shr
->dest_str
);
113 XFREE(MTYPE_STATIC_ROUTE
, shr
->mask_str
);
115 XFREE(MTYPE_STATIC_ROUTE
, shr
->src_str
);
117 XFREE(MTYPE_STATIC_ROUTE
, shr
->gate_str
);
119 XFREE(MTYPE_STATIC_ROUTE
, shr
->ifname
);
121 XFREE(MTYPE_STATIC_ROUTE
, shr
->flag_str
);
123 XFREE(MTYPE_STATIC_ROUTE
, shr
->tag_str
);
124 if (shr
->distance_str
)
125 XFREE(MTYPE_STATIC_ROUTE
, shr
->distance_str
);
127 XFREE(MTYPE_STATIC_ROUTE
, shr
->label_str
);
129 XFREE(MTYPE_STATIC_ROUTE
, shr
->table_str
);
131 XFREE(MTYPE_STATIC_ROUTE
, shr
);
134 static int static_list_compare(void *arg1
, void *arg2
)
136 struct static_hold_route
*shr1
= arg1
;
137 struct static_hold_route
*shr2
= arg2
;
140 ret
= strcmp(shr1
->vrf_name
, shr2
->vrf_name
);
144 ret
= strcmp(shr1
->nhvrf_name
, shr2
->nhvrf_name
);
148 ret
= shr1
->afi
- shr2
->afi
;
152 ret
= shr1
->safi
- shr2
->safi
;
156 ret
= prefix_cmp(&shr1
->dest
, &shr2
->dest
);
160 ret
= static_list_compare_helper(shr1
->src_str
, shr2
->src_str
);
164 ret
= static_list_compare_helper(shr1
->gate_str
, shr2
->gate_str
);
168 ret
= static_list_compare_helper(shr1
->ifname
, shr2
->ifname
);
172 ret
= static_list_compare_helper(shr1
->flag_str
, shr2
->flag_str
);
176 ret
= static_list_compare_helper(shr1
->tag_str
, shr2
->tag_str
);
180 ret
= static_list_compare_helper(shr1
->distance_str
,
185 ret
= static_list_compare_helper(shr1
->table_str
,
190 return static_list_compare_helper(shr1
->label_str
, shr2
->label_str
);
194 /* General function for static route. */
195 static int zebra_static_route_holdem(
196 struct static_vrf
*svrf
, struct static_vrf
*nh_svrf
, afi_t afi
,
197 safi_t safi
, const char *negate
, struct prefix
*dest
,
198 const char *dest_str
, const char *mask_str
, const char *src_str
,
199 const char *gate_str
, const char *ifname
, const char *flag_str
,
200 const char *tag_str
, const char *distance_str
, const char *label_str
,
201 const char *table_str
)
203 struct static_hold_route
*shr
, *lookup
;
204 struct listnode
*node
;
206 zlog_warn("Static Route to %s not installed currently because dependent config not fully available",
209 shr
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(*shr
));
210 shr
->vrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, svrf
->vrf
->name
);
211 shr
->nhvrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, nh_svrf
->vrf
->name
);
215 prefix_copy(&shr
->dest
, dest
);
217 shr
->dest_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, dest_str
);
219 shr
->mask_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, mask_str
);
221 shr
->src_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, src_str
);
223 shr
->gate_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, gate_str
);
225 shr
->ifname
= XSTRDUP(MTYPE_STATIC_ROUTE
, ifname
);
227 shr
->flag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, flag_str
);
229 shr
->tag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, tag_str
);
231 shr
->distance_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, distance_str
);
233 shr
->label_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, label_str
);
235 shr
->table_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, table_str
);
237 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, lookup
)) {
238 if (static_list_compare(shr
, lookup
) == 0)
244 listnode_delete(static_list
, lookup
);
245 static_list_delete(shr
);
246 static_list_delete(lookup
);
252 * If a person enters the same line again
253 * we need to silently accept it
259 listnode_add_sort(static_list
, shr
);
264 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
265 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
266 XFREE(MTYPE_STATIC_ROUTE
, shr
);
271 static int static_route_leak(
272 struct vty
*vty
, struct static_vrf
*svrf
, struct static_vrf
*nh_svrf
,
273 afi_t afi
, safi_t safi
, const char *negate
, const char *dest_str
,
274 const char *mask_str
, const char *src_str
, const char *gate_str
,
275 const char *ifname
, const char *flag_str
, const char *tag_str
,
276 const char *distance_str
, const char *label_str
, const char *table_str
)
280 struct prefix p
, src
;
281 struct prefix_ipv6
*src_p
= NULL
;
283 union g_addr
*gatep
= NULL
;
285 enum static_blackhole_type bh_type
= 0;
288 struct static_nh_label snh_label
;
289 uint32_t table_id
= 0;
291 ret
= str2prefix(dest_str
, &p
);
294 vty_out(vty
, "%% Malformed address\n");
296 zlog_warn("%s: Malformed address: %s",
297 __PRETTY_FUNCTION__
, dest_str
);
298 return CMD_WARNING_CONFIG_FAILED
;
303 /* Cisco like mask notation. */
305 ret
= inet_aton(mask_str
, &mask
);
308 vty_out(vty
, "%% Malformed address\n");
310 zlog_warn("%s: Malformed address: %s",
313 return CMD_WARNING_CONFIG_FAILED
;
315 p
.prefixlen
= ip_masklen(mask
);
319 /* srcdest routing */
321 ret
= str2prefix(src_str
, &src
);
322 if (ret
<= 0 || src
.family
!= AF_INET6
) {
325 "%% Malformed source address\n");
328 "%s: Malformed source address: %s",
329 __PRETTY_FUNCTION__
, src_str
);
330 return CMD_WARNING_CONFIG_FAILED
;
332 src_p
= (struct prefix_ipv6
*)&src
;
339 /* Apply mask for given prefix. */
342 if (svrf
->vrf
->vrf_id
== VRF_UNKNOWN
343 || nh_svrf
->vrf
->vrf_id
== VRF_UNKNOWN
) {
344 vrf_set_user_cfged(svrf
->vrf
);
345 return zebra_static_route_holdem(
346 svrf
, nh_svrf
, afi
, safi
, negate
, &p
, dest_str
,
347 mask_str
, src_str
, gate_str
, ifname
, flag_str
, tag_str
,
348 distance_str
, label_str
, table_str
);
352 /* table configured. check consistent with vrf config
354 if (svrf
->vrf
->data
.l
.table_id
!= RT_TABLE_MAIN
) {
357 "%% Table %s overlaps vrf table %u\n",
358 table_str
, svrf
->vrf
->data
.l
.table_id
);
361 "%s: Table %s overlaps vrf table %u",
363 table_str
, svrf
->vrf
->data
.l
.table_id
);
364 return CMD_WARNING_CONFIG_FAILED
;
368 /* Administrative distance. */
370 distance
= atoi(distance_str
);
372 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
376 tag
= strtoul(tag_str
, NULL
, 10);
379 memset(&snh_label
, 0, sizeof(struct static_nh_label
));
384 "%% MPLS not turned on in kernel, ignoring command\n");
387 "%s: MPLS not turned on in kernel ignoring static route to %s",
388 __PRETTY_FUNCTION__
, dest_str
);
389 return CMD_WARNING_CONFIG_FAILED
;
391 int rc
= mpls_str2label(label_str
, &snh_label
.num_labels
,
397 vty_out(vty
, "%% Malformed label(s)\n");
400 "%s: Malformed labels specified for route %s",
401 __PRETTY_FUNCTION__
, dest_str
);
406 "%% Cannot use reserved label(s) (%d-%d)\n",
407 MPLS_LABEL_RESERVED_MIN
,
408 MPLS_LABEL_RESERVED_MAX
);
411 "%s: Cannot use reserved labels (%d-%d) for %s",
413 MPLS_LABEL_RESERVED_MIN
,
414 MPLS_LABEL_RESERVED_MAX
,
420 "%% Too many labels. Enter %d or fewer\n",
424 "%s: Too many labels, Enter %d or fewer for %s",
426 MPLS_MAX_LABELS
, dest_str
);
429 return CMD_WARNING_CONFIG_FAILED
;
435 table_id
= atol(table_str
);
437 /* Null0 static route. */
438 if (ifname
!= NULL
) {
439 if (strncasecmp(ifname
, "Null0", strlen(ifname
)) == 0
440 || strncasecmp(ifname
, "reject", strlen(ifname
)) == 0
441 || strncasecmp(ifname
, "blackhole", strlen(ifname
)) == 0) {
444 "%% Nexthop interface cannot be Null0, reject or blackhole\n");
447 "%s: Nexthop interface cannot be Null0, reject or blackhole for %s",
448 __PRETTY_FUNCTION__
, dest_str
);
449 return CMD_WARNING_CONFIG_FAILED
;
455 switch (flag_str
[0]) {
457 bh_type
= STATIC_BLACKHOLE_REJECT
;
460 bh_type
= STATIC_BLACKHOLE_DROP
;
463 bh_type
= STATIC_BLACKHOLE_NULL
;
467 vty_out(vty
, "%% Malformed flag %s \n",
470 zlog_warn("%s: Malformed flag %s for %s",
471 __PRETTY_FUNCTION__
, flag_str
,
473 return CMD_WARNING_CONFIG_FAILED
;
478 if (inet_pton(afi2family(afi
), gate_str
, &gate
) != 1) {
481 "%% Malformed nexthop address %s\n",
485 "%s: Malformed nexthop address %s for %s",
486 __PRETTY_FUNCTION__
, gate_str
,
488 return CMD_WARNING_CONFIG_FAILED
;
493 if (gate_str
== NULL
&& ifname
== NULL
)
494 type
= STATIC_BLACKHOLE
;
495 else if (gate_str
&& ifname
) {
497 type
= STATIC_IPV4_GATEWAY_IFNAME
;
499 type
= STATIC_IPV6_GATEWAY_IFNAME
;
501 type
= STATIC_IFNAME
;
504 type
= STATIC_IPV4_GATEWAY
;
506 type
= STATIC_IPV6_GATEWAY
;
510 static_add_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
511 bh_type
, tag
, distance
, svrf
, nh_svrf
,
512 &snh_label
, table_id
);
513 /* Mark as having FRR configuration */
514 vrf_set_user_cfged(svrf
->vrf
);
516 static_delete_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
517 tag
, distance
, svrf
, &snh_label
, table_id
);
518 /* If no other FRR config for this VRF, mark accordingly. */
519 if (!static_vrf_has_config(svrf
))
520 vrf_reset_user_cfged(svrf
->vrf
);
526 static int static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
527 const char *negate
, const char *dest_str
,
528 const char *mask_str
, const char *src_str
,
529 const char *gate_str
, const char *ifname
,
530 const char *flag_str
, const char *tag_str
,
531 const char *distance_str
, const char *vrf_name
,
532 const char *label_str
, const char *table_str
)
534 struct static_vrf
*svrf
;
537 svrf
= static_vrf_lookup_by_name(vrf_name
);
539 /* When trying to delete, the VRF must exist. */
540 if (negate
&& !svrf
) {
541 vty_out(vty
, "%% vrf %s is not defined\n", vrf_name
);
542 return CMD_WARNING_CONFIG_FAILED
;
545 /* When trying to create, create the VRF if it doesn't exist.
546 * Note: The VRF isn't active until we hear about it from the kernel.
549 svrf
= static_vty_get_unknown_vrf(vty
, vrf_name
);
551 return CMD_WARNING_CONFIG_FAILED
;
553 return static_route_leak(
554 vty
, svrf
, svrf
, afi
, safi
, negate
, dest_str
, mask_str
, src_str
,
555 gate_str
, ifname
, flag_str
, tag_str
, distance_str
, label_str
,
559 void static_config_install_delayed_routes(struct static_vrf
*svrf
)
561 struct listnode
*node
, *nnode
;
562 struct static_hold_route
*shr
;
563 struct static_vrf
*osvrf
, *nh_svrf
;
566 for (ALL_LIST_ELEMENTS(static_list
, node
, nnode
, shr
)) {
567 osvrf
= static_vrf_lookup_by_name(shr
->vrf_name
);
568 nh_svrf
= static_vrf_lookup_by_name(shr
->nhvrf_name
);
570 if (osvrf
!= svrf
&& nh_svrf
!= svrf
)
573 if (osvrf
->vrf
->vrf_id
== VRF_UNKNOWN
574 || nh_svrf
->vrf
->vrf_id
== VRF_UNKNOWN
)
577 installed
= static_route_leak(
578 NULL
, osvrf
, nh_svrf
, shr
->afi
, shr
->safi
, NULL
,
579 shr
->dest_str
, shr
->mask_str
, shr
->src_str
,
580 shr
->gate_str
, shr
->ifname
, shr
->flag_str
, shr
->tag_str
,
581 shr
->distance_str
, shr
->label_str
, shr
->table_str
);
583 if (installed
!= CMD_SUCCESS
)
585 "%s: Attempt to install %s as a route and it was rejected",
586 __PRETTY_FUNCTION__
, shr
->dest_str
);
587 listnode_delete(static_list
, shr
);
588 static_list_delete(shr
);
592 /* Write static route configuration. */
593 int static_config(struct vty
*vty
, struct static_vrf
*svrf
, afi_t afi
,
594 safi_t safi
, const char *cmd
)
596 struct static_hold_route
*shr
;
597 struct listnode
*node
;
599 struct route_node
*rn
;
600 struct static_route
*si
;
601 struct route_table
*stable
;
602 char buf
[SRCDEST2STR_BUFFER
];
605 stable
= svrf
->stable
[afi
][safi
];
609 sprintf(spacing
, "%s%s", (svrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ",
613 * Static routes for vrfs not fully inited
615 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, shr
)) {
616 if (shr
->afi
!= afi
|| shr
->safi
!= safi
)
619 if (strcmp(svrf
->vrf
->name
, shr
->vrf_name
) != 0)
622 char dest_str
[PREFIX_STRLEN
];
624 prefix2str(&shr
->dest
, dest_str
, sizeof(dest_str
));
626 vty_out(vty
, "%s ", spacing
);
628 vty_out(vty
, "%s ", dest_str
);
630 vty_out(vty
, "from %s ", shr
->src_str
);
632 vty_out(vty
, "%s ", shr
->gate_str
);
634 vty_out(vty
, "%s ", shr
->ifname
);
636 vty_out(vty
, "%s ", shr
->flag_str
);
638 vty_out(vty
, "tag %s ", shr
->tag_str
);
639 if (shr
->distance_str
)
640 vty_out(vty
, "%s ", shr
->distance_str
);
642 vty_out(vty
, "label %s ", shr
->label_str
);
644 vty_out(vty
, "table %s", shr
->table_str
);
645 if (strcmp(shr
->vrf_name
, shr
->nhvrf_name
) != 0)
646 vty_out(vty
, "nexthop-vrf %s", shr
->nhvrf_name
);
650 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
))
651 for (si
= rn
->info
; si
; si
= si
->next
) {
652 vty_out(vty
, "%s %s", spacing
,
653 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
656 case STATIC_IPV4_GATEWAY
:
657 vty_out(vty
, " %s", inet_ntoa(si
->addr
.ipv4
));
659 case STATIC_IPV6_GATEWAY
:
661 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
665 vty_out(vty
, " %s", si
->ifname
);
667 case STATIC_BLACKHOLE
:
668 switch (si
->bh_type
) {
669 case STATIC_BLACKHOLE_DROP
:
670 vty_out(vty
, " blackhole");
672 case STATIC_BLACKHOLE_NULL
:
673 vty_out(vty
, " Null0");
675 case STATIC_BLACKHOLE_REJECT
:
676 vty_out(vty
, " reject");
680 case STATIC_IPV4_GATEWAY_IFNAME
:
681 vty_out(vty
, " %s %s",
682 inet_ntop(AF_INET
, &si
->addr
.ipv4
, buf
,
686 case STATIC_IPV6_GATEWAY_IFNAME
:
687 vty_out(vty
, " %s %s",
688 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
695 vty_out(vty
, " tag %" ROUTE_TAG_PRI
, si
->tag
);
697 if (si
->distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
)
698 vty_out(vty
, " %d", si
->distance
);
700 /* Label information */
701 if (si
->snh_label
.num_labels
)
702 vty_out(vty
, " label %s",
703 mpls_label2str(si
->snh_label
.num_labels
,
704 si
->snh_label
.label
, buf
,
707 if (si
->nh_vrf_id
!= si
->vrf_id
)
708 vty_out(vty
, " nexthop-vrf %s", si
->nh_vrfname
);
711 * table ID from VRF overrides configured
714 svrf
->vrf
->data
.l
.table_id
== RT_TABLE_MAIN
)
715 vty_out(vty
, " table %u", si
->table_id
);
724 /* Static unicast routes for multicast RPF lookup. */
725 DEFPY (ip_mroute_dist
,
727 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
730 "Configure static unicast route into MRIB for multicast RPF lookup\n"
731 "IP destination prefix (e.g. 10.0.0.0/8)\n"
733 "Nexthop interface name\n"
736 return static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
737 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
738 distance_str
, NULL
, NULL
, NULL
);
741 /* Static route configuration. */
742 DEFPY(ip_route_blackhole
,
743 ip_route_blackhole_cmd
,
745 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
746 <reject|blackhole>$flag \
752 |table (1-4294967295) \
755 "Establish static routes\n"
756 "IP destination prefix (e.g. 10.0.0.0/8)\n"
757 "IP destination prefix\n"
758 "IP destination prefix mask\n"
759 "Emit an ICMP unreachable when matched\n"
760 "Silently discard pkts when matched\n"
761 "Set tag for this route\n"
763 "Distance value for this route\n"
766 "Table to configure\n"
767 "The table number to configure\n")
769 if (table_str
&& !vrf_is_backend_netns()) {
771 "%% table param only available when running on netns-based vrfs\n");
772 return CMD_WARNING_CONFIG_FAILED
;
775 return static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
776 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
777 distance_str
, vrf
, label
, table_str
);
780 DEFPY(ip_route_blackhole_vrf
,
781 ip_route_blackhole_vrf_cmd
,
783 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
784 <reject|blackhole>$flag \
789 |table (1-4294967295) \
792 "Establish static routes\n"
793 "IP destination prefix (e.g. 10.0.0.0/8)\n"
794 "IP destination prefix\n"
795 "IP destination prefix mask\n"
796 "Emit an ICMP unreachable when matched\n"
797 "Silently discard pkts when matched\n"
798 "Set tag for this route\n"
800 "Distance value for this route\n"
802 "Table to configure\n"
803 "The table number to configure\n")
805 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
806 struct static_vrf
*svrf
= vrf
->info
;
808 if (table_str
&& !vrf_is_backend_netns()) {
810 "%% table param only available when running on netns-based vrfs\n");
811 return CMD_WARNING_CONFIG_FAILED
;
815 * Coverity is complaining that prefix could
816 * be dereferenced, but we know that prefix will
817 * valid. Add an assert to make it happy
820 return static_route_leak(vty
, svrf
, svrf
, AFI_IP
, SAFI_UNICAST
,
821 no
, prefix
, mask_str
, NULL
, NULL
, NULL
,
822 flag
, tag_str
, distance_str
, label
, table_str
);
825 DEFPY(ip_route_address_interface
,
826 ip_route_address_interface_cmd
,
828 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
836 |table (1-4294967295) \
840 "Establish static routes\n"
841 "IP destination prefix (e.g. 10.0.0.0/8)\n"
842 "IP destination prefix\n"
843 "IP destination prefix mask\n"
844 "IP gateway address\n"
845 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
847 "Set tag for this route\n"
849 "Distance value for this route\n"
852 "Table to configure\n"
853 "The table number to configure\n"
856 struct static_vrf
*svrf
;
857 struct static_vrf
*nh_svrf
;
858 const char *flag
= NULL
;
860 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
865 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
867 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
868 return CMD_WARNING_CONFIG_FAILED
;
871 if (table_str
&& !vrf_is_backend_netns()) {
873 "%% table param only available when running on netns-based vrfs\n");
874 return CMD_WARNING_CONFIG_FAILED
;
878 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
883 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
884 return CMD_WARNING_CONFIG_FAILED
;
887 return static_route_leak(
888 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
889 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
893 DEFPY(ip_route_address_interface_vrf
,
894 ip_route_address_interface_vrf_cmd
,
896 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
903 |table (1-4294967295) \
907 "Establish static routes\n"
908 "IP destination prefix (e.g. 10.0.0.0/8)\n"
909 "IP destination prefix\n"
910 "IP destination prefix mask\n"
911 "IP gateway address\n"
912 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
914 "Set tag for this route\n"
916 "Distance value for this route\n"
918 "Table to configure\n"
919 "The table number to configure\n"
922 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
923 const char *flag
= NULL
;
924 struct static_vrf
*svrf
= vrf
->info
;
925 struct static_vrf
*nh_svrf
;
927 if (table_str
&& !vrf_is_backend_netns()) {
929 "%% table param only available when running on netns-based vrfs\n");
930 return CMD_WARNING_CONFIG_FAILED
;
933 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
939 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
944 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
945 return CMD_WARNING_CONFIG_FAILED
;
948 return static_route_leak(
949 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
950 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
957 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
958 <A.B.C.D$gate|INTERFACE$ifname> \
964 |table (1-4294967295) \
968 "Establish static routes\n"
969 "IP destination prefix (e.g. 10.0.0.0/8)\n"
970 "IP destination prefix\n"
971 "IP destination prefix mask\n"
972 "IP gateway address\n"
973 "IP gateway interface name\n"
974 "Set tag for this route\n"
976 "Distance value for this route\n"
979 "Table to configure\n"
980 "The table number to configure\n"
983 struct static_vrf
*svrf
;
984 struct static_vrf
*nh_svrf
;
985 const char *flag
= NULL
;
987 if (table_str
&& !vrf_is_backend_netns()) {
989 "%% table param only available when running on netns-based vrfs\n");
990 return CMD_WARNING_CONFIG_FAILED
;
993 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
998 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1000 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1001 return CMD_WARNING_CONFIG_FAILED
;
1005 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1010 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1011 return CMD_WARNING_CONFIG_FAILED
;
1014 return static_route_leak(
1015 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1016 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1023 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1024 <A.B.C.D$gate|INTERFACE$ifname> \
1026 tag (1-4294967295) \
1029 |table (1-4294967295) \
1033 "Establish static routes\n"
1034 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1035 "IP destination prefix\n"
1036 "IP destination prefix mask\n"
1037 "IP gateway address\n"
1038 "IP gateway interface name\n"
1039 "Set tag for this route\n"
1041 "Distance value for this route\n"
1043 "Table to configure\n"
1044 "The table number to configure\n"
1047 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1048 struct static_vrf
*svrf
= vrf
->info
;
1049 struct static_vrf
*nh_svrf
;
1050 const char *flag
= NULL
;
1052 if (table_str
&& !vrf_is_backend_netns()) {
1054 "%% table param only available when running on netns-based vrfs\n");
1055 return CMD_WARNING_CONFIG_FAILED
;
1058 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1064 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1069 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1070 return CMD_WARNING_CONFIG_FAILED
;
1073 return static_route_leak(
1074 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1075 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1079 DEFPY(ipv6_route_blackhole
,
1080 ipv6_route_blackhole_cmd
,
1081 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1082 <Null0|reject|blackhole>$flag \
1084 tag (1-4294967295) \
1088 |table (1-4294967295) \
1092 "Establish static routes\n"
1093 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1094 "IPv6 source-dest route\n"
1095 "IPv6 source prefix\n"
1097 "Emit an ICMP unreachable when matched\n"
1098 "Silently discard pkts when matched\n"
1099 "Set tag for this route\n"
1101 "Distance value for this prefix\n"
1104 "Table to configure\n"
1105 "The table number to configure\n")
1107 if (table_str
&& !vrf_is_backend_netns()) {
1109 "%% table param only available when running on netns-based vrfs\n");
1110 return CMD_WARNING_CONFIG_FAILED
;
1113 return static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
1114 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
1115 distance_str
, vrf
, label
, table_str
);
1118 DEFPY(ipv6_route_blackhole_vrf
,
1119 ipv6_route_blackhole_vrf_cmd
,
1120 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1121 <Null0|reject|blackhole>$flag \
1123 tag (1-4294967295) \
1126 |table (1-4294967295) \
1130 "Establish static routes\n"
1131 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1132 "IPv6 source-dest route\n"
1133 "IPv6 source prefix\n"
1135 "Emit an ICMP unreachable when matched\n"
1136 "Silently discard pkts when matched\n"
1137 "Set tag for this route\n"
1139 "Distance value for this prefix\n"
1141 "Table to configure\n"
1142 "The table number to configure\n")
1144 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1145 struct static_vrf
*svrf
= vrf
->info
;
1147 if (table_str
&& !vrf_is_backend_netns()) {
1149 "%% table param only available when running on netns-based vrfs\n");
1150 return CMD_WARNING_CONFIG_FAILED
;
1154 * Coverity is complaining that prefix could
1155 * be dereferenced, but we know that prefix will
1156 * valid. Add an assert to make it happy
1159 return static_route_leak(
1160 vty
, svrf
, svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1161 from_str
, NULL
, NULL
, flag
, tag_str
, distance_str
, label
,
1165 DEFPY(ipv6_route_address_interface
,
1166 ipv6_route_address_interface_cmd
,
1167 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1171 tag (1-4294967295) \
1175 |table (1-4294967295) \
1180 "Establish static routes\n"
1181 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1182 "IPv6 source-dest route\n"
1183 "IPv6 source prefix\n"
1184 "IPv6 gateway address\n"
1185 "IPv6 gateway interface name\n"
1186 "Set tag for this route\n"
1188 "Distance value for this prefix\n"
1191 "Table to configure\n"
1192 "The table number to configure\n"
1195 struct static_vrf
*svrf
;
1196 struct static_vrf
*nh_svrf
;
1198 if (table_str
&& !vrf_is_backend_netns()) {
1200 "%% table param only available when running on netns-based vrfs\n");
1201 return CMD_WARNING_CONFIG_FAILED
;
1204 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1206 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1207 return CMD_WARNING_CONFIG_FAILED
;
1211 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1216 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1217 return CMD_WARNING_CONFIG_FAILED
;
1220 return static_route_leak(
1221 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1222 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1226 DEFPY(ipv6_route_address_interface_vrf
,
1227 ipv6_route_address_interface_vrf_cmd
,
1228 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1232 tag (1-4294967295) \
1235 |table (1-4294967295) \
1240 "Establish static routes\n"
1241 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1242 "IPv6 source-dest route\n"
1243 "IPv6 source prefix\n"
1244 "IPv6 gateway address\n"
1245 "IPv6 gateway interface name\n"
1246 "Set tag for this route\n"
1248 "Distance value for this prefix\n"
1250 "Table to configure\n"
1251 "The table number to configure\n"
1254 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1255 struct static_vrf
*svrf
= vrf
->info
;
1256 struct static_vrf
*nh_svrf
;
1258 if (table_str
&& !vrf_is_backend_netns()) {
1260 "%% table param only available when running on netns-based vrfs\n");
1261 return CMD_WARNING_CONFIG_FAILED
;
1265 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1270 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1271 return CMD_WARNING_CONFIG_FAILED
;
1274 return static_route_leak(
1275 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1276 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1282 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1283 <X:X::X:X$gate|INTERFACE$ifname> \
1285 tag (1-4294967295) \
1289 |table (1-4294967295) \
1294 "Establish static routes\n"
1295 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1296 "IPv6 source-dest route\n"
1297 "IPv6 source prefix\n"
1298 "IPv6 gateway address\n"
1299 "IPv6 gateway interface name\n"
1300 "Set tag for this route\n"
1302 "Distance value for this prefix\n"
1305 "Table to configure\n"
1306 "The table number to configure\n"
1309 struct static_vrf
*svrf
;
1310 struct static_vrf
*nh_svrf
;
1312 if (table_str
&& !vrf_is_backend_netns()) {
1314 "%% table param only available when running on netns-based vrfs\n");
1315 return CMD_WARNING_CONFIG_FAILED
;
1318 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1320 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1321 return CMD_WARNING_CONFIG_FAILED
;
1325 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1330 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1331 return CMD_WARNING_CONFIG_FAILED
;
1334 return static_route_leak(
1335 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1336 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1340 DEFPY(ipv6_route_vrf
,
1342 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1343 <X:X::X:X$gate|INTERFACE$ifname> \
1345 tag (1-4294967295) \
1348 |table (1-4294967295) \
1353 "Establish static routes\n"
1354 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1355 "IPv6 source-dest route\n"
1356 "IPv6 source prefix\n"
1357 "IPv6 gateway address\n"
1358 "IPv6 gateway interface name\n"
1359 "Set tag for this route\n"
1361 "Distance value for this prefix\n"
1363 "Table to configure\n"
1364 "The table number to configure\n"
1367 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1368 struct static_vrf
*svrf
= vrf
->info
;
1369 struct static_vrf
*nh_svrf
;
1371 if (table_str
&& !vrf_is_backend_netns()) {
1373 "%% table param only available when running on netns-based vrfs\n");
1374 return CMD_WARNING_CONFIG_FAILED
;
1378 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1383 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1384 return CMD_WARNING_CONFIG_FAILED
;
1387 return static_route_leak(
1388 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1389 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1393 void static_vty_init(void)
1395 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1397 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1398 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1399 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1400 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1401 install_element(CONFIG_NODE
, &ip_route_cmd
);
1402 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1404 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1405 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1406 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1407 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1408 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1409 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1411 static_list
= list_new();
1412 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
1413 static_list
->del
= (void (*)(void *))static_list_delete
;