]> git.proxmox.com Git - mirror_frr.git/blob - staticd/static_vty.c
Merge pull request #5787 from karamalla0406/rmac_check
[mirror_frr.git] / staticd / static_vty.c
1 /*
2 * STATICd - vty code
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
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)
9 * any later version.
10 *
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
14 * more details.
15 *
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
19 */
20 #include <zebra.h>
21
22 #include "command.h"
23 #include "vty.h"
24 #include "vrf.h"
25 #include "prefix.h"
26 #include "nexthop.h"
27 #include "table.h"
28 #include "srcdest_table.h"
29 #include "mpls.h"
30
31 #include "static_vrf.h"
32 #include "static_memory.h"
33 #include "static_vty.h"
34 #include "static_routes.h"
35 #include "static_debug.h"
36 #ifndef VTYSH_EXTRACT_PL
37 #include "staticd/static_vty_clippy.c"
38 #endif
39
40 #define STATICD_STR "Static route daemon\n"
41
42 static struct static_vrf *static_vty_get_unknown_vrf(struct vty *vty,
43 const char *vrf_name)
44 {
45 struct static_vrf *svrf;
46 struct vrf *vrf;
47
48 svrf = static_vrf_lookup_by_name(vrf_name);
49
50 if (svrf)
51 return svrf;
52
53 vrf = vrf_get(VRF_UNKNOWN, vrf_name);
54 if (!vrf) {
55 vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
56 return NULL;
57 }
58 svrf = vrf->info;
59 if (!svrf) {
60 vty_out(vty, "%% Could not create vrf-info %s\n",
61 vrf_name);
62 return NULL;
63 }
64 /* Mark as having FRR configuration */
65 vrf_set_user_cfged(vrf);
66
67 return svrf;
68 }
69
70 struct static_hold_route {
71 char *vrf_name;
72 char *nhvrf_name;
73 afi_t afi;
74 safi_t safi;
75 char *dest_str;
76 char *mask_str;
77 char *src_str;
78 char *gate_str;
79 char *ifname;
80 char *flag_str;
81 char *tag_str;
82 char *distance_str;
83 char *label_str;
84 char *table_str;
85 bool onlink;
86
87 /* processed & masked destination, used for config display */
88 struct prefix dest;
89 };
90
91 static struct list *static_list;
92
93 static int static_list_compare_helper(const char *s1, const char *s2)
94 {
95 /* extra (!s1 && !s2) to keep SA happy */
96 if (s1 == s2 || (!s1 && !s2))
97 return 0;
98
99 if (!s1 && s2)
100 return -1;
101
102 if (s1 && !s2)
103 return 1;
104
105 return strcmp(s1, s2);
106 }
107
108 static void static_list_delete(struct static_hold_route *shr)
109 {
110 XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
111 XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
112 XFREE(MTYPE_STATIC_ROUTE, shr->dest_str);
113 XFREE(MTYPE_STATIC_ROUTE, shr->mask_str);
114 XFREE(MTYPE_STATIC_ROUTE, shr->src_str);
115 XFREE(MTYPE_STATIC_ROUTE, shr->gate_str);
116 XFREE(MTYPE_STATIC_ROUTE, shr->ifname);
117 XFREE(MTYPE_STATIC_ROUTE, shr->flag_str);
118 XFREE(MTYPE_STATIC_ROUTE, shr->tag_str);
119 XFREE(MTYPE_STATIC_ROUTE, shr->distance_str);
120 XFREE(MTYPE_STATIC_ROUTE, shr->label_str);
121 XFREE(MTYPE_STATIC_ROUTE, shr->table_str);
122
123 XFREE(MTYPE_STATIC_ROUTE, shr);
124 }
125
126 static int static_list_compare(void *arg1, void *arg2)
127 {
128 struct static_hold_route *shr1 = arg1;
129 struct static_hold_route *shr2 = arg2;
130 int ret;
131
132 ret = strcmp(shr1->vrf_name, shr2->vrf_name);
133 if (ret)
134 return ret;
135
136 ret = strcmp(shr1->nhvrf_name, shr2->nhvrf_name);
137 if (ret)
138 return ret;
139
140 ret = shr1->afi - shr2->afi;
141 if (ret)
142 return ret;
143
144 ret = shr1->safi - shr2->safi;
145 if (ret)
146 return ret;
147
148 ret = prefix_cmp(&shr1->dest, &shr2->dest);
149 if (ret)
150 return ret;
151
152 ret = static_list_compare_helper(shr1->src_str, shr2->src_str);
153 if (ret)
154 return ret;
155
156 ret = static_list_compare_helper(shr1->gate_str, shr2->gate_str);
157 if (ret)
158 return ret;
159
160 ret = static_list_compare_helper(shr1->ifname, shr2->ifname);
161 if (ret)
162 return ret;
163
164 ret = static_list_compare_helper(shr1->flag_str, shr2->flag_str);
165 if (ret)
166 return ret;
167
168 ret = static_list_compare_helper(shr1->tag_str, shr2->tag_str);
169 if (ret)
170 return ret;
171
172 ret = static_list_compare_helper(shr1->distance_str,
173 shr2->distance_str);
174 if (ret)
175 return ret;
176
177 ret = static_list_compare_helper(shr1->table_str,
178 shr2->table_str);
179 if (ret)
180 return ret;
181
182 return static_list_compare_helper(shr1->label_str, shr2->label_str);
183 }
184
185
186 /* General function for static route. */
187 static int zebra_static_route_holdem(
188 struct static_vrf *svrf, struct static_vrf *nh_svrf, afi_t afi,
189 safi_t safi, const char *negate, struct prefix *dest,
190 const char *dest_str, const char *mask_str, const char *src_str,
191 const char *gate_str, const char *ifname, const char *flag_str,
192 const char *tag_str, const char *distance_str, const char *label_str,
193 const char *table_str, bool onlink)
194 {
195 struct static_hold_route *shr, *lookup;
196 struct listnode *node;
197
198 zlog_warn("Static Route to %s not installed currently because dependent config not fully available",
199 dest_str);
200
201 shr = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(*shr));
202 shr->vrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, svrf->vrf->name);
203 shr->nhvrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, nh_svrf->vrf->name);
204 shr->afi = afi;
205 shr->safi = safi;
206 shr->onlink = onlink;
207 if (dest)
208 prefix_copy(&shr->dest, dest);
209 if (dest_str)
210 shr->dest_str = XSTRDUP(MTYPE_STATIC_ROUTE, dest_str);
211 if (mask_str)
212 shr->mask_str = XSTRDUP(MTYPE_STATIC_ROUTE, mask_str);
213 if (src_str)
214 shr->src_str = XSTRDUP(MTYPE_STATIC_ROUTE, src_str);
215 if (gate_str)
216 shr->gate_str = XSTRDUP(MTYPE_STATIC_ROUTE, gate_str);
217 if (ifname)
218 shr->ifname = XSTRDUP(MTYPE_STATIC_ROUTE, ifname);
219 if (flag_str)
220 shr->flag_str = XSTRDUP(MTYPE_STATIC_ROUTE, flag_str);
221 if (tag_str)
222 shr->tag_str = XSTRDUP(MTYPE_STATIC_ROUTE, tag_str);
223 if (distance_str)
224 shr->distance_str = XSTRDUP(MTYPE_STATIC_ROUTE, distance_str);
225 if (label_str)
226 shr->label_str = XSTRDUP(MTYPE_STATIC_ROUTE, label_str);
227 if (table_str)
228 shr->table_str = XSTRDUP(MTYPE_STATIC_ROUTE, table_str);
229
230 for (ALL_LIST_ELEMENTS_RO(static_list, node, lookup)) {
231 if (static_list_compare(shr, lookup) == 0)
232 break;
233 }
234
235 if (lookup) {
236 if (negate) {
237 listnode_delete(static_list, lookup);
238 static_list_delete(shr);
239 static_list_delete(lookup);
240
241 return CMD_SUCCESS;
242 }
243
244 /*
245 * If a person enters the same line again
246 * we need to silently accept it
247 */
248 goto shr_cleanup;
249 }
250
251 if (!negate) {
252 listnode_add_sort(static_list, shr);
253 return CMD_SUCCESS;
254 }
255
256 shr_cleanup:
257 XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
258 XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
259 XFREE(MTYPE_STATIC_ROUTE, shr);
260
261 return CMD_SUCCESS;
262 }
263
264 static int static_route_leak(
265 struct vty *vty, struct static_vrf *svrf, struct static_vrf *nh_svrf,
266 afi_t afi, safi_t safi, const char *negate, const char *dest_str,
267 const char *mask_str, const char *src_str, const char *gate_str,
268 const char *ifname, const char *flag_str, const char *tag_str,
269 const char *distance_str, const char *label_str, const char *table_str,
270 bool onlink)
271 {
272 int ret;
273 uint8_t distance;
274 struct prefix p, src;
275 struct prefix_ipv6 *src_p = NULL;
276 union g_addr gate;
277 union g_addr *gatep = NULL;
278 struct in_addr mask;
279 enum static_blackhole_type bh_type = 0;
280 route_tag_t tag = 0;
281 uint8_t type;
282 struct static_nh_label snh_label;
283 uint32_t table_id = 0;
284
285 ret = str2prefix(dest_str, &p);
286 if (ret <= 0) {
287 if (vty)
288 vty_out(vty, "%% Malformed address\n");
289 else
290 zlog_warn("%s: Malformed address: %s",
291 __PRETTY_FUNCTION__, dest_str);
292 return CMD_WARNING_CONFIG_FAILED;
293 }
294
295 switch (afi) {
296 case AFI_IP:
297 /* Cisco like mask notation. */
298 if (mask_str) {
299 ret = inet_aton(mask_str, &mask);
300 if (ret == 0) {
301 if (vty)
302 vty_out(vty, "%% Malformed address\n");
303 else
304 zlog_warn("%s: Malformed address: %s",
305 __PRETTY_FUNCTION__,
306 mask_str);
307 return CMD_WARNING_CONFIG_FAILED;
308 }
309 p.prefixlen = ip_masklen(mask);
310 }
311 break;
312 case AFI_IP6:
313 /* srcdest routing */
314 if (src_str) {
315 ret = str2prefix(src_str, &src);
316 if (ret <= 0 || src.family != AF_INET6) {
317 if (vty)
318 vty_out(vty,
319 "%% Malformed source address\n");
320 else
321 zlog_warn(
322 "%s: Malformed source address: %s",
323 __PRETTY_FUNCTION__, src_str);
324 return CMD_WARNING_CONFIG_FAILED;
325 }
326 src_p = (struct prefix_ipv6 *)&src;
327 }
328 break;
329 default:
330 break;
331 }
332
333 /* Apply mask for given prefix. */
334 apply_mask(&p);
335
336 if (svrf->vrf->vrf_id == VRF_UNKNOWN
337 || nh_svrf->vrf->vrf_id == VRF_UNKNOWN) {
338 vrf_set_user_cfged(svrf->vrf);
339 return zebra_static_route_holdem(
340 svrf, nh_svrf, afi, safi, negate, &p, dest_str,
341 mask_str, src_str, gate_str, ifname, flag_str, tag_str,
342 distance_str, label_str, table_str, onlink);
343 }
344
345 if (table_str) {
346 /* table configured. check consistent with vrf config
347 */
348 if (svrf->vrf->data.l.table_id != RT_TABLE_MAIN) {
349 if (vty)
350 vty_out(vty,
351 "%% Table %s overlaps vrf table %u\n",
352 table_str, svrf->vrf->data.l.table_id);
353 else
354 zlog_warn(
355 "%s: Table %s overlaps vrf table %u",
356 __PRETTY_FUNCTION__,
357 table_str, svrf->vrf->data.l.table_id);
358 return CMD_WARNING_CONFIG_FAILED;
359 }
360 }
361
362 /* Administrative distance. */
363 if (distance_str)
364 distance = atoi(distance_str);
365 else
366 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
367
368 /* tag */
369 if (tag_str)
370 tag = strtoul(tag_str, NULL, 10);
371
372 /* Labels */
373 memset(&snh_label, 0, sizeof(struct static_nh_label));
374 if (label_str) {
375 if (!mpls_enabled) {
376 if (vty)
377 vty_out(vty,
378 "%% MPLS not turned on in kernel, ignoring command\n");
379 else
380 zlog_warn(
381 "%s: MPLS not turned on in kernel ignoring static route to %s",
382 __PRETTY_FUNCTION__, dest_str);
383 return CMD_WARNING_CONFIG_FAILED;
384 }
385 int rc = mpls_str2label(label_str, &snh_label.num_labels,
386 snh_label.label);
387 if (rc < 0) {
388 switch (rc) {
389 case -1:
390 if (vty)
391 vty_out(vty, "%% Malformed label(s)\n");
392 else
393 zlog_warn(
394 "%s: Malformed labels specified for route %s",
395 __PRETTY_FUNCTION__, dest_str);
396 break;
397 case -2:
398 if (vty)
399 vty_out(vty,
400 "%% Cannot use reserved label(s) (%d-%d)\n",
401 MPLS_LABEL_RESERVED_MIN,
402 MPLS_LABEL_RESERVED_MAX);
403 else
404 zlog_warn(
405 "%s: Cannot use reserved labels (%d-%d) for %s",
406 __PRETTY_FUNCTION__,
407 MPLS_LABEL_RESERVED_MIN,
408 MPLS_LABEL_RESERVED_MAX,
409 dest_str);
410 break;
411 case -3:
412 if (vty)
413 vty_out(vty,
414 "%% Too many labels. Enter %d or fewer\n",
415 MPLS_MAX_LABELS);
416 else
417 zlog_warn(
418 "%s: Too many labels, Enter %d or fewer for %s",
419 __PRETTY_FUNCTION__,
420 MPLS_MAX_LABELS, dest_str);
421 break;
422 }
423 return CMD_WARNING_CONFIG_FAILED;
424 }
425 }
426
427 /* TableID */
428 if (table_str)
429 table_id = atol(table_str);
430
431 /* Null0 static route. */
432 if (ifname != NULL) {
433 if (strcasecmp(ifname, "Null0") == 0
434 || strcasecmp(ifname, "reject") == 0
435 || strcasecmp(ifname, "blackhole") == 0) {
436 if (vty)
437 vty_out(vty,
438 "%% Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)\n");
439 else
440 zlog_warn(
441 "%s: %s: Nexthop interface name can not be from reserved keywords (Null0, reject, blackhole)",
442 __PRETTY_FUNCTION__, dest_str);
443 return CMD_WARNING_CONFIG_FAILED;
444 }
445 }
446
447 /* Route flags */
448 if (flag_str) {
449 switch (flag_str[0]) {
450 case 'r':
451 bh_type = STATIC_BLACKHOLE_REJECT;
452 break;
453 case 'b':
454 bh_type = STATIC_BLACKHOLE_DROP;
455 break;
456 case 'N':
457 bh_type = STATIC_BLACKHOLE_NULL;
458 break;
459 default:
460 if (vty)
461 vty_out(vty, "%% Malformed flag %s \n",
462 flag_str);
463 else
464 zlog_warn("%s: Malformed flag %s for %s",
465 __PRETTY_FUNCTION__, flag_str,
466 dest_str);
467 return CMD_WARNING_CONFIG_FAILED;
468 }
469 }
470
471 if (gate_str) {
472 if (inet_pton(afi2family(afi), gate_str, &gate) != 1) {
473 if (vty)
474 vty_out(vty,
475 "%% Malformed nexthop address %s\n",
476 gate_str);
477 else
478 zlog_warn(
479 "%s: Malformed nexthop address %s for %s",
480 __PRETTY_FUNCTION__, gate_str,
481 dest_str);
482 return CMD_WARNING_CONFIG_FAILED;
483 }
484 gatep = &gate;
485
486 if (afi == AFI_IP && !negate) {
487 if (if_lookup_exact_address(&gatep->ipv4, AF_INET,
488 svrf->vrf->vrf_id))
489 if (vty)
490 vty_out(vty,
491 "%% Warning!! Local connected address is configured as Gateway IP(%s)\n",
492 gate_str);
493 } else if (afi == AFI_IP6 && !negate) {
494 if (if_lookup_exact_address(&gatep->ipv6, AF_INET6,
495 svrf->vrf->vrf_id))
496 if (vty)
497 vty_out(vty,
498 "%% Warning!! Local connected address is configured as Gateway IPv6(%s)\n",
499 gate_str);
500 }
501
502 }
503
504 if (gate_str == NULL && ifname == NULL)
505 type = STATIC_BLACKHOLE;
506 else if (gate_str && ifname) {
507 if (afi == AFI_IP)
508 type = STATIC_IPV4_GATEWAY_IFNAME;
509 else
510 type = STATIC_IPV6_GATEWAY_IFNAME;
511 } else if (ifname)
512 type = STATIC_IFNAME;
513 else {
514 if (afi == AFI_IP)
515 type = STATIC_IPV4_GATEWAY;
516 else
517 type = STATIC_IPV6_GATEWAY;
518 }
519
520 if (!negate) {
521 static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
522 bh_type, tag, distance, svrf, nh_svrf,
523 &snh_label, table_id, onlink);
524 /* Mark as having FRR configuration */
525 vrf_set_user_cfged(svrf->vrf);
526 } else {
527 static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
528 tag, distance, svrf, &snh_label, table_id);
529 /* If no other FRR config for this VRF, mark accordingly. */
530 if (!static_vrf_has_config(svrf))
531 vrf_reset_user_cfged(svrf->vrf);
532 }
533
534 return CMD_SUCCESS;
535 }
536
537 static int static_route(struct vty *vty, afi_t afi, safi_t safi,
538 const char *negate, const char *dest_str,
539 const char *mask_str, const char *src_str,
540 const char *gate_str, const char *ifname,
541 const char *flag_str, const char *tag_str,
542 const char *distance_str, const char *vrf_name,
543 const char *label_str, const char *table_str)
544 {
545 struct static_vrf *svrf;
546
547 /* VRF id */
548 svrf = static_vrf_lookup_by_name(vrf_name);
549
550 /* When trying to delete, the VRF must exist. */
551 if (negate && !svrf) {
552 vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
553 return CMD_WARNING_CONFIG_FAILED;
554 }
555
556 /* When trying to create, create the VRF if it doesn't exist.
557 * Note: The VRF isn't active until we hear about it from the kernel.
558 */
559 if (!svrf) {
560 svrf = static_vty_get_unknown_vrf(vty, vrf_name);
561 if (!svrf)
562 return CMD_WARNING_CONFIG_FAILED;
563 }
564 return static_route_leak(vty, svrf, svrf, afi, safi, negate, dest_str,
565 mask_str, src_str, gate_str, ifname, flag_str,
566 tag_str, distance_str, label_str, table_str,
567 false);
568 }
569
570 void static_config_install_delayed_routes(struct static_vrf *svrf)
571 {
572 struct listnode *node, *nnode;
573 struct static_hold_route *shr;
574 struct static_vrf *osvrf, *nh_svrf;
575 int installed;
576
577 for (ALL_LIST_ELEMENTS(static_list, node, nnode, shr)) {
578 osvrf = static_vrf_lookup_by_name(shr->vrf_name);
579 nh_svrf = static_vrf_lookup_by_name(shr->nhvrf_name);
580
581 if (osvrf != svrf && nh_svrf != svrf)
582 continue;
583
584 if (osvrf->vrf->vrf_id == VRF_UNKNOWN
585 || nh_svrf->vrf->vrf_id == VRF_UNKNOWN)
586 continue;
587
588 installed = static_route_leak(
589 NULL, osvrf, nh_svrf, shr->afi, shr->safi, NULL,
590 shr->dest_str, shr->mask_str, shr->src_str,
591 shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str,
592 shr->distance_str, shr->label_str, shr->table_str,
593 shr->onlink);
594
595 if (installed != CMD_SUCCESS)
596 zlog_debug(
597 "%s: Attempt to install %s as a route and it was rejected",
598 __PRETTY_FUNCTION__, shr->dest_str);
599 listnode_delete(static_list, shr);
600 static_list_delete(shr);
601 }
602 }
603
604 /* Write static route configuration. */
605 int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi,
606 safi_t safi, const char *cmd)
607 {
608 struct static_hold_route *shr;
609 struct listnode *node;
610 char spacing[100];
611 struct route_node *rn;
612 struct static_route *si;
613 struct route_table *stable;
614 char buf[SRCDEST2STR_BUFFER];
615 int write = 0;
616
617 stable = svrf->stable[afi][safi];
618 if (stable == NULL)
619 return write;
620
621 sprintf(spacing, "%s%s", (svrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ",
622 cmd);
623
624 /*
625 * Static routes for vrfs not fully inited
626 */
627 for (ALL_LIST_ELEMENTS_RO(static_list, node, shr)) {
628 if (shr->afi != afi || shr->safi != safi)
629 continue;
630
631 if (strcmp(svrf->vrf->name, shr->vrf_name) != 0)
632 continue;
633
634 char dest_str[PREFIX_STRLEN];
635
636 prefix2str(&shr->dest, dest_str, sizeof(dest_str));
637
638 vty_out(vty, "%s ", spacing);
639 if (shr->dest_str)
640 vty_out(vty, "%s ", dest_str);
641 if (shr->src_str)
642 vty_out(vty, "from %s ", shr->src_str);
643 if (shr->gate_str)
644 vty_out(vty, "%s ", shr->gate_str);
645 if (shr->ifname)
646 vty_out(vty, "%s ", shr->ifname);
647 if (shr->flag_str)
648 vty_out(vty, "%s ", shr->flag_str);
649 if (shr->tag_str)
650 vty_out(vty, "tag %s ", shr->tag_str);
651 if (shr->distance_str)
652 vty_out(vty, "%s ", shr->distance_str);
653 if (shr->label_str)
654 vty_out(vty, "label %s ", shr->label_str);
655 if (shr->table_str)
656 vty_out(vty, "table %s", shr->table_str);
657 if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0)
658 vty_out(vty, "nexthop-vrf %s ", shr->nhvrf_name);
659 if (shr->onlink)
660 vty_out(vty, "onlink");
661 vty_out(vty, "\n");
662 }
663
664 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
665 for (si = rn->info; si; si = si->next) {
666 vty_out(vty, "%s %s", spacing,
667 srcdest_rnode2str(rn, buf, sizeof(buf)));
668
669 switch (si->type) {
670 case STATIC_IPV4_GATEWAY:
671 vty_out(vty, " %s", inet_ntoa(si->addr.ipv4));
672 break;
673 case STATIC_IPV6_GATEWAY:
674 vty_out(vty, " %s",
675 inet_ntop(AF_INET6, &si->addr.ipv6, buf,
676 sizeof(buf)));
677 break;
678 case STATIC_IFNAME:
679 vty_out(vty, " %s", si->ifname);
680 break;
681 case STATIC_BLACKHOLE:
682 switch (si->bh_type) {
683 case STATIC_BLACKHOLE_DROP:
684 vty_out(vty, " blackhole");
685 break;
686 case STATIC_BLACKHOLE_NULL:
687 vty_out(vty, " Null0");
688 break;
689 case STATIC_BLACKHOLE_REJECT:
690 vty_out(vty, " reject");
691 break;
692 }
693 break;
694 case STATIC_IPV4_GATEWAY_IFNAME:
695 vty_out(vty, " %s %s",
696 inet_ntop(AF_INET, &si->addr.ipv4, buf,
697 sizeof(buf)),
698 si->ifname);
699 break;
700 case STATIC_IPV6_GATEWAY_IFNAME:
701 vty_out(vty, " %s %s",
702 inet_ntop(AF_INET6, &si->addr.ipv6, buf,
703 sizeof(buf)),
704 si->ifname);
705 break;
706 }
707
708 if (si->tag)
709 vty_out(vty, " tag %" ROUTE_TAG_PRI, si->tag);
710
711 if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
712 vty_out(vty, " %d", si->distance);
713
714 /* Label information */
715 if (si->snh_label.num_labels)
716 vty_out(vty, " label %s",
717 mpls_label2str(si->snh_label.num_labels,
718 si->snh_label.label, buf,
719 sizeof(buf), 0));
720
721 if (si->nh_vrf_id != si->vrf_id)
722 vty_out(vty, " nexthop-vrf %s", si->nh_vrfname);
723
724 /*
725 * table ID from VRF overrides configured
726 */
727 if (si->table_id &&
728 svrf->vrf->data.l.table_id == RT_TABLE_MAIN)
729 vty_out(vty, " table %u", si->table_id);
730
731 if (si->onlink)
732 vty_out(vty, " onlink");
733
734 vty_out(vty, "\n");
735
736 write = 1;
737 }
738 return write;
739 }
740
741 /* Static unicast routes for multicast RPF lookup. */
742 DEFPY (ip_mroute_dist,
743 ip_mroute_dist_cmd,
744 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
745 NO_STR
746 IP_STR
747 "Configure static unicast route into MRIB for multicast RPF lookup\n"
748 "IP destination prefix (e.g. 10.0.0.0/8)\n"
749 "Nexthop address\n"
750 "Nexthop interface name\n"
751 "Distance\n")
752 {
753 return static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
754 NULL, NULL, gate_str, ifname, NULL, NULL,
755 distance_str, NULL, NULL, NULL);
756 }
757
758 /* Static route configuration. */
759 DEFPY(ip_route_blackhole,
760 ip_route_blackhole_cmd,
761 "[no] ip route\
762 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
763 <reject|blackhole>$flag \
764 [{ \
765 tag (1-4294967295) \
766 |(1-255)$distance \
767 |vrf NAME \
768 |label WORD \
769 |table (1-4294967295) \
770 }]",
771 NO_STR IP_STR
772 "Establish static routes\n"
773 "IP destination prefix (e.g. 10.0.0.0/8)\n"
774 "IP destination prefix\n"
775 "IP destination prefix mask\n"
776 "Emit an ICMP unreachable when matched\n"
777 "Silently discard pkts when matched\n"
778 "Set tag for this route\n"
779 "Tag value\n"
780 "Distance value for this route\n"
781 VRF_CMD_HELP_STR
782 MPLS_LABEL_HELPSTR
783 "Table to configure\n"
784 "The table number to configure\n")
785 {
786 if (table_str && vrf && !vrf_is_backend_netns()) {
787 vty_out(vty,
788 "%% table param only available when running on netns-based vrfs\n");
789 return CMD_WARNING_CONFIG_FAILED;
790 }
791
792 return static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
793 mask_str, NULL, NULL, NULL, flag, tag_str,
794 distance_str, vrf, label, table_str);
795 }
796
797 DEFPY(ip_route_blackhole_vrf,
798 ip_route_blackhole_vrf_cmd,
799 "[no] ip route\
800 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
801 <reject|blackhole>$flag \
802 [{ \
803 tag (1-4294967295) \
804 |(1-255)$distance \
805 |label WORD \
806 |table (1-4294967295) \
807 }]",
808 NO_STR IP_STR
809 "Establish static routes\n"
810 "IP destination prefix (e.g. 10.0.0.0/8)\n"
811 "IP destination prefix\n"
812 "IP destination prefix mask\n"
813 "Emit an ICMP unreachable when matched\n"
814 "Silently discard pkts when matched\n"
815 "Set tag for this route\n"
816 "Tag value\n"
817 "Distance value for this route\n"
818 MPLS_LABEL_HELPSTR
819 "Table to configure\n"
820 "The table number to configure\n")
821 {
822 VTY_DECLVAR_CONTEXT(vrf, vrf);
823 struct static_vrf *svrf = vrf->info;
824
825 if (table_str && !vrf_is_backend_netns()) {
826 vty_out(vty,
827 "%% table param only available when running on netns-based vrfs\n");
828 return CMD_WARNING_CONFIG_FAILED;
829 }
830
831 /*
832 * Coverity is complaining that prefix could
833 * be dereferenced, but we know that prefix will
834 * valid. Add an assert to make it happy
835 */
836 assert(prefix);
837 return static_route_leak(vty, svrf, svrf, AFI_IP, SAFI_UNICAST, no,
838 prefix, mask_str, NULL, NULL, NULL, flag,
839 tag_str, distance_str, label, table_str,
840 false);
841 }
842
843 DEFPY(ip_route_address_interface,
844 ip_route_address_interface_cmd,
845 "[no] ip route\
846 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
847 A.B.C.D$gate \
848 <INTERFACE|Null0>$ifname \
849 [{ \
850 tag (1-4294967295) \
851 |(1-255)$distance \
852 |vrf NAME \
853 |label WORD \
854 |table (1-4294967295) \
855 |nexthop-vrf NAME \
856 |onlink$onlink \
857 }]",
858 NO_STR IP_STR
859 "Establish static routes\n"
860 "IP destination prefix (e.g. 10.0.0.0/8)\n"
861 "IP destination prefix\n"
862 "IP destination prefix mask\n"
863 "IP gateway address\n"
864 "IP gateway interface name\n"
865 "Null interface\n"
866 "Set tag for this route\n"
867 "Tag value\n"
868 "Distance value for this route\n"
869 VRF_CMD_HELP_STR
870 MPLS_LABEL_HELPSTR
871 "Table to configure\n"
872 "The table number to configure\n"
873 VRF_CMD_HELP_STR
874 "Treat the nexthop as directly attached to the interface")
875 {
876 struct static_vrf *svrf;
877 struct static_vrf *nh_svrf;
878 const char *flag = NULL;
879
880 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
881 flag = "Null0";
882 ifname = NULL;
883 }
884
885 svrf = static_vty_get_unknown_vrf(vty, vrf);
886 if (!svrf) {
887 vty_out(vty, "%% vrf %s is not defined\n", vrf);
888 return CMD_WARNING_CONFIG_FAILED;
889 }
890
891 if (table_str && vrf && !vrf_is_backend_netns()) {
892 vty_out(vty,
893 "%% table param only available when running on netns-based vrfs\n");
894 return CMD_WARNING_CONFIG_FAILED;
895 }
896
897 if (nexthop_vrf)
898 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
899 else
900 nh_svrf = svrf;
901
902 if (!nh_svrf) {
903 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
904 return CMD_WARNING_CONFIG_FAILED;
905 }
906
907 return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no,
908 prefix, mask_str, NULL, gate_str, ifname, flag,
909 tag_str, distance_str, label, table_str,
910 !!onlink);
911 }
912
913 DEFPY(ip_route_address_interface_vrf,
914 ip_route_address_interface_vrf_cmd,
915 "[no] ip route\
916 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
917 A.B.C.D$gate \
918 <INTERFACE|Null0>$ifname \
919 [{ \
920 tag (1-4294967295) \
921 |(1-255)$distance \
922 |label WORD \
923 |table (1-4294967295) \
924 |nexthop-vrf NAME \
925 |onlink$onlink \
926 }]",
927 NO_STR IP_STR
928 "Establish static routes\n"
929 "IP destination prefix (e.g. 10.0.0.0/8)\n"
930 "IP destination prefix\n"
931 "IP destination prefix mask\n"
932 "IP gateway address\n"
933 "IP gateway interface name\n"
934 "Null interface\n"
935 "Set tag for this route\n"
936 "Tag value\n"
937 "Distance value for this route\n"
938 MPLS_LABEL_HELPSTR
939 "Table to configure\n"
940 "The table number to configure\n"
941 VRF_CMD_HELP_STR
942 "Treat the nexthop as directly attached to the interface")
943 {
944 VTY_DECLVAR_CONTEXT(vrf, vrf);
945 const char *flag = NULL;
946 struct static_vrf *svrf = vrf->info;
947 struct static_vrf *nh_svrf;
948
949 if (table_str && !vrf_is_backend_netns()) {
950 vty_out(vty,
951 "%% table param only available when running on netns-based vrfs\n");
952 return CMD_WARNING_CONFIG_FAILED;
953 }
954
955 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
956 flag = "Null0";
957 ifname = NULL;
958 }
959
960 if (nexthop_vrf)
961 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
962 else
963 nh_svrf = svrf;
964
965 if (!nh_svrf) {
966 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
967 return CMD_WARNING_CONFIG_FAILED;
968 }
969
970 return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no,
971 prefix, mask_str, NULL, gate_str, ifname, flag,
972 tag_str, distance_str, label, table_str,
973 !!onlink);
974 }
975
976 DEFPY(ip_route,
977 ip_route_cmd,
978 "[no] ip route\
979 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
980 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
981 [{ \
982 tag (1-4294967295) \
983 |(1-255)$distance \
984 |vrf NAME \
985 |label WORD \
986 |table (1-4294967295) \
987 |nexthop-vrf NAME \
988 }]",
989 NO_STR IP_STR
990 "Establish static routes\n"
991 "IP destination prefix (e.g. 10.0.0.0/8)\n"
992 "IP destination prefix\n"
993 "IP destination prefix mask\n"
994 "IP gateway address\n"
995 "IP gateway interface name\n"
996 "Null interface\n"
997 "Set tag for this route\n"
998 "Tag value\n"
999 "Distance value for this route\n"
1000 VRF_CMD_HELP_STR
1001 MPLS_LABEL_HELPSTR
1002 "Table to configure\n"
1003 "The table number to configure\n"
1004 VRF_CMD_HELP_STR)
1005 {
1006 struct static_vrf *svrf;
1007 struct static_vrf *nh_svrf;
1008 const char *flag = NULL;
1009
1010 if (table_str && vrf && !vrf_is_backend_netns()) {
1011 vty_out(vty,
1012 "%% table param only available when running on netns-based vrfs\n");
1013 return CMD_WARNING_CONFIG_FAILED;
1014 }
1015
1016 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
1017 flag = "Null0";
1018 ifname = NULL;
1019 }
1020
1021 svrf = static_vty_get_unknown_vrf(vty, vrf);
1022 if (!svrf) {
1023 vty_out(vty, "%% vrf %s is not defined\n", vrf);
1024 return CMD_WARNING_CONFIG_FAILED;
1025 }
1026
1027 if (nexthop_vrf)
1028 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
1029 else
1030 nh_svrf = svrf;
1031
1032 if (!nh_svrf) {
1033 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1034 return CMD_WARNING_CONFIG_FAILED;
1035 }
1036
1037 return static_route_leak(
1038 vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
1039 NULL, gate_str, ifname, flag, tag_str, distance_str, label,
1040 table_str, false);
1041 }
1042
1043 DEFPY(ip_route_vrf,
1044 ip_route_vrf_cmd,
1045 "[no] ip route\
1046 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1047 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
1048 [{ \
1049 tag (1-4294967295) \
1050 |(1-255)$distance \
1051 |label WORD \
1052 |table (1-4294967295) \
1053 |nexthop-vrf NAME \
1054 }]",
1055 NO_STR IP_STR
1056 "Establish static routes\n"
1057 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1058 "IP destination prefix\n"
1059 "IP destination prefix mask\n"
1060 "IP gateway address\n"
1061 "IP gateway interface name\n"
1062 "Null interface\n"
1063 "Set tag for this route\n"
1064 "Tag value\n"
1065 "Distance value for this route\n"
1066 MPLS_LABEL_HELPSTR
1067 "Table to configure\n"
1068 "The table number to configure\n"
1069 VRF_CMD_HELP_STR)
1070 {
1071 VTY_DECLVAR_CONTEXT(vrf, vrf);
1072 struct static_vrf *svrf = vrf->info;
1073 struct static_vrf *nh_svrf;
1074 const char *flag = NULL;
1075
1076 if (table_str && !vrf_is_backend_netns()) {
1077 vty_out(vty,
1078 "%% table param only available when running on netns-based vrfs\n");
1079 return CMD_WARNING_CONFIG_FAILED;
1080 }
1081
1082 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
1083 flag = "Null0";
1084 ifname = NULL;
1085 }
1086
1087 if (nexthop_vrf)
1088 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
1089 else
1090 nh_svrf = svrf;
1091
1092 if (!nh_svrf) {
1093 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1094 return CMD_WARNING_CONFIG_FAILED;
1095 }
1096
1097 return static_route_leak(
1098 vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
1099 NULL, gate_str, ifname, flag, tag_str, distance_str, label,
1100 table_str, false);
1101 }
1102
1103 DEFPY(ipv6_route_blackhole,
1104 ipv6_route_blackhole_cmd,
1105 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1106 <reject|blackhole>$flag \
1107 [{ \
1108 tag (1-4294967295) \
1109 |(1-255)$distance \
1110 |vrf NAME \
1111 |label WORD \
1112 |table (1-4294967295) \
1113 }]",
1114 NO_STR
1115 IPV6_STR
1116 "Establish static routes\n"
1117 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1118 "IPv6 source-dest route\n"
1119 "IPv6 source prefix\n"
1120 "Emit an ICMP unreachable when matched\n"
1121 "Silently discard pkts when matched\n"
1122 "Set tag for this route\n"
1123 "Tag value\n"
1124 "Distance value for this prefix\n"
1125 VRF_CMD_HELP_STR
1126 MPLS_LABEL_HELPSTR
1127 "Table to configure\n"
1128 "The table number to configure\n")
1129 {
1130 if (table_str && vrf && !vrf_is_backend_netns()) {
1131 vty_out(vty,
1132 "%% table param only available when running on netns-based vrfs\n");
1133 return CMD_WARNING_CONFIG_FAILED;
1134 }
1135
1136 return static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
1137 NULL, from_str, NULL, NULL, flag, tag_str,
1138 distance_str, vrf, label, table_str);
1139 }
1140
1141 DEFPY(ipv6_route_blackhole_vrf,
1142 ipv6_route_blackhole_vrf_cmd,
1143 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1144 <reject|blackhole>$flag \
1145 [{ \
1146 tag (1-4294967295) \
1147 |(1-255)$distance \
1148 |label WORD \
1149 |table (1-4294967295) \
1150 }]",
1151 NO_STR
1152 IPV6_STR
1153 "Establish static routes\n"
1154 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1155 "IPv6 source-dest route\n"
1156 "IPv6 source prefix\n"
1157 "Emit an ICMP unreachable when matched\n"
1158 "Silently discard pkts when matched\n"
1159 "Set tag for this route\n"
1160 "Tag value\n"
1161 "Distance value for this prefix\n"
1162 MPLS_LABEL_HELPSTR
1163 "Table to configure\n"
1164 "The table number to configure\n")
1165 {
1166 VTY_DECLVAR_CONTEXT(vrf, vrf);
1167 struct static_vrf *svrf = vrf->info;
1168
1169 if (table_str && !vrf_is_backend_netns()) {
1170 vty_out(vty,
1171 "%% table param only available when running on netns-based vrfs\n");
1172 return CMD_WARNING_CONFIG_FAILED;
1173 }
1174
1175 /*
1176 * Coverity is complaining that prefix could
1177 * be dereferenced, but we know that prefix will
1178 * valid. Add an assert to make it happy
1179 */
1180 assert(prefix);
1181 return static_route_leak(
1182 vty, svrf, svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
1183 from_str, NULL, NULL, flag, tag_str, distance_str, label,
1184 table_str, false);
1185 }
1186
1187 DEFPY(ipv6_route_address_interface,
1188 ipv6_route_address_interface_cmd,
1189 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1190 X:X::X:X$gate \
1191 <INTERFACE|Null0>$ifname \
1192 [{ \
1193 tag (1-4294967295) \
1194 |(1-255)$distance \
1195 |vrf NAME \
1196 |label WORD \
1197 |table (1-4294967295) \
1198 |nexthop-vrf NAME \
1199 |onlink$onlink \
1200 }]",
1201 NO_STR
1202 IPV6_STR
1203 "Establish static routes\n"
1204 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1205 "IPv6 source-dest route\n"
1206 "IPv6 source prefix\n"
1207 "IPv6 gateway address\n"
1208 "IPv6 gateway interface name\n"
1209 "Null interface\n"
1210 "Set tag for this route\n"
1211 "Tag value\n"
1212 "Distance value for this prefix\n"
1213 VRF_CMD_HELP_STR
1214 MPLS_LABEL_HELPSTR
1215 "Table to configure\n"
1216 "The table number to configure\n"
1217 VRF_CMD_HELP_STR
1218 "Treat the nexthop as directly attached to the interface")
1219 {
1220 struct static_vrf *svrf;
1221 struct static_vrf *nh_svrf;
1222 const char *flag = NULL;
1223
1224 if (table_str && vrf && !vrf_is_backend_netns()) {
1225 vty_out(vty,
1226 "%% table param only available when running on netns-based vrfs\n");
1227 return CMD_WARNING_CONFIG_FAILED;
1228 }
1229
1230 svrf = static_vty_get_unknown_vrf(vty, vrf);
1231 if (!svrf) {
1232 vty_out(vty, "%% vrf %s is not defined\n", vrf);
1233 return CMD_WARNING_CONFIG_FAILED;
1234 }
1235
1236 if (nexthop_vrf)
1237 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
1238 else
1239 nh_svrf = svrf;
1240
1241 if (!nh_svrf) {
1242 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1243 return CMD_WARNING_CONFIG_FAILED;
1244 }
1245
1246 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
1247 flag = "Null0";
1248 ifname = NULL;
1249 }
1250
1251 return static_route_leak(
1252 vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
1253 from_str, gate_str, ifname, flag, tag_str, distance_str, label,
1254 table_str, !!onlink);
1255 }
1256
1257 DEFPY(ipv6_route_address_interface_vrf,
1258 ipv6_route_address_interface_vrf_cmd,
1259 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1260 X:X::X:X$gate \
1261 <INTERFACE|Null0>$ifname \
1262 [{ \
1263 tag (1-4294967295) \
1264 |(1-255)$distance \
1265 |label WORD \
1266 |table (1-4294967295) \
1267 |nexthop-vrf NAME \
1268 |onlink$onlink \
1269 }]",
1270 NO_STR
1271 IPV6_STR
1272 "Establish static routes\n"
1273 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1274 "IPv6 source-dest route\n"
1275 "IPv6 source prefix\n"
1276 "IPv6 gateway address\n"
1277 "IPv6 gateway interface name\n"
1278 "Null interface\n"
1279 "Set tag for this route\n"
1280 "Tag value\n"
1281 "Distance value for this prefix\n"
1282 MPLS_LABEL_HELPSTR
1283 "Table to configure\n"
1284 "The table number to configure\n"
1285 VRF_CMD_HELP_STR
1286 "Treat the nexthop as directly attached to the interface")
1287 {
1288 VTY_DECLVAR_CONTEXT(vrf, vrf);
1289 struct static_vrf *svrf = vrf->info;
1290 struct static_vrf *nh_svrf;
1291 const char *flag = NULL;
1292
1293 if (table_str && !vrf_is_backend_netns()) {
1294 vty_out(vty,
1295 "%% table param only available when running on netns-based vrfs\n");
1296 return CMD_WARNING_CONFIG_FAILED;
1297 }
1298
1299 if (nexthop_vrf)
1300 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
1301 else
1302 nh_svrf = svrf;
1303
1304 if (!nh_svrf) {
1305 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1306 return CMD_WARNING_CONFIG_FAILED;
1307 }
1308
1309 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
1310 flag = "Null0";
1311 ifname = NULL;
1312 }
1313
1314 return static_route_leak(
1315 vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
1316 from_str, gate_str, ifname, flag, tag_str, distance_str, label,
1317 table_str, !!onlink);
1318 }
1319
1320 DEFPY(ipv6_route,
1321 ipv6_route_cmd,
1322 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1323 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1324 [{ \
1325 tag (1-4294967295) \
1326 |(1-255)$distance \
1327 |vrf NAME \
1328 |label WORD \
1329 |table (1-4294967295) \
1330 |nexthop-vrf NAME \
1331 }]",
1332 NO_STR
1333 IPV6_STR
1334 "Establish static routes\n"
1335 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1336 "IPv6 source-dest route\n"
1337 "IPv6 source prefix\n"
1338 "IPv6 gateway address\n"
1339 "IPv6 gateway interface name\n"
1340 "Null interface\n"
1341 "Set tag for this route\n"
1342 "Tag value\n"
1343 "Distance value for this prefix\n"
1344 VRF_CMD_HELP_STR
1345 MPLS_LABEL_HELPSTR
1346 "Table to configure\n"
1347 "The table number to configure\n"
1348 VRF_CMD_HELP_STR)
1349 {
1350 struct static_vrf *svrf;
1351 struct static_vrf *nh_svrf;
1352 const char *flag = NULL;
1353
1354 if (table_str && vrf && !vrf_is_backend_netns()) {
1355 vty_out(vty,
1356 "%% table param only available when running on netns-based vrfs\n");
1357 return CMD_WARNING_CONFIG_FAILED;
1358 }
1359
1360 svrf = static_vty_get_unknown_vrf(vty, vrf);
1361 if (!svrf) {
1362 vty_out(vty, "%% vrf %s is not defined\n", vrf);
1363 return CMD_WARNING_CONFIG_FAILED;
1364 }
1365
1366 if (nexthop_vrf)
1367 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
1368 else
1369 nh_svrf = svrf;
1370
1371 if (!nh_svrf) {
1372 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1373 return CMD_WARNING_CONFIG_FAILED;
1374 }
1375
1376 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
1377 flag = "Null0";
1378 ifname = NULL;
1379 }
1380
1381 return static_route_leak(
1382 vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
1383 from_str, gate_str, ifname, flag, tag_str, distance_str, label,
1384 table_str, false);
1385 }
1386
1387 DEFPY(ipv6_route_vrf,
1388 ipv6_route_vrf_cmd,
1389 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1390 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1391 [{ \
1392 tag (1-4294967295) \
1393 |(1-255)$distance \
1394 |label WORD \
1395 |table (1-4294967295) \
1396 |nexthop-vrf NAME \
1397 }]",
1398 NO_STR
1399 IPV6_STR
1400 "Establish static routes\n"
1401 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1402 "IPv6 source-dest route\n"
1403 "IPv6 source prefix\n"
1404 "IPv6 gateway address\n"
1405 "IPv6 gateway interface name\n"
1406 "Null interface\n"
1407 "Set tag for this route\n"
1408 "Tag value\n"
1409 "Distance value for this prefix\n"
1410 MPLS_LABEL_HELPSTR
1411 "Table to configure\n"
1412 "The table number to configure\n"
1413 VRF_CMD_HELP_STR)
1414 {
1415 VTY_DECLVAR_CONTEXT(vrf, vrf);
1416 struct static_vrf *svrf = vrf->info;
1417 struct static_vrf *nh_svrf;
1418 const char *flag = NULL;
1419
1420 if (table_str && !vrf_is_backend_netns()) {
1421 vty_out(vty,
1422 "%% table param only available when running on netns-based vrfs\n");
1423 return CMD_WARNING_CONFIG_FAILED;
1424 }
1425
1426 if (nexthop_vrf)
1427 nh_svrf = static_vty_get_unknown_vrf(vty, nexthop_vrf);
1428 else
1429 nh_svrf = svrf;
1430
1431 if (!nh_svrf) {
1432 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1433 return CMD_WARNING_CONFIG_FAILED;
1434 }
1435
1436 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
1437 flag = "Null0";
1438 ifname = NULL;
1439 }
1440
1441 return static_route_leak(
1442 vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
1443 from_str, gate_str, ifname, flag, tag_str, distance_str, label,
1444 table_str, false);
1445 }
1446 DEFPY(debug_staticd,
1447 debug_staticd_cmd,
1448 "[no] debug static [{events$events}]",
1449 NO_STR
1450 DEBUG_STR
1451 STATICD_STR
1452 "Debug events\n")
1453 {
1454 /* If no specific category, change all */
1455 if (strmatch(argv[argc - 1]->text, "static"))
1456 static_debug_set(vty->node, !no, true);
1457 else
1458 static_debug_set(vty->node, !no, !!events);
1459
1460 return CMD_SUCCESS;
1461 }
1462
1463 DEFUN_NOSH (show_debugging_static,
1464 show_debugging_static_cmd,
1465 "show debugging [static]",
1466 SHOW_STR
1467 DEBUG_STR
1468 "Static Information\n")
1469 {
1470 vty_out(vty, "Staticd debugging status\n");
1471
1472 static_debug_status_write(vty);
1473
1474 return CMD_SUCCESS;
1475 }
1476
1477 static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
1478
1479 void static_vty_init(void)
1480 {
1481 install_node(&debug_node, static_config_write_debug);
1482
1483 install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
1484
1485 install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
1486 install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
1487 install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
1488 install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
1489 install_element(CONFIG_NODE, &ip_route_cmd);
1490 install_element(VRF_NODE, &ip_route_vrf_cmd);
1491
1492 install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
1493 install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
1494 install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
1495 install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
1496 install_element(CONFIG_NODE, &ipv6_route_cmd);
1497 install_element(VRF_NODE, &ipv6_route_vrf_cmd);
1498
1499 install_element(VIEW_NODE, &show_debugging_static_cmd);
1500 install_element(VIEW_NODE, &debug_staticd_cmd);
1501 install_element(CONFIG_NODE, &debug_staticd_cmd);
1502
1503 static_list = list_new();
1504 static_list->cmp = (int (*)(void *, void *))static_list_compare;
1505 static_list->del = (void (*)(void *))static_list_delete;
1506 }