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> \
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. Specify 'Null0' (case-insensitive) for a \
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> \
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. Specify 'Null0' (case-insensitive) for a \
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$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"
988 "Set tag for this route\n"
990 "Distance value for this route\n"
993 "Table to configure\n"
994 "The table number to configure\n"
997 struct static_vrf
*svrf
;
998 struct static_vrf
*nh_svrf
;
999 const char *flag
= NULL
;
1001 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1003 "%% table param only available when running on netns-based vrfs\n");
1004 return CMD_WARNING_CONFIG_FAILED
;
1007 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1012 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1014 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1015 return CMD_WARNING_CONFIG_FAILED
;
1019 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1024 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1025 return CMD_WARNING_CONFIG_FAILED
;
1028 return static_route_leak(
1029 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1030 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1037 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1038 <A.B.C.D$gate|INTERFACE$ifname> \
1040 tag (1-4294967295) \
1043 |table (1-4294967295) \
1047 "Establish static routes\n"
1048 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1049 "IP destination prefix\n"
1050 "IP destination prefix mask\n"
1051 "IP gateway address\n"
1052 "IP gateway interface name\n"
1053 "Set tag for this route\n"
1055 "Distance value for this route\n"
1057 "Table to configure\n"
1058 "The table number to configure\n"
1061 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1062 struct static_vrf
*svrf
= vrf
->info
;
1063 struct static_vrf
*nh_svrf
;
1064 const char *flag
= NULL
;
1066 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
1068 "%% table param only available when running on netns-based vrfs\n");
1069 return CMD_WARNING_CONFIG_FAILED
;
1072 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1078 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1083 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1084 return CMD_WARNING_CONFIG_FAILED
;
1087 return static_route_leak(
1088 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1089 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1093 DEFPY(ipv6_route_blackhole
,
1094 ipv6_route_blackhole_cmd
,
1095 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1096 <Null0|reject|blackhole>$flag \
1098 tag (1-4294967295) \
1102 |table (1-4294967295) \
1106 "Establish static routes\n"
1107 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1108 "IPv6 source-dest route\n"
1109 "IPv6 source prefix\n"
1111 "Emit an ICMP unreachable when matched\n"
1112 "Silently discard pkts when matched\n"
1113 "Set tag for this route\n"
1115 "Distance value for this prefix\n"
1118 "Table to configure\n"
1119 "The table number to configure\n")
1121 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1123 "%% table param only available when running on netns-based vrfs\n");
1124 return CMD_WARNING_CONFIG_FAILED
;
1127 return static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
1128 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
1129 distance_str
, vrf
, label
, table_str
);
1132 DEFPY(ipv6_route_blackhole_vrf
,
1133 ipv6_route_blackhole_vrf_cmd
,
1134 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1135 <Null0|reject|blackhole>$flag \
1137 tag (1-4294967295) \
1140 |table (1-4294967295) \
1144 "Establish static routes\n"
1145 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1146 "IPv6 source-dest route\n"
1147 "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] \
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"
1201 "Set tag for this route\n"
1203 "Distance value for this prefix\n"
1206 "Table to configure\n"
1207 "The table number to configure\n"
1209 "Treat the nexthop as directly attached to the interface")
1211 struct static_vrf
*svrf
;
1212 struct static_vrf
*nh_svrf
;
1214 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1216 "%% table param only available when running on netns-based vrfs\n");
1217 return CMD_WARNING_CONFIG_FAILED
;
1220 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1222 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1223 return CMD_WARNING_CONFIG_FAILED
;
1227 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1232 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1233 return CMD_WARNING_CONFIG_FAILED
;
1236 return static_route_leak(
1237 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1238 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1239 table_str
, !!onlink
);
1242 DEFPY(ipv6_route_address_interface_vrf
,
1243 ipv6_route_address_interface_vrf_cmd
,
1244 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1248 tag (1-4294967295) \
1251 |table (1-4294967295) \
1257 "Establish static routes\n"
1258 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1259 "IPv6 source-dest route\n"
1260 "IPv6 source prefix\n"
1261 "IPv6 gateway address\n"
1262 "IPv6 gateway interface name\n"
1263 "Set tag for this route\n"
1265 "Distance value for this prefix\n"
1267 "Table to configure\n"
1268 "The table number to configure\n"
1270 "Treat the nexthop as directly attached to the interface")
1272 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1273 struct static_vrf
*svrf
= vrf
->info
;
1274 struct static_vrf
*nh_svrf
;
1276 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
1278 "%% table param only available when running on netns-based vrfs\n");
1279 return CMD_WARNING_CONFIG_FAILED
;
1283 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1288 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1289 return CMD_WARNING_CONFIG_FAILED
;
1292 return static_route_leak(
1293 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1294 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1295 table_str
, !!onlink
);
1300 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1301 <X:X::X:X$gate|INTERFACE$ifname> \
1303 tag (1-4294967295) \
1307 |table (1-4294967295) \
1312 "Establish static routes\n"
1313 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1314 "IPv6 source-dest route\n"
1315 "IPv6 source prefix\n"
1316 "IPv6 gateway address\n"
1317 "IPv6 gateway interface name\n"
1318 "Set tag for this route\n"
1320 "Distance value for this prefix\n"
1323 "Table to configure\n"
1324 "The table number to configure\n"
1327 struct static_vrf
*svrf
;
1328 struct static_vrf
*nh_svrf
;
1330 if (table_str
&& vrf
&& !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf
))) {
1332 "%% table param only available when running on netns-based vrfs\n");
1333 return CMD_WARNING_CONFIG_FAILED
;
1336 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1338 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1339 return CMD_WARNING_CONFIG_FAILED
;
1343 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1348 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1349 return CMD_WARNING_CONFIG_FAILED
;
1352 return static_route_leak(
1353 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1354 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1358 DEFPY(ipv6_route_vrf
,
1360 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1361 <X:X::X:X$gate|INTERFACE$ifname> \
1363 tag (1-4294967295) \
1366 |table (1-4294967295) \
1371 "Establish static routes\n"
1372 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1373 "IPv6 source-dest route\n"
1374 "IPv6 source prefix\n"
1375 "IPv6 gateway address\n"
1376 "IPv6 gateway interface name\n"
1377 "Set tag for this route\n"
1379 "Distance value for this prefix\n"
1381 "Table to configure\n"
1382 "The table number to configure\n"
1385 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1386 struct static_vrf
*svrf
= vrf
->info
;
1387 struct static_vrf
*nh_svrf
;
1389 if (table_str
&& !vrf_is_mapped_on_netns(vrf
)) {
1391 "%% table param only available when running on netns-based vrfs\n");
1392 return CMD_WARNING_CONFIG_FAILED
;
1396 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1401 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1402 return CMD_WARNING_CONFIG_FAILED
;
1405 return static_route_leak(
1406 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1407 from_str
, gate_str
, ifname
, NULL
, tag_str
, distance_str
, label
,
1411 DEFUN_NOSH (show_debugging_staticd
,
1412 show_debugging_staticd_cmd
,
1413 "show debugging [static]",
1416 "Static Information\n")
1418 vty_out(vty
, "Static debugging status\n");
1423 void static_vty_init(void)
1425 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1427 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1428 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1429 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1430 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1431 install_element(CONFIG_NODE
, &ip_route_cmd
);
1432 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1434 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1435 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1436 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1437 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1438 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1439 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1441 install_element(VIEW_NODE
, &show_debugging_staticd_cmd
);
1443 static_list
= list_new();
1444 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
1445 static_list
->del
= (void (*)(void *))static_list_delete
;