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"
30 #include "northbound.h"
32 #include "routing_nb.h"
33 #include "northbound_cli.h"
35 #include "static_vrf.h"
36 #include "static_memory.h"
37 #include "static_vty.h"
38 #include "static_routes.h"
39 #include "static_debug.h"
40 #ifndef VTYSH_EXTRACT_PL
41 #include "staticd/static_vty_clippy.c"
43 #include "static_nb.h"
45 #define STATICD_STR "Static route daemon\n"
47 static int static_route_leak(struct vty
*vty
, const char *svrf
,
48 const char *nh_svrf
, afi_t afi
, safi_t safi
,
49 const char *negate
, const char *dest_str
,
50 const char *mask_str
, const char *src_str
,
51 const char *gate_str
, const char *ifname
,
52 const char *flag_str
, const char *tag_str
,
53 const char *distance_str
, const char *label_str
,
54 const char *table_str
, bool onlink
,
55 const char *color_str
)
62 char xpath_prefix
[XPATH_MAXLEN
];
63 char xpath_nexthop
[XPATH_MAXLEN
];
64 char xpath_mpls
[XPATH_MAXLEN
];
65 char xpath_label
[XPATH_MAXLEN
];
66 char ab_xpath
[XPATH_MAXLEN
];
67 char buf_prefix
[PREFIX_STRLEN
];
68 char buf_src_prefix
[PREFIX_STRLEN
];
69 char buf_nh_type
[PREFIX_STRLEN
];
70 char buf_tag
[PREFIX_STRLEN
];
71 uint8_t label_stack_id
= 0;
72 const char *buf_gate_str
;
73 uint8_t distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
75 uint32_t table_id
= 0;
76 const struct lyd_node
*dnode
;
78 memset(buf_src_prefix
, 0, PREFIX_STRLEN
);
79 memset(buf_nh_type
, 0, PREFIX_STRLEN
);
81 ret
= str2prefix(dest_str
, &p
);
83 vty_out(vty
, "%% Malformed address\n");
84 return CMD_WARNING_CONFIG_FAILED
;
89 /* Cisco like mask notation. */
91 ret
= inet_aton(mask_str
, &mask
);
93 vty_out(vty
, "%% Malformed address\n");
94 return CMD_WARNING_CONFIG_FAILED
;
96 p
.prefixlen
= ip_masklen(mask
);
100 /* srcdest routing */
102 ret
= str2prefix(src_str
, &src
);
103 if (ret
<= 0 || src
.family
!= AF_INET6
) {
104 vty_out(vty
, "%% Malformed source address\n");
105 return CMD_WARNING_CONFIG_FAILED
;
113 /* Apply mask for given prefix. */
116 prefix2str(&p
, buf_prefix
, sizeof(buf_prefix
));
119 prefix2str(&src
, buf_src_prefix
, sizeof(buf_src_prefix
));
121 buf_gate_str
= gate_str
;
125 if (gate_str
== NULL
&& ifname
== NULL
)
126 type
= STATIC_BLACKHOLE
;
127 else if (gate_str
&& ifname
) {
129 type
= STATIC_IPV4_GATEWAY_IFNAME
;
131 type
= STATIC_IPV6_GATEWAY_IFNAME
;
133 type
= STATIC_IFNAME
;
136 type
= STATIC_IPV4_GATEWAY
;
138 type
= STATIC_IPV6_GATEWAY
;
141 /* Administrative distance. */
143 distance
= atoi(distance_str
);
145 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
149 tag
= strtoul(tag_str
, NULL
, 10);
153 table_id
= atol(table_str
);
155 static_get_nh_type(type
, buf_nh_type
, PREFIX_STRLEN
);
157 /* route + path procesing */
159 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
160 FRR_S_ROUTE_SRC_INFO_KEY_XPATH
,
161 "frr-staticd:staticd", "staticd", svrf
,
163 yang_afi_safi_value2identity(afi
, safi
),
164 buf_src_prefix
, table_id
, distance
);
166 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
167 FRR_STATIC_ROUTE_INFO_KEY_XPATH
,
168 "frr-staticd:staticd", "staticd", svrf
,
170 yang_afi_safi_value2identity(afi
, safi
),
173 nb_cli_enqueue_change(vty
, xpath_prefix
, NB_OP_CREATE
, NULL
);
176 snprintf(buf_tag
, sizeof(buf_tag
), "%u", tag
);
177 strlcpy(ab_xpath
, xpath_prefix
, sizeof(ab_xpath
));
178 strlcat(ab_xpath
, FRR_STATIC_ROUTE_PATH_TAG_XPATH
,
180 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_MODIFY
, buf_tag
);
182 /* nexthop processing */
184 snprintf(ab_xpath
, sizeof(ab_xpath
),
185 FRR_STATIC_ROUTE_NH_KEY_XPATH
, buf_nh_type
, nh_svrf
,
186 buf_gate_str
, ifname
);
187 strlcpy(xpath_nexthop
, xpath_prefix
, sizeof(xpath_nexthop
));
188 strlcat(xpath_nexthop
, ab_xpath
, sizeof(xpath_nexthop
));
189 nb_cli_enqueue_change(vty
, xpath_nexthop
, NB_OP_CREATE
, NULL
);
191 if (type
== STATIC_BLACKHOLE
) {
192 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
193 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_BH_XPATH
,
198 switch (flag_str
[0]) {
212 nb_cli_enqueue_change(vty
, ab_xpath
,
213 NB_OP_MODIFY
, bh_type
);
215 nb_cli_enqueue_change(vty
, ab_xpath
,
216 NB_OP_MODIFY
, "null");
219 if (type
== STATIC_IPV4_GATEWAY_IFNAME
220 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
221 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
222 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_ONLINK_XPATH
,
226 nb_cli_enqueue_change(vty
, ab_xpath
,
227 NB_OP_MODIFY
, "true");
229 nb_cli_enqueue_change(vty
, ab_xpath
,
230 NB_OP_MODIFY
, "false");
232 if (type
== STATIC_IPV4_GATEWAY
233 || type
== STATIC_IPV6_GATEWAY
234 || type
== STATIC_IPV4_GATEWAY_IFNAME
235 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
236 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
237 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_COLOR_XPATH
,
240 nb_cli_enqueue_change(vty
, ab_xpath
,
241 NB_OP_MODIFY
, color_str
);
244 /* copy of label string (start) */
246 /* pointer to next segment */
249 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
250 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
253 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
256 ostr
= XSTRDUP(MTYPE_TMP
, label_str
);
257 while ((nump
= strsep(&ostr
, "/")) != NULL
) {
258 snprintf(ab_xpath
, sizeof(ab_xpath
),
259 FRR_STATIC_ROUTE_NHLB_KEY_XPATH
,
261 strlcpy(xpath_label
, xpath_mpls
,
262 sizeof(xpath_label
));
263 strlcat(xpath_label
, ab_xpath
,
264 sizeof(xpath_label
));
265 nb_cli_enqueue_change(vty
, xpath_label
,
269 XFREE(MTYPE_TMP
, ostr
);
271 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
272 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
274 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
277 ret
= nb_cli_apply_changes(vty
, xpath_prefix
);
280 snprintf(ab_xpath
, sizeof(ab_xpath
),
281 FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH
,
282 "frr-staticd:staticd", "staticd", svrf
,
284 yang_afi_safi_value2identity(afi
, safi
),
285 buf_src_prefix
, table_id
, distance
,
286 buf_nh_type
, nh_svrf
, buf_gate_str
, ifname
);
288 snprintf(ab_xpath
, sizeof(ab_xpath
),
289 FRR_DEL_S_ROUTE_NH_KEY_XPATH
,
290 "frr-staticd:staticd", "staticd", svrf
,
292 yang_afi_safi_value2identity(afi
, safi
),
293 table_id
, distance
, buf_nh_type
, nh_svrf
,
294 buf_gate_str
, ifname
);
296 dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, ab_xpath
);
299 "%% Refusing to remove a non-existent route\n");
303 dnode
= yang_get_subtree_with_no_sibling(dnode
);
305 yang_dnode_get_path(dnode
, ab_xpath
, XPATH_MAXLEN
);
307 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_DESTROY
, NULL
);
308 ret
= nb_cli_apply_changes(vty
, ab_xpath
);
313 static int static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
314 const char *negate
, const char *dest_str
,
315 const char *mask_str
, const char *src_str
,
316 const char *gate_str
, const char *ifname
,
317 const char *flag_str
, const char *tag_str
,
318 const char *distance_str
, const char *vrf_name
,
319 const char *label_str
, const char *table_str
)
322 vrf_name
= VRF_DEFAULT_NAME
;
324 return static_route_leak(vty
, vrf_name
, vrf_name
, afi
, safi
, negate
,
325 dest_str
, mask_str
, src_str
, gate_str
, ifname
,
326 flag_str
, tag_str
, distance_str
, label_str
,
327 table_str
, false, NULL
);
330 /* Write static route configuration. */
331 int static_config(struct vty
*vty
, struct static_vrf
*svrf
, afi_t afi
,
332 safi_t safi
, const char *cmd
)
335 struct route_node
*rn
;
336 struct static_nexthop
*nh
;
337 struct static_path
*pn
;
338 struct route_table
*stable
;
339 struct static_route_info
*si
;
340 char buf
[SRCDEST2STR_BUFFER
];
342 struct stable_info
*info
;
344 stable
= svrf
->stable
[afi
][safi
];
348 snprintf(spacing
, sizeof(spacing
), "%s%s",
349 (svrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ", cmd
);
351 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
352 si
= static_route_info_from_rnode(rn
);
355 info
= static_get_stable_info(rn
);
356 frr_each(static_path_list
, &si
->path_list
, pn
) {
357 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
358 vty_out(vty
, "%s %s", spacing
,
359 srcdest_rnode2str(rn
, buf
,
363 case STATIC_IPV4_GATEWAY
:
364 vty_out(vty
, " %pI4", &nh
->addr
.ipv4
);
366 case STATIC_IPV6_GATEWAY
:
373 vty_out(vty
, " %s", nh
->ifname
);
375 case STATIC_BLACKHOLE
:
376 switch (nh
->bh_type
) {
377 case STATIC_BLACKHOLE_DROP
:
378 vty_out(vty
, " blackhole");
380 case STATIC_BLACKHOLE_NULL
:
381 vty_out(vty
, " Null0");
383 case STATIC_BLACKHOLE_REJECT
:
384 vty_out(vty
, " reject");
388 case STATIC_IPV4_GATEWAY_IFNAME
:
389 vty_out(vty
, " %s %s",
395 case STATIC_IPV6_GATEWAY_IFNAME
:
396 vty_out(vty
, " %s %s",
405 vty_out(vty
, " tag %" ROUTE_TAG_PRI
,
409 != ZEBRA_STATIC_DISTANCE_DEFAULT
)
410 vty_out(vty
, " %u", pn
->distance
);
412 /* Label information */
413 if (nh
->snh_label
.num_labels
)
414 vty_out(vty
, " label %s",
419 buf
, sizeof(buf
), 0));
421 if (!strmatch(nh
->nh_vrfname
,
422 info
->svrf
->vrf
->name
))
423 vty_out(vty
, " nexthop-vrf %s",
427 * table ID from VRF overrides
431 && svrf
->vrf
->data
.l
.table_id
433 vty_out(vty
, " table %u", pn
->table_id
);
436 vty_out(vty
, " onlink");
442 vty_out(vty
, " color %u", nh
->color
);
453 /* Static unicast routes for multicast RPF lookup. */
454 DEFPY_YANG (ip_mroute_dist
,
456 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
459 "Configure static unicast route into MRIB for multicast RPF lookup\n"
460 "IP destination prefix (e.g. 10.0.0.0/8)\n"
462 "Nexthop interface name\n"
465 return static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
466 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
467 distance_str
, NULL
, NULL
, NULL
);
470 /* Static route configuration. */
471 DEFPY_YANG(ip_route_blackhole
,
472 ip_route_blackhole_cmd
,
474 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
475 <reject|blackhole>$flag \
481 |table (1-4294967295) \
484 "Establish static routes\n"
485 "IP destination prefix (e.g. 10.0.0.0/8)\n"
486 "IP destination prefix\n"
487 "IP destination prefix mask\n"
488 "Emit an ICMP unreachable when matched\n"
489 "Silently discard pkts when matched\n"
490 "Set tag for this route\n"
492 "Distance value for this route\n"
495 "Table to configure\n"
496 "The table number to configure\n")
498 return static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
499 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
500 distance_str
, vrf
, label
, table_str
);
503 DEFPY_YANG(ip_route_blackhole_vrf
,
504 ip_route_blackhole_vrf_cmd
,
506 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
507 <reject|blackhole>$flag \
512 |table (1-4294967295) \
515 "Establish static routes\n"
516 "IP destination prefix (e.g. 10.0.0.0/8)\n"
517 "IP destination prefix\n"
518 "IP destination prefix mask\n"
519 "Emit an ICMP unreachable when matched\n"
520 "Silently discard pkts when matched\n"
521 "Set tag for this route\n"
523 "Distance value for this route\n"
525 "Table to configure\n"
526 "The table number to configure\n")
528 const struct lyd_node
*vrf_dnode
;
532 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
534 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
535 return CMD_WARNING_CONFIG_FAILED
;
537 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
539 * Coverity is complaining that prefix could
540 * be dereferenced, but we know that prefix will
541 * valid. Add an assert to make it happy
544 return static_route_leak(vty
, vrfname
, vrfname
, AFI_IP
, SAFI_UNICAST
,
545 no
, prefix
, mask_str
, NULL
, NULL
, NULL
, flag
,
546 tag_str
, distance_str
, label
, table_str
,
550 DEFPY_YANG(ip_route_address_interface
,
551 ip_route_address_interface_cmd
,
553 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
555 <INTERFACE|Null0>$ifname \
561 |table (1-4294967295) \
564 |color (1-4294967295) \
567 "Establish static routes\n"
568 "IP destination prefix (e.g. 10.0.0.0/8)\n"
569 "IP destination prefix\n"
570 "IP destination prefix mask\n"
571 "IP gateway address\n"
572 "IP gateway interface name\n"
574 "Set tag for this route\n"
576 "Distance value for this route\n"
579 "Table to configure\n"
580 "The table number to configure\n"
582 "Treat the nexthop as directly attached to the interface\n"
584 "The SR-TE color to configure\n")
587 const char *flag
= NULL
;
589 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
594 vrf
= VRF_DEFAULT_NAME
;
597 nh_vrf
= nexthop_vrf
;
601 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
602 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
603 tag_str
, distance_str
, label
, table_str
,
604 !!onlink
, color_str
);
607 DEFPY_YANG(ip_route_address_interface_vrf
,
608 ip_route_address_interface_vrf_cmd
,
610 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
612 <INTERFACE|Null0>$ifname \
617 |table (1-4294967295) \
620 |color (1-4294967295) \
623 "Establish static routes\n"
624 "IP destination prefix (e.g. 10.0.0.0/8)\n"
625 "IP destination prefix\n"
626 "IP destination prefix mask\n"
627 "IP gateway address\n"
628 "IP gateway interface name\n"
630 "Set tag for this route\n"
632 "Distance value for this route\n"
634 "Table to configure\n"
635 "The table number to configure\n"
637 "Treat the nexthop as directly attached to the interface\n"
639 "The SR-TE color to configure\n")
642 const char *flag
= NULL
;
643 const struct lyd_node
*vrf_dnode
;
647 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
649 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
650 return CMD_WARNING_CONFIG_FAILED
;
652 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
654 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
659 nh_vrf
= nexthop_vrf
;
663 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
664 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
665 tag_str
, distance_str
, label
, table_str
,
666 !!onlink
, color_str
);
672 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
673 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
679 |table (1-4294967295) \
681 |color (1-4294967295) \
684 "Establish static routes\n"
685 "IP destination prefix (e.g. 10.0.0.0/8)\n"
686 "IP destination prefix\n"
687 "IP destination prefix mask\n"
688 "IP gateway address\n"
689 "IP gateway interface name\n"
691 "Set tag for this route\n"
693 "Distance value for this route\n"
696 "Table to configure\n"
697 "The table number to configure\n"
700 "The SR-TE color to configure\n")
703 const char *flag
= NULL
;
705 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
711 vrf
= VRF_DEFAULT_NAME
;
714 nh_vrf
= nexthop_vrf
;
718 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
719 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
720 tag_str
, distance_str
, label
, table_str
,
724 DEFPY_YANG(ip_route_vrf
,
727 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
728 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
733 |table (1-4294967295) \
735 |color (1-4294967295) \
738 "Establish static routes\n"
739 "IP destination prefix (e.g. 10.0.0.0/8)\n"
740 "IP destination prefix\n"
741 "IP destination prefix mask\n"
742 "IP gateway address\n"
743 "IP gateway interface name\n"
745 "Set tag for this route\n"
747 "Distance value for this route\n"
749 "Table to configure\n"
750 "The table number to configure\n"
753 "The SR-TE color to configure\n")
756 const char *flag
= NULL
;
757 const struct lyd_node
*vrf_dnode
;
761 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
763 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
764 return CMD_WARNING_CONFIG_FAILED
;
767 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
769 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
774 nh_vrf
= nexthop_vrf
;
778 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
779 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
780 tag_str
, distance_str
, label
, table_str
,
784 DEFPY_YANG(ipv6_route_blackhole
,
785 ipv6_route_blackhole_cmd
,
786 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
787 <reject|blackhole>$flag \
793 |table (1-4294967295) \
797 "Establish static routes\n"
798 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
799 "IPv6 source-dest route\n"
800 "IPv6 source prefix\n"
801 "Emit an ICMP unreachable when matched\n"
802 "Silently discard pkts when matched\n"
803 "Set tag for this route\n"
805 "Distance value for this prefix\n"
808 "Table to configure\n"
809 "The table number to configure\n")
811 return static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
812 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
813 distance_str
, vrf
, label
, table_str
);
816 DEFPY_YANG(ipv6_route_blackhole_vrf
,
817 ipv6_route_blackhole_vrf_cmd
,
818 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
819 <reject|blackhole>$flag \
824 |table (1-4294967295) \
828 "Establish static routes\n"
829 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
830 "IPv6 source-dest route\n"
831 "IPv6 source prefix\n"
832 "Emit an ICMP unreachable when matched\n"
833 "Silently discard pkts when matched\n"
834 "Set tag for this route\n"
836 "Distance value for this prefix\n"
838 "Table to configure\n"
839 "The table number to configure\n")
841 const struct lyd_node
*vrf_dnode
;
845 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
847 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
848 return CMD_WARNING_CONFIG_FAILED
;
850 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
853 * Coverity is complaining that prefix could
854 * be dereferenced, but we know that prefix will
855 * valid. Add an assert to make it happy
859 return static_route_leak(vty
, vrfname
, vrfname
, AFI_IP6
, SAFI_UNICAST
,
860 no
, prefix_str
, NULL
, from_str
, NULL
, NULL
,
861 flag
, tag_str
, distance_str
, label
, table_str
,
865 DEFPY_YANG(ipv6_route_address_interface
,
866 ipv6_route_address_interface_cmd
,
867 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
869 <INTERFACE|Null0>$ifname \
875 |table (1-4294967295) \
878 |color (1-4294967295) \
882 "Establish static routes\n"
883 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
884 "IPv6 source-dest route\n"
885 "IPv6 source prefix\n"
886 "IPv6 gateway address\n"
887 "IPv6 gateway interface name\n"
889 "Set tag for this route\n"
891 "Distance value for this prefix\n"
894 "Table to configure\n"
895 "The table number to configure\n"
897 "Treat the nexthop as directly attached to the interface\n"
899 "The SR-TE color to configure\n")
902 const char *flag
= NULL
;
904 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
910 vrf
= VRF_DEFAULT_NAME
;
913 nh_vrf
= nexthop_vrf
;
917 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
, no
,
918 prefix_str
, NULL
, from_str
, gate_str
, ifname
,
919 flag
, tag_str
, distance_str
, label
, table_str
,
920 !!onlink
, color_str
);
923 DEFPY_YANG(ipv6_route_address_interface_vrf
,
924 ipv6_route_address_interface_vrf_cmd
,
925 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
927 <INTERFACE|Null0>$ifname \
932 |table (1-4294967295) \
935 |color (1-4294967295) \
939 "Establish static routes\n"
940 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
941 "IPv6 source-dest route\n"
942 "IPv6 source prefix\n"
943 "IPv6 gateway address\n"
944 "IPv6 gateway interface name\n"
946 "Set tag for this route\n"
948 "Distance value for this prefix\n"
950 "Table to configure\n"
951 "The table number to configure\n"
953 "Treat the nexthop as directly attached to the interface\n"
955 "The SR-TE color to configure\n")
958 const char *flag
= NULL
;
959 const struct lyd_node
*vrf_dnode
;
963 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
965 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
966 return CMD_WARNING_CONFIG_FAILED
;
968 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
971 nh_vrf
= nexthop_vrf
;
975 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
979 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
,
980 no
, prefix_str
, NULL
, from_str
, gate_str
,
981 ifname
, flag
, tag_str
, distance_str
, label
,
982 table_str
, !!onlink
, color_str
);
985 DEFPY_YANG(ipv6_route
,
987 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
988 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
994 |table (1-4294967295) \
996 |color (1-4294967295) \
1000 "Establish static routes\n"
1001 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1002 "IPv6 source-dest route\n"
1003 "IPv6 source prefix\n"
1004 "IPv6 gateway address\n"
1005 "IPv6 gateway interface name\n"
1007 "Set tag for this route\n"
1009 "Distance value for this prefix\n"
1012 "Table to configure\n"
1013 "The table number to configure\n"
1016 "The SR-TE color to configure\n")
1019 const char *flag
= NULL
;
1022 vrf
= VRF_DEFAULT_NAME
;
1025 nh_vrf
= nexthop_vrf
;
1029 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1033 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
, no
,
1034 prefix_str
, NULL
, from_str
, gate_str
, ifname
,
1035 flag
, tag_str
, distance_str
, label
, table_str
,
1039 DEFPY_YANG(ipv6_route_vrf
,
1041 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1042 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1044 tag (1-4294967295) \
1047 |table (1-4294967295) \
1049 |color (1-4294967295) \
1053 "Establish static routes\n"
1054 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1055 "IPv6 source-dest route\n"
1056 "IPv6 source prefix\n"
1057 "IPv6 gateway address\n"
1058 "IPv6 gateway interface name\n"
1060 "Set tag for this route\n"
1062 "Distance value for this prefix\n"
1064 "Table to configure\n"
1065 "The table number to configure\n"
1068 "The SR-TE color to configure\n")
1071 const char *flag
= NULL
;
1072 const struct lyd_node
*vrf_dnode
;
1073 const char *vrfname
;
1076 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
1078 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
1079 return CMD_WARNING_CONFIG_FAILED
;
1081 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
1084 nh_vrf
= nexthop_vrf
;
1088 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1092 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
,
1093 no
, prefix_str
, NULL
, from_str
, gate_str
,
1094 ifname
, flag
, tag_str
, distance_str
, label
,
1095 table_str
, false, color_str
);
1097 DEFPY_YANG(debug_staticd
, debug_staticd_cmd
,
1098 "[no] debug static [{events$events|route$route}]",
1099 NO_STR DEBUG_STR STATICD_STR
1103 /* If no specific category, change all */
1104 if (strmatch(argv
[argc
- 1]->text
, "static"))
1105 static_debug_set(vty
->node
, !no
, true, true);
1107 static_debug_set(vty
->node
, !no
, !!events
, !!route
);
1112 DEFUN_NOSH (show_debugging_static
,
1113 show_debugging_static_cmd
,
1114 "show debugging [static]",
1117 "Static Information\n")
1119 vty_out(vty
, "Staticd debugging status\n");
1121 static_debug_status_write(vty
);
1126 static struct cmd_node debug_node
= {
1130 .config_write
= static_config_write_debug
,
1133 void static_vty_init(void)
1135 install_node(&debug_node
);
1137 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1139 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1140 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1141 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1142 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1143 install_element(CONFIG_NODE
, &ip_route_cmd
);
1144 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1146 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1147 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1148 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1149 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1150 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1151 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1153 install_element(ENABLE_NODE
, &show_debugging_static_cmd
);
1154 install_element(ENABLE_NODE
, &debug_staticd_cmd
);
1155 install_element(CONFIG_NODE
, &debug_staticd_cmd
);