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"
38 static struct static_vrf
*static_vty_get_unknown_vrf(struct vty
*vty
,
41 struct static_vrf
*svrf
;
44 svrf
= static_vrf_lookup_by_name(vrf_name
);
49 vrf
= vrf_get(VRF_UNKNOWN
, vrf_name
);
51 vty_out(vty
, "%% Could not create vrf %s\n", vrf_name
);
56 vty_out(vty
, "%% Could not create vrf-info %s\n",
60 /* Mark as having FRR configuration */
61 vrf_set_user_cfged(vrf
);
66 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
)
91 /* extra (!s1 && !s2) to keep SA happy */
92 if (s1
== s2
|| (!s1
&& !s2
))
101 return strcmp(s1
, s2
);
104 static void static_list_delete(struct static_hold_route
*shr
)
106 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
107 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
108 XFREE(MTYPE_STATIC_ROUTE
, shr
->dest_str
);
109 XFREE(MTYPE_STATIC_ROUTE
, shr
->mask_str
);
110 XFREE(MTYPE_STATIC_ROUTE
, shr
->src_str
);
111 XFREE(MTYPE_STATIC_ROUTE
, shr
->gate_str
);
112 XFREE(MTYPE_STATIC_ROUTE
, shr
->ifname
);
113 XFREE(MTYPE_STATIC_ROUTE
, shr
->flag_str
);
114 XFREE(MTYPE_STATIC_ROUTE
, shr
->tag_str
);
115 XFREE(MTYPE_STATIC_ROUTE
, shr
->distance_str
);
116 XFREE(MTYPE_STATIC_ROUTE
, shr
->label_str
);
117 XFREE(MTYPE_STATIC_ROUTE
, shr
->table_str
);
119 XFREE(MTYPE_STATIC_ROUTE
, shr
);
122 static int static_list_compare(void *arg1
, void *arg2
)
124 struct static_hold_route
*shr1
= arg1
;
125 struct static_hold_route
*shr2
= arg2
;
128 ret
= strcmp(shr1
->vrf_name
, shr2
->vrf_name
);
132 ret
= strcmp(shr1
->nhvrf_name
, shr2
->nhvrf_name
);
136 ret
= shr1
->afi
- shr2
->afi
;
140 ret
= shr1
->safi
- shr2
->safi
;
144 ret
= prefix_cmp(&shr1
->dest
, &shr2
->dest
);
148 ret
= static_list_compare_helper(shr1
->src_str
, shr2
->src_str
);
152 ret
= static_list_compare_helper(shr1
->gate_str
, shr2
->gate_str
);
156 ret
= static_list_compare_helper(shr1
->ifname
, shr2
->ifname
);
160 ret
= static_list_compare_helper(shr1
->flag_str
, shr2
->flag_str
);
164 ret
= static_list_compare_helper(shr1
->tag_str
, shr2
->tag_str
);
168 ret
= static_list_compare_helper(shr1
->distance_str
,
173 ret
= static_list_compare_helper(shr1
->table_str
,
178 return static_list_compare_helper(shr1
->label_str
, shr2
->label_str
);
182 /* General function for static route. */
183 static int zebra_static_route_holdem(
184 struct static_vrf
*svrf
, struct static_vrf
*nh_svrf
, afi_t afi
,
185 safi_t safi
, const char *negate
, struct prefix
*dest
,
186 const char *dest_str
, const char *mask_str
, const char *src_str
,
187 const char *gate_str
, const char *ifname
, const char *flag_str
,
188 const char *tag_str
, const char *distance_str
, const char *label_str
,
189 const char *table_str
, bool onlink
)
191 struct static_hold_route
*shr
, *lookup
;
192 struct listnode
*node
;
194 zlog_warn("Static Route to %s not installed currently because dependent config not fully available",
197 shr
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(*shr
));
198 shr
->vrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, svrf
->vrf
->name
);
199 shr
->nhvrf_name
= XSTRDUP(MTYPE_STATIC_ROUTE
, nh_svrf
->vrf
->name
);
202 shr
->onlink
= onlink
;
204 prefix_copy(&shr
->dest
, dest
);
206 shr
->dest_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, dest_str
);
208 shr
->mask_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, mask_str
);
210 shr
->src_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, src_str
);
212 shr
->gate_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, gate_str
);
214 shr
->ifname
= XSTRDUP(MTYPE_STATIC_ROUTE
, ifname
);
216 shr
->flag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, flag_str
);
218 shr
->tag_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, tag_str
);
220 shr
->distance_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, distance_str
);
222 shr
->label_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, label_str
);
224 shr
->table_str
= XSTRDUP(MTYPE_STATIC_ROUTE
, table_str
);
226 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, lookup
)) {
227 if (static_list_compare(shr
, lookup
) == 0)
233 listnode_delete(static_list
, lookup
);
234 static_list_delete(shr
);
235 static_list_delete(lookup
);
241 * If a person enters the same line again
242 * we need to silently accept it
248 listnode_add_sort(static_list
, shr
);
253 XFREE(MTYPE_STATIC_ROUTE
, shr
->nhvrf_name
);
254 XFREE(MTYPE_STATIC_ROUTE
, shr
->vrf_name
);
255 XFREE(MTYPE_STATIC_ROUTE
, shr
);
260 static int static_route_leak(
261 struct vty
*vty
, struct static_vrf
*svrf
, struct static_vrf
*nh_svrf
,
262 afi_t afi
, safi_t safi
, const char *negate
, const char *dest_str
,
263 const char *mask_str
, const char *src_str
, const char *gate_str
,
264 const char *ifname
, const char *flag_str
, const char *tag_str
,
265 const char *distance_str
, const char *label_str
, const char *table_str
,
270 struct prefix p
, src
;
271 struct prefix_ipv6
*src_p
= NULL
;
273 union g_addr
*gatep
= NULL
;
275 enum static_blackhole_type bh_type
= 0;
278 struct static_nh_label snh_label
;
279 uint32_t table_id
= 0;
281 ret
= str2prefix(dest_str
, &p
);
284 vty_out(vty
, "%% Malformed address\n");
286 zlog_warn("%s: Malformed address: %s",
287 __PRETTY_FUNCTION__
, dest_str
);
288 return CMD_WARNING_CONFIG_FAILED
;
293 /* Cisco like mask notation. */
295 ret
= inet_aton(mask_str
, &mask
);
298 vty_out(vty
, "%% Malformed address\n");
300 zlog_warn("%s: Malformed address: %s",
303 return CMD_WARNING_CONFIG_FAILED
;
305 p
.prefixlen
= ip_masklen(mask
);
309 /* srcdest routing */
311 ret
= str2prefix(src_str
, &src
);
312 if (ret
<= 0 || src
.family
!= AF_INET6
) {
315 "%% Malformed source address\n");
318 "%s: Malformed source address: %s",
319 __PRETTY_FUNCTION__
, src_str
);
320 return CMD_WARNING_CONFIG_FAILED
;
322 src_p
= (struct prefix_ipv6
*)&src
;
329 /* Apply mask for given prefix. */
332 if (svrf
->vrf
->vrf_id
== VRF_UNKNOWN
333 || nh_svrf
->vrf
->vrf_id
== VRF_UNKNOWN
) {
334 vrf_set_user_cfged(svrf
->vrf
);
335 return zebra_static_route_holdem(
336 svrf
, nh_svrf
, afi
, safi
, negate
, &p
, dest_str
,
337 mask_str
, src_str
, gate_str
, ifname
, flag_str
, tag_str
,
338 distance_str
, label_str
, table_str
, onlink
);
342 /* table configured. check consistent with vrf config
344 if (svrf
->vrf
->data
.l
.table_id
!= RT_TABLE_MAIN
) {
347 "%% Table %s overlaps vrf table %u\n",
348 table_str
, svrf
->vrf
->data
.l
.table_id
);
351 "%s: Table %s overlaps vrf table %u",
353 table_str
, svrf
->vrf
->data
.l
.table_id
);
354 return CMD_WARNING_CONFIG_FAILED
;
358 /* Administrative distance. */
360 distance
= atoi(distance_str
);
362 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
366 tag
= strtoul(tag_str
, NULL
, 10);
369 memset(&snh_label
, 0, sizeof(struct static_nh_label
));
374 "%% MPLS not turned on in kernel, ignoring command\n");
377 "%s: MPLS not turned on in kernel ignoring static route to %s",
378 __PRETTY_FUNCTION__
, dest_str
);
379 return CMD_WARNING_CONFIG_FAILED
;
381 int rc
= mpls_str2label(label_str
, &snh_label
.num_labels
,
387 vty_out(vty
, "%% Malformed label(s)\n");
390 "%s: Malformed labels specified for route %s",
391 __PRETTY_FUNCTION__
, dest_str
);
396 "%% Cannot use reserved label(s) (%d-%d)\n",
397 MPLS_LABEL_RESERVED_MIN
,
398 MPLS_LABEL_RESERVED_MAX
);
401 "%s: Cannot use reserved labels (%d-%d) for %s",
403 MPLS_LABEL_RESERVED_MIN
,
404 MPLS_LABEL_RESERVED_MAX
,
410 "%% Too many labels. Enter %d or fewer\n",
414 "%s: Too many labels, Enter %d or fewer for %s",
416 MPLS_MAX_LABELS
, dest_str
);
419 return CMD_WARNING_CONFIG_FAILED
;
425 table_id
= atol(table_str
);
427 /* Null0 static route. */
428 if (ifname
!= NULL
) {
429 if (strcasecmp(ifname
, "Null0") == 0
430 || strcasecmp(ifname
, "reject") == 0
431 || strcasecmp(ifname
, "blackhole") == 0) {
434 "%% Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)\n");
437 "%s: %s: Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)",
438 __PRETTY_FUNCTION__
, dest_str
);
439 return CMD_WARNING_CONFIG_FAILED
;
445 switch (flag_str
[0]) {
447 bh_type
= STATIC_BLACKHOLE_REJECT
;
450 bh_type
= STATIC_BLACKHOLE_DROP
;
453 bh_type
= STATIC_BLACKHOLE_NULL
;
457 vty_out(vty
, "%% Malformed flag %s \n",
460 zlog_warn("%s: Malformed flag %s for %s",
461 __PRETTY_FUNCTION__
, flag_str
,
463 return CMD_WARNING_CONFIG_FAILED
;
468 if (inet_pton(afi2family(afi
), gate_str
, &gate
) != 1) {
471 "%% Malformed nexthop address %s\n",
475 "%s: Malformed nexthop address %s for %s",
476 __PRETTY_FUNCTION__
, gate_str
,
478 return CMD_WARNING_CONFIG_FAILED
;
482 if (afi
== AFI_IP
&& !negate
) {
483 if (if_lookup_exact_address(&gatep
->ipv4
, AF_INET
,
487 "%% Warning!! Local connected address is configured as Gateway IP(%s)\n",
489 } else if (afi
== AFI_IP6
&& !negate
) {
490 if (if_lookup_exact_address(&gatep
->ipv6
, AF_INET6
,
494 "%% Warning!! Local connected address is configured as Gateway IPv6(%s)\n",
500 if (gate_str
== NULL
&& ifname
== NULL
)
501 type
= STATIC_BLACKHOLE
;
502 else if (gate_str
&& ifname
) {
504 type
= STATIC_IPV4_GATEWAY_IFNAME
;
506 type
= STATIC_IPV6_GATEWAY_IFNAME
;
508 type
= STATIC_IFNAME
;
511 type
= STATIC_IPV4_GATEWAY
;
513 type
= STATIC_IPV6_GATEWAY
;
517 static_add_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
518 bh_type
, tag
, distance
, svrf
, nh_svrf
,
519 &snh_label
, table_id
, onlink
);
520 /* Mark as having FRR configuration */
521 vrf_set_user_cfged(svrf
->vrf
);
523 static_delete_route(afi
, safi
, type
, &p
, src_p
, gatep
, ifname
,
524 tag
, distance
, svrf
, &snh_label
, table_id
);
525 /* If no other FRR config for this VRF, mark accordingly. */
526 if (!static_vrf_has_config(svrf
))
527 vrf_reset_user_cfged(svrf
->vrf
);
533 static int static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
534 const char *negate
, const char *dest_str
,
535 const char *mask_str
, const char *src_str
,
536 const char *gate_str
, const char *ifname
,
537 const char *flag_str
, const char *tag_str
,
538 const char *distance_str
, const char *vrf_name
,
539 const char *label_str
, const char *table_str
)
541 struct static_vrf
*svrf
;
544 svrf
= static_vrf_lookup_by_name(vrf_name
);
546 /* When trying to delete, the VRF must exist. */
547 if (negate
&& !svrf
) {
548 vty_out(vty
, "%% vrf %s is not defined\n", vrf_name
);
549 return CMD_WARNING_CONFIG_FAILED
;
552 /* When trying to create, create the VRF if it doesn't exist.
553 * Note: The VRF isn't active until we hear about it from the kernel.
556 svrf
= static_vty_get_unknown_vrf(vty
, vrf_name
);
558 return CMD_WARNING_CONFIG_FAILED
;
560 return static_route_leak(vty
, svrf
, svrf
, afi
, safi
, negate
, dest_str
,
561 mask_str
, src_str
, gate_str
, ifname
, flag_str
,
562 tag_str
, distance_str
, label_str
, table_str
,
566 void static_config_install_delayed_routes(struct static_vrf
*svrf
)
568 struct listnode
*node
, *nnode
;
569 struct static_hold_route
*shr
;
570 struct static_vrf
*osvrf
, *nh_svrf
;
573 for (ALL_LIST_ELEMENTS(static_list
, node
, nnode
, shr
)) {
574 osvrf
= static_vrf_lookup_by_name(shr
->vrf_name
);
575 nh_svrf
= static_vrf_lookup_by_name(shr
->nhvrf_name
);
577 if (osvrf
!= svrf
&& nh_svrf
!= svrf
)
580 if (osvrf
->vrf
->vrf_id
== VRF_UNKNOWN
581 || nh_svrf
->vrf
->vrf_id
== VRF_UNKNOWN
)
584 installed
= static_route_leak(
585 NULL
, osvrf
, nh_svrf
, shr
->afi
, shr
->safi
, NULL
,
586 shr
->dest_str
, shr
->mask_str
, shr
->src_str
,
587 shr
->gate_str
, shr
->ifname
, shr
->flag_str
, shr
->tag_str
,
588 shr
->distance_str
, shr
->label_str
, shr
->table_str
,
591 if (installed
!= CMD_SUCCESS
)
593 "%s: Attempt to install %s as a route and it was rejected",
594 __PRETTY_FUNCTION__
, shr
->dest_str
);
595 listnode_delete(static_list
, shr
);
596 static_list_delete(shr
);
600 /* Write static route configuration. */
601 int static_config(struct vty
*vty
, struct static_vrf
*svrf
, afi_t afi
,
602 safi_t safi
, const char *cmd
)
604 struct static_hold_route
*shr
;
605 struct listnode
*node
;
607 struct route_node
*rn
;
608 struct static_route
*si
;
609 struct route_table
*stable
;
610 char buf
[SRCDEST2STR_BUFFER
];
613 stable
= svrf
->stable
[afi
][safi
];
617 sprintf(spacing
, "%s%s", (svrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ",
621 * Static routes for vrfs not fully inited
623 for (ALL_LIST_ELEMENTS_RO(static_list
, node
, shr
)) {
624 if (shr
->afi
!= afi
|| shr
->safi
!= safi
)
627 if (strcmp(svrf
->vrf
->name
, shr
->vrf_name
) != 0)
630 char dest_str
[PREFIX_STRLEN
];
632 prefix2str(&shr
->dest
, dest_str
, sizeof(dest_str
));
634 vty_out(vty
, "%s ", spacing
);
636 vty_out(vty
, "%s ", dest_str
);
638 vty_out(vty
, "from %s ", shr
->src_str
);
640 vty_out(vty
, "%s ", shr
->gate_str
);
642 vty_out(vty
, "%s ", shr
->ifname
);
644 vty_out(vty
, "%s ", shr
->flag_str
);
646 vty_out(vty
, "tag %s ", shr
->tag_str
);
647 if (shr
->distance_str
)
648 vty_out(vty
, "%s ", shr
->distance_str
);
650 vty_out(vty
, "label %s ", shr
->label_str
);
652 vty_out(vty
, "table %s", shr
->table_str
);
653 if (strcmp(shr
->vrf_name
, shr
->nhvrf_name
) != 0)
654 vty_out(vty
, "nexthop-vrf %s ", shr
->nhvrf_name
);
656 vty_out(vty
, "onlink");
660 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
))
661 for (si
= rn
->info
; si
; si
= si
->next
) {
662 vty_out(vty
, "%s %s", spacing
,
663 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
666 case STATIC_IPV4_GATEWAY
:
667 vty_out(vty
, " %s", inet_ntoa(si
->addr
.ipv4
));
669 case STATIC_IPV6_GATEWAY
:
671 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
675 vty_out(vty
, " %s", si
->ifname
);
677 case STATIC_BLACKHOLE
:
678 switch (si
->bh_type
) {
679 case STATIC_BLACKHOLE_DROP
:
680 vty_out(vty
, " blackhole");
682 case STATIC_BLACKHOLE_NULL
:
683 vty_out(vty
, " Null0");
685 case STATIC_BLACKHOLE_REJECT
:
686 vty_out(vty
, " reject");
690 case STATIC_IPV4_GATEWAY_IFNAME
:
691 vty_out(vty
, " %s %s",
692 inet_ntop(AF_INET
, &si
->addr
.ipv4
, buf
,
696 case STATIC_IPV6_GATEWAY_IFNAME
:
697 vty_out(vty
, " %s %s",
698 inet_ntop(AF_INET6
, &si
->addr
.ipv6
, buf
,
705 vty_out(vty
, " tag %" ROUTE_TAG_PRI
, si
->tag
);
707 if (si
->distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
)
708 vty_out(vty
, " %d", si
->distance
);
710 /* Label information */
711 if (si
->snh_label
.num_labels
)
712 vty_out(vty
, " label %s",
713 mpls_label2str(si
->snh_label
.num_labels
,
714 si
->snh_label
.label
, buf
,
717 if (si
->nh_vrf_id
!= si
->vrf_id
)
718 vty_out(vty
, " nexthop-vrf %s", si
->nh_vrfname
);
721 * table ID from VRF overrides configured
724 svrf
->vrf
->data
.l
.table_id
== RT_TABLE_MAIN
)
725 vty_out(vty
, " table %u", si
->table_id
);
728 vty_out(vty
, " onlink");
737 /* Static unicast routes for multicast RPF lookup. */
738 DEFPY (ip_mroute_dist
,
740 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
743 "Configure static unicast route into MRIB for multicast RPF lookup\n"
744 "IP destination prefix (e.g. 10.0.0.0/8)\n"
746 "Nexthop interface name\n"
749 return static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
750 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
751 distance_str
, NULL
, NULL
, NULL
);
754 /* Static route configuration. */
755 DEFPY(ip_route_blackhole
,
756 ip_route_blackhole_cmd
,
758 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
759 <reject|blackhole>$flag \
765 |table (1-4294967295) \
768 "Establish static routes\n"
769 "IP destination prefix (e.g. 10.0.0.0/8)\n"
770 "IP destination prefix\n"
771 "IP destination prefix mask\n"
772 "Emit an ICMP unreachable when matched\n"
773 "Silently discard pkts when matched\n"
774 "Set tag for this route\n"
776 "Distance value for this route\n"
779 "Table to configure\n"
780 "The table number to configure\n")
782 if (table_str
&& vrf
&& !vrf_is_backend_netns()) {
784 "%% table param only available when running on netns-based vrfs\n");
785 return CMD_WARNING_CONFIG_FAILED
;
788 return static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
789 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
790 distance_str
, vrf
, label
, table_str
);
793 DEFPY(ip_route_blackhole_vrf
,
794 ip_route_blackhole_vrf_cmd
,
796 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
797 <reject|blackhole>$flag \
802 |table (1-4294967295) \
805 "Establish static routes\n"
806 "IP destination prefix (e.g. 10.0.0.0/8)\n"
807 "IP destination prefix\n"
808 "IP destination prefix mask\n"
809 "Emit an ICMP unreachable when matched\n"
810 "Silently discard pkts when matched\n"
811 "Set tag for this route\n"
813 "Distance value for this route\n"
815 "Table to configure\n"
816 "The table number to configure\n")
818 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
819 struct static_vrf
*svrf
= vrf
->info
;
821 if (table_str
&& !vrf_is_backend_netns()) {
823 "%% table param only available when running on netns-based vrfs\n");
824 return CMD_WARNING_CONFIG_FAILED
;
828 * Coverity is complaining that prefix could
829 * be dereferenced, but we know that prefix will
830 * valid. Add an assert to make it happy
833 return static_route_leak(vty
, svrf
, svrf
, AFI_IP
, SAFI_UNICAST
, no
,
834 prefix
, mask_str
, NULL
, NULL
, NULL
, flag
,
835 tag_str
, distance_str
, label
, table_str
,
839 DEFPY(ip_route_address_interface
,
840 ip_route_address_interface_cmd
,
842 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
844 <INTERFACE|Null0>$ifname \
850 |table (1-4294967295) \
855 "Establish static routes\n"
856 "IP destination prefix (e.g. 10.0.0.0/8)\n"
857 "IP destination prefix\n"
858 "IP destination prefix mask\n"
859 "IP gateway address\n"
860 "IP gateway interface name\n"
862 "Set tag for this route\n"
864 "Distance value for this route\n"
867 "Table to configure\n"
868 "The table number to configure\n"
870 "Treat the nexthop as directly attached to the interface")
872 struct static_vrf
*svrf
;
873 struct static_vrf
*nh_svrf
;
874 const char *flag
= NULL
;
876 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
881 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
883 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
884 return CMD_WARNING_CONFIG_FAILED
;
887 if (table_str
&& vrf
&& !vrf_is_backend_netns()) {
889 "%% table param only available when running on netns-based vrfs\n");
890 return CMD_WARNING_CONFIG_FAILED
;
894 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
899 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
900 return CMD_WARNING_CONFIG_FAILED
;
903 return static_route_leak(vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
,
904 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
905 tag_str
, distance_str
, label
, table_str
,
909 DEFPY(ip_route_address_interface_vrf
,
910 ip_route_address_interface_vrf_cmd
,
912 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
914 <INTERFACE|Null0>$ifname \
919 |table (1-4294967295) \
924 "Establish static routes\n"
925 "IP destination prefix (e.g. 10.0.0.0/8)\n"
926 "IP destination prefix\n"
927 "IP destination prefix mask\n"
928 "IP gateway address\n"
929 "IP gateway interface name\n"
931 "Set tag for this route\n"
933 "Distance value for this route\n"
935 "Table to configure\n"
936 "The table number to configure\n"
938 "Treat the nexthop as directly attached to the interface")
940 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
941 const char *flag
= NULL
;
942 struct static_vrf
*svrf
= vrf
->info
;
943 struct static_vrf
*nh_svrf
;
945 if (table_str
&& !vrf_is_backend_netns()) {
947 "%% table param only available when running on netns-based vrfs\n");
948 return CMD_WARNING_CONFIG_FAILED
;
951 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
957 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
962 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
963 return CMD_WARNING_CONFIG_FAILED
;
966 return static_route_leak(vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
,
967 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
968 tag_str
, distance_str
, label
, table_str
,
975 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
976 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
982 |table (1-4294967295) \
986 "Establish static routes\n"
987 "IP destination prefix (e.g. 10.0.0.0/8)\n"
988 "IP destination prefix\n"
989 "IP destination prefix mask\n"
990 "IP gateway address\n"
991 "IP gateway interface name\n"
993 "Set tag for this route\n"
995 "Distance value for this route\n"
998 "Table to configure\n"
999 "The table number to configure\n"
1002 struct static_vrf
*svrf
;
1003 struct static_vrf
*nh_svrf
;
1004 const char *flag
= NULL
;
1006 if (table_str
&& vrf
&& !vrf_is_backend_netns()) {
1008 "%% table param only available when running on netns-based vrfs\n");
1009 return CMD_WARNING_CONFIG_FAILED
;
1012 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1017 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1019 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1020 return CMD_WARNING_CONFIG_FAILED
;
1024 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1029 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1030 return CMD_WARNING_CONFIG_FAILED
;
1033 return static_route_leak(
1034 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1035 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1042 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1043 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
1045 tag (1-4294967295) \
1048 |table (1-4294967295) \
1052 "Establish static routes\n"
1053 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1054 "IP destination prefix\n"
1055 "IP destination prefix mask\n"
1056 "IP gateway address\n"
1057 "IP gateway interface name\n"
1059 "Set tag for this route\n"
1061 "Distance value for this route\n"
1063 "Table to configure\n"
1064 "The table number to configure\n"
1067 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1068 struct static_vrf
*svrf
= vrf
->info
;
1069 struct static_vrf
*nh_svrf
;
1070 const char *flag
= NULL
;
1072 if (table_str
&& !vrf_is_backend_netns()) {
1074 "%% table param only available when running on netns-based vrfs\n");
1075 return CMD_WARNING_CONFIG_FAILED
;
1078 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1084 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1089 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1090 return CMD_WARNING_CONFIG_FAILED
;
1093 return static_route_leak(
1094 vty
, svrf
, nh_svrf
, AFI_IP
, SAFI_UNICAST
, no
, prefix
, mask_str
,
1095 NULL
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1099 DEFPY(ipv6_route_blackhole
,
1100 ipv6_route_blackhole_cmd
,
1101 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1102 <reject|blackhole>$flag \
1104 tag (1-4294967295) \
1108 |table (1-4294967295) \
1112 "Establish static routes\n"
1113 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1114 "IPv6 source-dest route\n"
1115 "IPv6 source prefix\n"
1116 "Emit an ICMP unreachable when matched\n"
1117 "Silently discard pkts when matched\n"
1118 "Set tag for this route\n"
1120 "Distance value for this prefix\n"
1123 "Table to configure\n"
1124 "The table number to configure\n")
1126 if (table_str
&& vrf
&& !vrf_is_backend_netns()) {
1128 "%% table param only available when running on netns-based vrfs\n");
1129 return CMD_WARNING_CONFIG_FAILED
;
1132 return static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
1133 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
1134 distance_str
, vrf
, label
, table_str
);
1137 DEFPY(ipv6_route_blackhole_vrf
,
1138 ipv6_route_blackhole_vrf_cmd
,
1139 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1140 <reject|blackhole>$flag \
1142 tag (1-4294967295) \
1145 |table (1-4294967295) \
1149 "Establish static routes\n"
1150 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1151 "IPv6 source-dest route\n"
1152 "IPv6 source prefix\n"
1153 "Emit an ICMP unreachable when matched\n"
1154 "Silently discard pkts when matched\n"
1155 "Set tag for this route\n"
1157 "Distance value for this prefix\n"
1159 "Table to configure\n"
1160 "The table number to configure\n")
1162 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1163 struct static_vrf
*svrf
= vrf
->info
;
1165 if (table_str
&& !vrf_is_backend_netns()) {
1167 "%% table param only available when running on netns-based vrfs\n");
1168 return CMD_WARNING_CONFIG_FAILED
;
1172 * Coverity is complaining that prefix could
1173 * be dereferenced, but we know that prefix will
1174 * valid. Add an assert to make it happy
1177 return static_route_leak(
1178 vty
, svrf
, svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1179 from_str
, NULL
, NULL
, flag
, tag_str
, distance_str
, label
,
1183 DEFPY(ipv6_route_address_interface
,
1184 ipv6_route_address_interface_cmd
,
1185 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1187 <INTERFACE|Null0>$ifname \
1189 tag (1-4294967295) \
1193 |table (1-4294967295) \
1199 "Establish static routes\n"
1200 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1201 "IPv6 source-dest route\n"
1202 "IPv6 source prefix\n"
1203 "IPv6 gateway address\n"
1204 "IPv6 gateway interface name\n"
1206 "Set tag for this route\n"
1208 "Distance value for this prefix\n"
1211 "Table to configure\n"
1212 "The table number to configure\n"
1214 "Treat the nexthop as directly attached to the interface")
1216 struct static_vrf
*svrf
;
1217 struct static_vrf
*nh_svrf
;
1218 const char *flag
= NULL
;
1220 if (table_str
&& vrf
&& !vrf_is_backend_netns()) {
1222 "%% table param only available when running on netns-based vrfs\n");
1223 return CMD_WARNING_CONFIG_FAILED
;
1226 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1228 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1229 return CMD_WARNING_CONFIG_FAILED
;
1233 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1238 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1239 return CMD_WARNING_CONFIG_FAILED
;
1242 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1247 return static_route_leak(
1248 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1249 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1250 table_str
, !!onlink
);
1253 DEFPY(ipv6_route_address_interface_vrf
,
1254 ipv6_route_address_interface_vrf_cmd
,
1255 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1257 <INTERFACE|Null0>$ifname \
1259 tag (1-4294967295) \
1262 |table (1-4294967295) \
1268 "Establish static routes\n"
1269 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1270 "IPv6 source-dest route\n"
1271 "IPv6 source prefix\n"
1272 "IPv6 gateway address\n"
1273 "IPv6 gateway interface name\n"
1275 "Set tag for this route\n"
1277 "Distance value for this prefix\n"
1279 "Table to configure\n"
1280 "The table number to configure\n"
1282 "Treat the nexthop as directly attached to the interface")
1284 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1285 struct static_vrf
*svrf
= vrf
->info
;
1286 struct static_vrf
*nh_svrf
;
1287 const char *flag
= NULL
;
1289 if (table_str
&& !vrf_is_backend_netns()) {
1291 "%% table param only available when running on netns-based vrfs\n");
1292 return CMD_WARNING_CONFIG_FAILED
;
1296 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1301 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1302 return CMD_WARNING_CONFIG_FAILED
;
1305 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1310 return static_route_leak(
1311 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1312 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1313 table_str
, !!onlink
);
1318 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1319 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1321 tag (1-4294967295) \
1325 |table (1-4294967295) \
1330 "Establish static routes\n"
1331 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1332 "IPv6 source-dest route\n"
1333 "IPv6 source prefix\n"
1334 "IPv6 gateway address\n"
1335 "IPv6 gateway interface name\n"
1337 "Set tag for this route\n"
1339 "Distance value for this prefix\n"
1342 "Table to configure\n"
1343 "The table number to configure\n"
1346 struct static_vrf
*svrf
;
1347 struct static_vrf
*nh_svrf
;
1348 const char *flag
= NULL
;
1350 if (table_str
&& vrf
&& !vrf_is_backend_netns()) {
1352 "%% table param only available when running on netns-based vrfs\n");
1353 return CMD_WARNING_CONFIG_FAILED
;
1356 svrf
= static_vty_get_unknown_vrf(vty
, vrf
);
1358 vty_out(vty
, "%% vrf %s is not defined\n", vrf
);
1359 return CMD_WARNING_CONFIG_FAILED
;
1363 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1368 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1369 return CMD_WARNING_CONFIG_FAILED
;
1372 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1377 return static_route_leak(
1378 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1379 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1383 DEFPY(ipv6_route_vrf
,
1385 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1386 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1388 tag (1-4294967295) \
1391 |table (1-4294967295) \
1396 "Establish static routes\n"
1397 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1398 "IPv6 source-dest route\n"
1399 "IPv6 source prefix\n"
1400 "IPv6 gateway address\n"
1401 "IPv6 gateway interface name\n"
1403 "Set tag for this route\n"
1405 "Distance value for this prefix\n"
1407 "Table to configure\n"
1408 "The table number to configure\n"
1411 VTY_DECLVAR_CONTEXT(vrf
, vrf
);
1412 struct static_vrf
*svrf
= vrf
->info
;
1413 struct static_vrf
*nh_svrf
;
1414 const char *flag
= NULL
;
1416 if (table_str
&& !vrf_is_backend_netns()) {
1418 "%% table param only available when running on netns-based vrfs\n");
1419 return CMD_WARNING_CONFIG_FAILED
;
1423 nh_svrf
= static_vty_get_unknown_vrf(vty
, nexthop_vrf
);
1428 vty_out(vty
, "%% nexthop vrf %s is not defined\n", nexthop_vrf
);
1429 return CMD_WARNING_CONFIG_FAILED
;
1432 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1437 return static_route_leak(
1438 vty
, svrf
, nh_svrf
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
, NULL
,
1439 from_str
, gate_str
, ifname
, flag
, tag_str
, distance_str
, label
,
1443 DEFUN_NOSH (show_debugging_staticd
,
1444 show_debugging_staticd_cmd
,
1445 "show debugging [static]",
1448 "Static Information\n")
1450 vty_out(vty
, "Static debugging status\n");
1455 void static_vty_init(void)
1457 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1459 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1460 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1461 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1462 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1463 install_element(CONFIG_NODE
, &ip_route_cmd
);
1464 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1466 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1467 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1468 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1469 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1470 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1471 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1473 install_element(VIEW_NODE
, &show_debugging_staticd_cmd
);
1475 static_list
= list_new();
1476 static_list
->cmp
= (int (*)(void *, void *))static_list_compare
;
1477 static_list
->del
= (void (*)(void *))static_list_delete
;