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