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
{
84 /* processed & masked destination, used for config display */
88 static struct list
*static_list
;
90 static int static_list_compare_helper(const char *s1
, const char *s2
)
92 /* extra (!s1 && !s2) to keep SA happy */
93 if (s1
== s2
|| (!s1
&& !s2
))
102 return strcmp(s1
, s2
);
105 static void static_list_delete(struct static_hold_route
*shr
)
108 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
110 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
112 XFREE(MTYPE_STATIC_ROUTE
, shr
->dest_str
);
114 XFREE(MTYPE_STATIC_ROUTE
, shr
->mask_str
);
116 XFREE(MTYPE_STATIC_ROUTE
, shr
->src_str
);
118 XFREE(MTYPE_STATIC_ROUTE
, shr
->gate_str
);
120 XFREE(MTYPE_STATIC_ROUTE
, shr
->ifname
);
122 XFREE(MTYPE_STATIC_ROUTE
, shr
->flag_str
);
124 XFREE(MTYPE_STATIC_ROUTE
, shr
->tag_str
);
125 if (shr
->distance_str
)
126 XFREE(MTYPE_STATIC_ROUTE
, shr
->distance_str
);
128 XFREE(MTYPE_STATIC_ROUTE
, shr
->label_str
);
130 XFREE(MTYPE_STATIC_ROUTE
, shr
->table_str
);
132 XFREE(MTYPE_STATIC_ROUTE
, shr
);
135 static int static_list_compare(void *arg1
, void *arg2
)
137 struct static_hold_route
*shr1
= arg1
;
138 struct static_hold_route
*shr2
= arg2
;
141 ret
= strcmp(shr1
->vrf_name
, shr2
->vrf_name
);
145 ret
= strcmp(shr1
->nhvrf_name
, shr2
->nhvrf_name
);
149 ret
= shr1
->afi
- shr2
->afi
;
153 ret
= shr1
->safi
- shr2
->safi
;
157 ret
= prefix_cmp(&shr1
->dest
, &shr2
->dest
);
161 ret
= static_list_compare_helper(shr1
->src_str
, shr2
->src_str
);
165 ret
= static_list_compare_helper(shr1
->gate_str
, shr2
->gate_str
);
169 ret
= static_list_compare_helper(shr1
->ifname
, shr2
->ifname
);
173 ret
= static_list_compare_helper(shr1
->flag_str
, shr2
->flag_str
);
177 ret
= static_list_compare_helper(shr1
->tag_str
, shr2
->tag_str
);
181 ret
= static_list_compare_helper(shr1
->distance_str
,
186 ret
= static_list_compare_helper(shr1
->table_str
,
191 return static_list_compare_helper(shr1
->label_str
, shr2
->label_str
);
195 /* General function for static route. */
196 static int zebra_static_route_holdem(
197 struct static_vrf
*svrf
, struct static_vrf
*nh_svrf
, afi_t afi
,
198 safi_t safi
, const char *negate
, struct prefix
*dest
,
199 const char *dest_str
, const char *mask_str
, const char *src_str
,
200 const char *gate_str
, const char *ifname
, const char *flag_str
,
201 const char *tag_str
, const char *distance_str
, const char *label_str
,
202 const char *table_str
, bool onlink
)
204 struct static_hold_route
*shr
, *lookup
;
205 struct listnode
*node
;
207 zlog_warn("Static Route to %s not installed currently because dependent config not fully available",
210 shr
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(*shr
));
211 shr
->vrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, svrf
->vrf
->name
);
212 shr
->nhvrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, nh_svrf
->vrf
->name
);
215 shr
->onlink
= onlink
;
217 prefix_copy(&shr
->dest
, dest
);
219 shr
->dest_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, dest_str
);
221 shr
->mask_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, mask_str
);
223 shr
->src_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, src_str
);
225 shr
->gate_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, gate_str
);
227 shr
->ifname
= XSTRDUP(MTYPE_STATIC_ROUTE
, ifname
);
229 shr
->flag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, flag_str
);
231 shr
->tag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, tag_str
);
233 shr
->distance_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, distance_str
);
235 shr
->label_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, label_str
);
237 shr
->table_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, table_str
);
239 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, lookup
)) {
240 if (static_list_compare(shr
, lookup
) == 0)
246 listnode_delete(static_list
, lookup
);
247 static_list_delete(shr
);
248 static_list_delete(lookup
);
254 * If a person enters the same line again
255 * we need to silently accept it
261 listnode_add_sort(static_list
, shr
);
266 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
267 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
268 XFREE(MTYPE_STATIC_ROUTE
, shr
);
273 static int static_route_leak(
274 struct vty
*vty
, struct static_vrf
*svrf
, struct static_vrf
*nh_svrf
,
275 afi_t afi
, safi_t safi
, const char *negate
, const char *dest_str
,
276 const char *mask_str
, const char *src_str
, const char *gate_str
,
277 const char *ifname
, const char *flag_str
, const char *tag_str
,
278 const char *distance_str
, const char *label_str
, const char *table_str
,
283 struct prefix p
, src
;
284 struct prefix_ipv6
*src_p
= NULL
;
286 union g_addr
*gatep
= NULL
;
288 enum static_blackhole_type bh_type
= 0;
291 struct static_nh_label snh_label
;
292 uint32_t table_id
= 0;
294 ret
= str2prefix(dest_str
, &p
);
297 vty_out(vty
, "%% Malformed address\n");
299 zlog_warn("%s: Malformed address: %s",
300 __PRETTY_FUNCTION__
, dest_str
);
301 return CMD_WARNING_CONFIG_FAILED
;
306 /* Cisco like mask notation. */
308 ret
= inet_aton(mask_str
, &mask
);
311 vty_out(vty
, "%% Malformed address\n");
313 zlog_warn("%s: Malformed address: %s",
316 return CMD_WARNING_CONFIG_FAILED
;
318 p
.prefixlen
= ip_masklen(mask
);
322 /* srcdest routing */
324 ret
= str2prefix(src_str
, &src
);
325 if (ret
<= 0 || src
.family
!= AF_INET6
) {
328 "%% Malformed source address\n");
331 "%s: Malformed source address: %s",
332 __PRETTY_FUNCTION__
, src_str
);
333 return CMD_WARNING_CONFIG_FAILED
;
335 src_p
= (struct prefix_ipv6
*)&src
;
342 /* Apply mask for given prefix. */
345 if (svrf
->vrf
->vrf_id
== VRF_UNKNOWN
346 || nh_svrf
->vrf
->vrf_id
== VRF_UNKNOWN
) {
347 vrf_set_user_cfged(svrf
->vrf
);
348 return zebra_static_route_holdem(
349 svrf
, nh_svrf
, afi
, safi
, negate
, &p
, dest_str
,
350 mask_str
, src_str
, gate_str
, ifname
, flag_str
, tag_str
,
351 distance_str
, label_str
, table_str
, onlink
);
355 /* table configured. check consistent with vrf config
357 if (svrf
->vrf
->data
.l
.table_id
!= RT_TABLE_MAIN
) {
360 "%% Table %s overlaps vrf table %u\n",
361 table_str
, svrf
->vrf
->data
.l
.table_id
);
364 "%s: Table %s overlaps vrf table %u",
366 table_str
, svrf
->vrf
->data
.l
.table_id
);
367 return CMD_WARNING_CONFIG_FAILED
;
371 /* Administrative distance. */
373 distance
= atoi(distance_str
);
375 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
379 tag
= strtoul(tag_str
, NULL
, 10);
382 memset(&snh_label
, 0, sizeof(struct static_nh_label
));
387 "%% MPLS not turned on in kernel, ignoring command\n");
390 "%s: MPLS not turned on in kernel ignoring static route to %s",
391 __PRETTY_FUNCTION__
, dest_str
);
392 return CMD_WARNING_CONFIG_FAILED
;
394 int rc
= mpls_str2label(label_str
, &snh_label
.num_labels
,
400 vty_out(vty
, "%% Malformed label(s)\n");
403 "%s: Malformed labels specified for route %s",
404 __PRETTY_FUNCTION__
, dest_str
);
409 "%% Cannot use reserved label(s) (%d-%d)\n",
410 MPLS_LABEL_RESERVED_MIN
,
411 MPLS_LABEL_RESERVED_MAX
);
414 "%s: Cannot use reserved labels (%d-%d) for %s",
416 MPLS_LABEL_RESERVED_MIN
,
417 MPLS_LABEL_RESERVED_MAX
,
423 "%% Too many labels. Enter %d or fewer\n",
427 "%s: Too many labels, Enter %d or fewer for %s",
429 MPLS_MAX_LABELS
, dest_str
);
432 return CMD_WARNING_CONFIG_FAILED
;
438 table_id
= atol(table_str
);
440 /* Null0 static route. */
441 if (ifname
!= NULL
) {
442 if (strncasecmp(ifname
, "Null0", strlen(ifname
)) == 0
443 || strncasecmp(ifname
, "reject", strlen(ifname
)) == 0
444 || strncasecmp(ifname
, "blackhole", strlen(ifname
)) == 0) {
447 "%% Nexthop interface cannot be Null0, reject or blackhole\n");
450 "%s: Nexthop interface cannot be Null0, reject or blackhole for %s",
451 __PRETTY_FUNCTION__
, dest_str
);
452 return CMD_WARNING_CONFIG_FAILED
;
458 switch (flag_str
[0]) {
460 bh_type
= STATIC_BLACKHOLE_REJECT
;
463 bh_type
= STATIC_BLACKHOLE_DROP
;
466 bh_type
= STATIC_BLACKHOLE_NULL
;
470 vty_out(vty
, "%% Malformed flag %s \n",
473 zlog_warn("%s: Malformed flag %s for %s",
474 __PRETTY_FUNCTION__
, flag_str
,
476 return CMD_WARNING_CONFIG_FAILED
;
481 if (inet_pton(afi2family(afi
), gate_str
, &gate
) != 1) {
484 "%% Malformed nexthop address %s\n",
488 "%s: Malformed nexthop address %s for %s",
489 __PRETTY_FUNCTION__
, gate_str
,
491 return CMD_WARNING_CONFIG_FAILED
;
496 if (gate_str
== NULL
&& ifname
== NULL
)
497 type
= STATIC_BLACKHOLE
;
498 else if (gate_str
&& ifname
) {
500 type
= STATIC_IPV4_GATEWAY_IFNAME
;
502 type
= STATIC_IPV6_GATEWAY_IFNAME
;
504 type
= STATIC_IFNAME
;
507 type
= STATIC_IPV4_GATEWAY
;
509 type
= STATIC_IPV6_GATEWAY
;
513 static_add_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
514 bh_type
, tag
, distance
, svrf
, nh_svrf
,
515 &snh_label
, table_id
, onlink
);
516 /* Mark as having FRR configuration */
517 vrf_set_user_cfged(svrf
->vrf
);
519 static_delete_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
520 tag
, distance
, svrf
, &snh_label
, table_id
);
521 /* If no other FRR config for this VRF, mark accordingly. */
522 if (!static_vrf_has_config(svrf
))
523 vrf_reset_user_cfged(svrf
->vrf
);
529 static int static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
530 const char *negate
, const char *dest_str
,
531 const char *mask_str
, const char *src_str
,
532 const char *gate_str
, const char *ifname
,
533 const char *flag_str
, const char *tag_str
,
534 const char *distance_str
, const char *vrf_name
,
535 const char *label_str
, const char *table_str
)
537 struct static_vrf
*svrf
;
540 svrf
= static_vrf_lookup_by_name(vrf_name
);
542 /* When trying to delete, the VRF must exist. */
543 if (negate
&& !svrf
) {
544 vty_out(vty
, "%% vrf %s is not defined\n", vrf_name
);
545 return CMD_WARNING_CONFIG_FAILED
;
548 /* When trying to create, create the VRF if it doesn't exist.
549 * Note: The VRF isn't active until we hear about it from the kernel.
552 svrf
= static_vty_get_unknown_vrf(vty
, vrf_name
);
554 return CMD_WARNING_CONFIG_FAILED
;
556 return static_route_leak(vty
, svrf
, svrf
, afi
, safi
, negate
, dest_str
,
557 mask_str
, src_str
, gate_str
, ifname
, flag_str
,
558 tag_str
, distance_str
, label_str
, table_str
,
562 void static_config_install_delayed_routes(struct static_vrf
*svrf
)
564 struct listnode
*node
, *nnode
;
565 struct static_hold_route
*shr
;
566 struct static_vrf
*osvrf
, *nh_svrf
;
569 for (ALL_LIST_ELEMENTS(static_list
, node
, nnode
, shr
)) {
570 osvrf
= static_vrf_lookup_by_name(shr
->vrf_name
);
571 nh_svrf
= static_vrf_lookup_by_name(shr
->nhvrf_name
);
573 if (osvrf
!= svrf
&& nh_svrf
!= svrf
)
576 if (osvrf
->vrf
->vrf_id
== VRF_UNKNOWN
577 || nh_svrf
->vrf
->vrf_id
== VRF_UNKNOWN
)
580 installed
= static_route_leak(
581 NULL
, osvrf
, nh_svrf
, shr
->afi
, shr
->safi
, NULL
,
582 shr
->dest_str
, shr
->mask_str
, shr
->src_str
,
583 shr
->gate_str
, shr
->ifname
, shr
->flag_str
, shr
->tag_str
,
584 shr
->distance_str
, shr
->label_str
, shr
->table_str
,
587 if (installed
!= CMD_SUCCESS
)
589 "%s: Attempt to install %s as a route and it was rejected",
590 __PRETTY_FUNCTION__
, shr
->dest_str
);
591 listnode_delete(static_list
, shr
);
592 static_list_delete(shr
);
596 /* Write static route configuration. */
597 int static_config(struct vty
*vty
, struct static_vrf
*svrf
, afi_t afi
,
598 safi_t safi
, const char *cmd
)
600 struct static_hold_route
*shr
;
601 struct listnode
*node
;
603 struct route_node
*rn
;
604 struct static_route
*si
;
605 struct route_table
*stable
;
606 char buf
[SRCDEST2STR_BUFFER
];
609 stable
= svrf
->stable
[afi
][safi
];
613 sprintf(spacing
, "%s%s", (svrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ",
617 * Static routes for vrfs not fully inited
619 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, shr
)) {
620 if (shr
->afi
!= afi
|| shr
->safi
!= safi
)
623 if (strcmp(svrf
->vrf
->name
, shr
->vrf_name
) != 0)
626 char dest_str
[PREFIX_STRLEN
];
628 prefix2str(&shr
->dest
, dest_str
, sizeof(dest_str
));
630 vty_out(vty
, "%s ", spacing
);
632 vty_out(vty
, "%s ", dest_str
);
634 vty_out(vty
, "from %s ", shr
->src_str
);
636 vty_out(vty
, "%s ", shr
->gate_str
);
638 vty_out(vty
, "%s ", shr
->ifname
);
640 vty_out(vty
, "%s ", shr
->flag_str
);
642 vty_out(vty
, "tag %s ", shr
->tag_str
);
643 if (shr
->distance_str
)
644 vty_out(vty
, "%s ", shr
->distance_str
);
646 vty_out(vty
, "label %s ", shr
->label_str
);
648 vty_out(vty
, "table %s", shr
->table_str
);
649 if (strcmp(shr
->vrf_name
, shr
->nhvrf_name
) != 0)
650 vty_out(vty
, "nexthop-vrf %s ", shr
->nhvrf_name
);
652 vty_out(vty
, "onlink");
656 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
))
657 for (si
= rn
->info
; si
; si
= si
->next
) {
658 vty_out(vty
, "%s %s", spacing
,
659 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
662 case STATIC_IPV4_GATEWAY
:
663 vty_out(vty
, " %s", inet_ntoa(si
->addr
.ipv4
));
665 case STATIC_IPV6_GATEWAY
:
667 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
671 vty_out(vty
, " %s", si
->ifname
);
673 case STATIC_BLACKHOLE
:
674 switch (si
->bh_type
) {
675 case STATIC_BLACKHOLE_DROP
:
676 vty_out(vty
, " blackhole");
678 case STATIC_BLACKHOLE_NULL
:
679 vty_out(vty
, " Null0");
681 case STATIC_BLACKHOLE_REJECT
:
682 vty_out(vty
, " reject");
686 case STATIC_IPV4_GATEWAY_IFNAME
:
687 vty_out(vty
, " %s %s",
688 inet_ntop(AF_INET
, &si
->addr
.ipv4
, buf
,
692 case STATIC_IPV6_GATEWAY_IFNAME
:
693 vty_out(vty
, " %s %s",
694 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
701 vty_out(vty
, " tag %" ROUTE_TAG_PRI
, si
->tag
);
703 if (si
->distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
)
704 vty_out(vty
, " %d", si
->distance
);
706 /* Label information */
707 if (si
->snh_label
.num_labels
)
708 vty_out(vty
, " label %s",
709 mpls_label2str(si
->snh_label
.num_labels
,
710 si
->snh_label
.label
, buf
,
713 if (si
->nh_vrf_id
!= si
->vrf_id
)
714 vty_out(vty
, " nexthop-vrf %s", si
->nh_vrfname
);
717 * table ID from VRF overrides configured
720 svrf
->vrf
->data
.l
.table_id
== RT_TABLE_MAIN
)
721 vty_out(vty
, " table %u", si
->table_id
);
724 vty_out(vty
, " onlink");
733 /* Static unicast routes for multicast RPF lookup. */
734 DEFPY (ip_mroute_dist
,
736 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
739 "Configure static unicast route into MRIB for multicast RPF lookup\n"
740 "IP destination prefix (e.g. 10.0.0.0/8)\n"
742 "Nexthop interface name\n"
745 return static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
746 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
747 distance_str
, NULL
, NULL
, NULL
);
750 /* Static route configuration. */
751 DEFPY(ip_route_blackhole
,
752 ip_route_blackhole_cmd
,
754 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
755 <reject|blackhole>$flag \
761 |table (1-4294967295) \
764 "Establish static routes\n"
765 "IP destination prefix (e.g. 10.0.0.0/8)\n"
766 "IP destination prefix\n"
767 "IP destination prefix mask\n"
768 "Emit an ICMP unreachable when matched\n"
769 "Silently discard pkts when matched\n"
770 "Set tag for this route\n"
772 "Distance value for this route\n"
775 "Table to configure\n"
776 "The table number to configure\n")
778 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
780 "%% table param only available when running on netns-based vrfs\n");
781 return CMD_WARNING_CONFIG_FAILED
;
784 return static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
785 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
786 distance_str
, vrf
, label
, table_str
);
789 DEFPY(ip_route_blackhole_vrf
,
790 ip_route_blackhole_vrf_cmd
,
792 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
793 <reject|blackhole>$flag \
798 |table (1-4294967295) \
801 "Establish static routes\n"
802 "IP destination prefix (e.g. 10.0.0.0/8)\n"
803 "IP destination prefix\n"
804 "IP destination prefix mask\n"
805 "Emit an ICMP unreachable when matched\n"
806 "Silently discard pkts when matched\n"
807 "Set tag for this route\n"
809 "Distance value for this route\n"
811 "Table to configure\n"
812 "The table number to configure\n")
814 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
815 struct static_vrf
*svrf
= vrf
->info
;
817 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
819 "%% table param only available when running on netns-based vrfs\n");
820 return CMD_WARNING_CONFIG_FAILED
;
824 * Coverity is complaining that prefix could
825 * be dereferenced, but we know that prefix will
826 * valid. Add an assert to make it happy
829 return static_route_leak(vty
, svrf
, svrf
, AFI_IP
, SAFI_UNICAST
, no
,
830 prefix
, mask_str
, NULL
, NULL
, NULL
, flag
,
831 tag_str
, distance_str
, label
, table_str
,
835 DEFPY(ip_route_address_interface
,
836 ip_route_address_interface_cmd
,
838 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
840 <INTERFACE|Null0>$ifname \
846 |table (1-4294967295) \
851 "Establish static routes\n"
852 "IP destination prefix (e.g. 10.0.0.0/8)\n"
853 "IP destination prefix\n"
854 "IP destination prefix mask\n"
855 "IP gateway address\n"
856 "IP gateway interface name\n"
858 "Set tag for this route\n"
860 "Distance value for this route\n"
863 "Table to configure\n"
864 "The table number to configure\n"
866 "Treat the nexthop as directly attached to the interface")
868 struct static_vrf
*svrf
;
869 struct static_vrf
*nh_svrf
;
870 const char *flag
= NULL
;
872 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
877 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
879 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
880 return CMD_WARNING_CONFIG_FAILED
;
883 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
885 "%% table param only available when running on netns-based vrfs\n");
886 return CMD_WARNING_CONFIG_FAILED
;
890 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
895 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
896 return CMD_WARNING_CONFIG_FAILED
;
899 return static_route_leak(vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
,
900 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
901 tag_str
, distance_str
, label
, table_str
,
905 DEFPY(ip_route_address_interface_vrf
,
906 ip_route_address_interface_vrf_cmd
,
908 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
910 <INTERFACE|Null0>$ifname \
915 |table (1-4294967295) \
920 "Establish static routes\n"
921 "IP destination prefix (e.g. 10.0.0.0/8)\n"
922 "IP destination prefix\n"
923 "IP destination prefix mask\n"
924 "IP gateway address\n"
925 "IP gateway interface name\n"
927 "Set tag for this route\n"
929 "Distance value for this route\n"
931 "Table to configure\n"
932 "The table number to configure\n"
934 "Treat the nexthop as directly attached to the interface")
936 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
937 const char *flag
= NULL
;
938 struct static_vrf
*svrf
= vrf
->info
;
939 struct static_vrf
*nh_svrf
;
941 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
943 "%% table param only available when running on netns-based vrfs\n");
944 return CMD_WARNING_CONFIG_FAILED
;
947 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
953 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
958 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
959 return CMD_WARNING_CONFIG_FAILED
;
962 return static_route_leak(vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
,
963 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
964 tag_str
, distance_str
, label
, table_str
,
971 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
972 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
978 |table (1-4294967295) \
982 "Establish static routes\n"
983 "IP destination prefix (e.g. 10.0.0.0/8)\n"
984 "IP destination prefix\n"
985 "IP destination prefix mask\n"
986 "IP gateway address\n"
987 "IP gateway interface name\n"
989 "Set tag for this route\n"
991 "Distance value for this route\n"
994 "Table to configure\n"
995 "The table number to configure\n"
998 struct static_vrf
*svrf
;
999 struct static_vrf
*nh_svrf
;
1000 const char *flag
= NULL
;
1002 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1004 "%% table param only available when running on netns-based vrfs\n");
1005 return CMD_WARNING_CONFIG_FAILED
;
1008 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1013 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1015 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1016 return CMD_WARNING_CONFIG_FAILED
;
1020 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1025 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1026 return CMD_WARNING_CONFIG_FAILED
;
1029 return static_route_leak(
1030 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1031 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1038 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1039 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
1041 tag (1-4294967295) \
1044 |table (1-4294967295) \
1048 "Establish static routes\n"
1049 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1050 "IP destination prefix\n"
1051 "IP destination prefix mask\n"
1052 "IP gateway address\n"
1053 "IP gateway interface name\n"
1055 "Set tag for this route\n"
1057 "Distance value for this route\n"
1059 "Table to configure\n"
1060 "The table number to configure\n"
1063 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1064 struct static_vrf
*svrf
= vrf
->info
;
1065 struct static_vrf
*nh_svrf
;
1066 const char *flag
= NULL
;
1068 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
1070 "%% table param only available when running on netns-based vrfs\n");
1071 return CMD_WARNING_CONFIG_FAILED
;
1074 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1080 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1085 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1086 return CMD_WARNING_CONFIG_FAILED
;
1089 return static_route_leak(
1090 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1091 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1095 DEFPY(ipv6_route_blackhole
,
1096 ipv6_route_blackhole_cmd
,
1097 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1098 <reject|blackhole>$flag \
1100 tag (1-4294967295) \
1104 |table (1-4294967295) \
1108 "Establish static routes\n"
1109 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1110 "IPv6 source-dest route\n"
1111 "IPv6 source prefix\n"
1112 "Emit an ICMP unreachable when matched\n"
1113 "Silently discard pkts when matched\n"
1114 "Set tag for this route\n"
1116 "Distance value for this prefix\n"
1119 "Table to configure\n"
1120 "The table number to configure\n")
1122 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1124 "%% table param only available when running on netns-based vrfs\n");
1125 return CMD_WARNING_CONFIG_FAILED
;
1128 return static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
1129 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
1130 distance_str
, vrf
, label
, table_str
);
1133 DEFPY(ipv6_route_blackhole_vrf
,
1134 ipv6_route_blackhole_vrf_cmd
,
1135 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1136 <reject|blackhole>$flag \
1138 tag (1-4294967295) \
1141 |table (1-4294967295) \
1145 "Establish static routes\n"
1146 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1147 "IPv6 source-dest route\n"
1148 "IPv6 source prefix\n"
1149 "Emit an ICMP unreachable when matched\n"
1150 "Silently discard pkts when matched\n"
1151 "Set tag for this route\n"
1153 "Distance value for this prefix\n"
1155 "Table to configure\n"
1156 "The table number to configure\n")
1158 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1159 struct static_vrf
*svrf
= vrf
->info
;
1161 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
1163 "%% table param only available when running on netns-based vrfs\n");
1164 return CMD_WARNING_CONFIG_FAILED
;
1168 * Coverity is complaining that prefix could
1169 * be dereferenced, but we know that prefix will
1170 * valid. Add an assert to make it happy
1173 return static_route_leak(
1174 vty
, svrf
, svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1175 from_str
, NULL
, NULL
, flag
, tag_str
, distance_str
, label
,
1179 DEFPY(ipv6_route_address_interface
,
1180 ipv6_route_address_interface_cmd
,
1181 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1183 <INTERFACE|Null0>$ifname \
1185 tag (1-4294967295) \
1189 |table (1-4294967295) \
1195 "Establish static routes\n"
1196 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1197 "IPv6 source-dest route\n"
1198 "IPv6 source prefix\n"
1199 "IPv6 gateway address\n"
1200 "IPv6 gateway interface name\n"
1202 "Set tag for this route\n"
1204 "Distance value for this prefix\n"
1207 "Table to configure\n"
1208 "The table number to configure\n"
1210 "Treat the nexthop as directly attached to the interface")
1212 struct static_vrf
*svrf
;
1213 struct static_vrf
*nh_svrf
;
1216 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1218 "%% table param only available when running on netns-based vrfs\n");
1219 return CMD_WARNING_CONFIG_FAILED
;
1222 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1224 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1225 return CMD_WARNING_CONFIG_FAILED
;
1229 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1234 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1235 return CMD_WARNING_CONFIG_FAILED
;
1238 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1243 return static_route_leak(
1244 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1245 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1246 table_str
, !!onlink
);
1249 DEFPY(ipv6_route_address_interface_vrf
,
1250 ipv6_route_address_interface_vrf_cmd
,
1251 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1253 <INTERFACE|Null0>$ifname \
1255 tag (1-4294967295) \
1258 |table (1-4294967295) \
1264 "Establish static routes\n"
1265 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1266 "IPv6 source-dest route\n"
1267 "IPv6 source prefix\n"
1268 "IPv6 gateway address\n"
1269 "IPv6 gateway interface name\n"
1271 "Set tag for this route\n"
1273 "Distance value for this prefix\n"
1275 "Table to configure\n"
1276 "The table number to configure\n"
1278 "Treat the nexthop as directly attached to the interface")
1280 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1281 struct static_vrf
*svrf
= vrf
->info
;
1282 struct static_vrf
*nh_svrf
;
1285 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
1287 "%% table param only available when running on netns-based vrfs\n");
1288 return CMD_WARNING_CONFIG_FAILED
;
1292 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1297 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1298 return CMD_WARNING_CONFIG_FAILED
;
1301 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1306 return static_route_leak(
1307 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1308 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1309 table_str
, !!onlink
);
1314 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1315 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1317 tag (1-4294967295) \
1321 |table (1-4294967295) \
1326 "Establish static routes\n"
1327 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1328 "IPv6 source-dest route\n"
1329 "IPv6 source prefix\n"
1330 "IPv6 gateway address\n"
1331 "IPv6 gateway interface name\n"
1333 "Set tag for this route\n"
1335 "Distance value for this prefix\n"
1338 "Table to configure\n"
1339 "The table number to configure\n"
1342 struct static_vrf
*svrf
;
1343 struct static_vrf
*nh_svrf
;
1346 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1348 "%% table param only available when running on netns-based vrfs\n");
1349 return CMD_WARNING_CONFIG_FAILED
;
1352 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1354 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1355 return CMD_WARNING_CONFIG_FAILED
;
1359 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1364 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1365 return CMD_WARNING_CONFIG_FAILED
;
1368 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1373 return static_route_leak(
1374 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1375 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1379 DEFPY(ipv6_route_vrf
,
1381 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1382 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1384 tag (1-4294967295) \
1387 |table (1-4294967295) \
1392 "Establish static routes\n"
1393 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1394 "IPv6 source-dest route\n"
1395 "IPv6 source prefix\n"
1396 "IPv6 gateway address\n"
1397 "IPv6 gateway interface name\n"
1399 "Set tag for this route\n"
1401 "Distance value for this prefix\n"
1403 "Table to configure\n"
1404 "The table number to configure\n"
1407 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1408 struct static_vrf
*svrf
= vrf
->info
;
1409 struct static_vrf
*nh_svrf
;
1412 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
1414 "%% table param only available when running on netns-based vrfs\n");
1415 return CMD_WARNING_CONFIG_FAILED
;
1419 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1424 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1425 return CMD_WARNING_CONFIG_FAILED
;
1428 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1433 return static_route_leak(
1434 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1435 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1439 DEFUN_NOSH (show_debugging_staticd
,
1440 show_debugging_staticd_cmd
,
1441 "show debugging [static]",
1444 "Static Information\n")
1446 vty_out(vty
, "Static debugging status\n");
1451 void static_vty_init(void)
1453 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1455 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1456 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1457 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1458 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1459 install_element(CONFIG_NODE
, &ip_route_cmd
);
1460 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1462 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1463 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1464 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1465 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1466 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1467 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1469 install_element(VIEW_NODE
, &show_debugging_staticd_cmd
);
1471 static_list
= list_new();
1472 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
1473 static_list
->del
= (void (*)(void *))static_list_delete
;