Line data Source code
1 : /*
2 : * Copyright (C) 1998 Kunihiro Ishiguro
3 : * Copyright (C) 2018 NetDEF, Inc.
4 : * Renato Westphal
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 :
21 : #include <zebra.h>
22 :
23 : #include "if.h"
24 : #include "vrf.h"
25 : #include "log.h"
26 : #include "prefix.h"
27 : #include "command.h"
28 : #include "northbound_cli.h"
29 : #include "libfrr.h"
30 :
31 : #include "ripngd/ripngd.h"
32 : #include "ripngd/ripng_nb.h"
33 : #include "ripngd/ripng_cli_clippy.c"
34 :
35 : /*
36 : * XPath: /frr-ripngd:ripngd/instance
37 : */
38 1 : DEFPY_YANG_NOSH (router_ripng,
39 : router_ripng_cmd,
40 : "router ripng [vrf NAME]",
41 : "Enable a routing process\n"
42 : "Make RIPng instance command\n"
43 : VRF_CMD_HELP_STR)
44 : {
45 1 : char xpath[XPATH_MAXLEN];
46 1 : int ret;
47 :
48 : /* Build RIPng instance XPath. */
49 1 : if (!vrf)
50 1 : vrf = VRF_DEFAULT_NAME;
51 1 : snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
52 : vrf);
53 :
54 1 : nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
55 :
56 1 : ret = nb_cli_apply_changes(vty, NULL);
57 1 : if (ret == CMD_SUCCESS)
58 1 : VTY_PUSH_XPATH(RIPNG_NODE, xpath);
59 :
60 : return ret;
61 : }
62 :
63 0 : DEFPY_YANG (no_router_ripng,
64 : no_router_ripng_cmd,
65 : "no router ripng [vrf NAME]",
66 : NO_STR
67 : "Enable a routing process\n"
68 : "Make RIPng instance command\n"
69 : VRF_CMD_HELP_STR)
70 : {
71 0 : char xpath[XPATH_MAXLEN];
72 :
73 : /* Build RIPng instance XPath. */
74 0 : if (!vrf)
75 0 : vrf = VRF_DEFAULT_NAME;
76 0 : snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
77 : vrf);
78 :
79 0 : nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
80 :
81 0 : return nb_cli_apply_changes_clear_pending(vty, NULL);
82 : }
83 :
84 0 : void cli_show_router_ripng(struct vty *vty, const struct lyd_node *dnode,
85 : bool show_defaults)
86 : {
87 0 : const char *vrf_name;
88 :
89 0 : vrf_name = yang_dnode_get_string(dnode, "./vrf");
90 :
91 0 : vty_out(vty, "!\n");
92 0 : vty_out(vty, "router ripng");
93 0 : if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
94 0 : vty_out(vty, " vrf %s", vrf_name);
95 0 : vty_out(vty, "\n");
96 0 : }
97 :
98 : /*
99 : * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
100 : */
101 0 : DEFPY_YANG (ripng_allow_ecmp,
102 : ripng_allow_ecmp_cmd,
103 : "[no] allow-ecmp",
104 : NO_STR
105 : "Allow Equal Cost MultiPath\n")
106 : {
107 0 : nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY,
108 : no ? "false" : "true");
109 :
110 0 : return nb_cli_apply_changes(vty, NULL);
111 : }
112 :
113 0 : void cli_show_ripng_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
114 : bool show_defaults)
115 : {
116 0 : if (!yang_dnode_get_bool(dnode, NULL))
117 0 : vty_out(vty, " no");
118 :
119 0 : vty_out(vty, " allow-ecmp\n");
120 0 : }
121 :
122 : /*
123 : * XPath: /frr-ripngd:ripngd/instance/default-information-originate
124 : */
125 0 : DEFPY_YANG (ripng_default_information_originate,
126 : ripng_default_information_originate_cmd,
127 : "[no] default-information originate",
128 : NO_STR
129 : "Default route information\n"
130 : "Distribute default route\n")
131 : {
132 0 : nb_cli_enqueue_change(vty, "./default-information-originate",
133 : NB_OP_MODIFY, no ? "false" : "true");
134 :
135 0 : return nb_cli_apply_changes(vty, NULL);
136 : }
137 :
138 0 : void cli_show_ripng_default_information_originate(struct vty *vty,
139 : const struct lyd_node *dnode,
140 : bool show_defaults)
141 : {
142 0 : if (!yang_dnode_get_bool(dnode, NULL))
143 0 : vty_out(vty, " no");
144 :
145 0 : vty_out(vty, " default-information originate\n");
146 0 : }
147 :
148 : /*
149 : * XPath: /frr-ripngd:ripngd/instance/default-metric
150 : */
151 0 : DEFPY_YANG (ripng_default_metric,
152 : ripng_default_metric_cmd,
153 : "default-metric (1-16)",
154 : "Set a metric of redistribute routes\n"
155 : "Default metric\n")
156 : {
157 0 : nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY,
158 : default_metric_str);
159 :
160 0 : return nb_cli_apply_changes(vty, NULL);
161 : }
162 :
163 0 : DEFPY_YANG (no_ripng_default_metric,
164 : no_ripng_default_metric_cmd,
165 : "no default-metric [(1-16)]",
166 : NO_STR
167 : "Set a metric of redistribute routes\n"
168 : "Default metric\n")
169 : {
170 0 : nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, NULL);
171 :
172 0 : return nb_cli_apply_changes(vty, NULL);
173 : }
174 :
175 0 : void cli_show_ripng_default_metric(struct vty *vty,
176 : const struct lyd_node *dnode,
177 : bool show_defaults)
178 : {
179 0 : vty_out(vty, " default-metric %s\n",
180 : yang_dnode_get_string(dnode, NULL));
181 0 : }
182 :
183 : /*
184 : * XPath: /frr-ripngd:ripngd/instance/network
185 : */
186 1 : DEFPY_YANG (ripng_network_prefix,
187 : ripng_network_prefix_cmd,
188 : "[no] network X:X::X:X/M",
189 : NO_STR
190 : "RIPng enable on specified interface or network.\n"
191 : "IPv6 network\n")
192 : {
193 2 : nb_cli_enqueue_change(vty, "./network",
194 : no ? NB_OP_DESTROY : NB_OP_CREATE, network_str);
195 :
196 1 : return nb_cli_apply_changes(vty, NULL);
197 : }
198 :
199 0 : void cli_show_ripng_network_prefix(struct vty *vty,
200 : const struct lyd_node *dnode,
201 : bool show_defaults)
202 : {
203 0 : vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
204 0 : }
205 :
206 : /*
207 : * XPath: /frr-ripngd:ripngd/instance/interface
208 : */
209 0 : DEFPY_YANG (ripng_network_if,
210 : ripng_network_if_cmd,
211 : "[no] network WORD",
212 : NO_STR
213 : "RIPng enable on specified interface or network.\n"
214 : "Interface name\n")
215 : {
216 0 : nb_cli_enqueue_change(vty, "./interface",
217 : no ? NB_OP_DESTROY : NB_OP_CREATE, network);
218 :
219 0 : return nb_cli_apply_changes(vty, NULL);
220 : }
221 :
222 0 : void cli_show_ripng_network_interface(struct vty *vty,
223 : const struct lyd_node *dnode,
224 : bool show_defaults)
225 : {
226 0 : vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
227 0 : }
228 :
229 : /*
230 : * XPath: /frr-ripngd:ripngd/instance/offset-list
231 : */
232 0 : DEFPY_YANG (ripng_offset_list,
233 : ripng_offset_list_cmd,
234 : "[no] offset-list ACCESSLIST6_NAME$acl <in|out>$direction (0-16)$metric [IFNAME]",
235 : NO_STR
236 : "Modify RIPng metric\n"
237 : "Access-list name\n"
238 : "For incoming updates\n"
239 : "For outgoing updates\n"
240 : "Metric value\n"
241 : "Interface to match\n")
242 : {
243 0 : if (!no) {
244 0 : nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
245 0 : nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl);
246 0 : nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
247 : metric_str);
248 : } else
249 0 : nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
250 :
251 0 : return nb_cli_apply_changes(
252 : vty, "./offset-list[interface='%s'][direction='%s']",
253 : ifname ? ifname : "*", direction);
254 : }
255 :
256 0 : void cli_show_ripng_offset_list(struct vty *vty, const struct lyd_node *dnode,
257 : bool show_defaults)
258 : {
259 0 : const char *interface;
260 :
261 0 : interface = yang_dnode_get_string(dnode, "./interface");
262 :
263 0 : vty_out(vty, " offset-list %s %s %s",
264 : yang_dnode_get_string(dnode, "./access-list"),
265 : yang_dnode_get_string(dnode, "./direction"),
266 : yang_dnode_get_string(dnode, "./metric"));
267 0 : if (!strmatch(interface, "*"))
268 0 : vty_out(vty, " %s", interface);
269 0 : vty_out(vty, "\n");
270 0 : }
271 :
272 : /*
273 : * XPath: /frr-ripngd:ripngd/instance/passive-interface
274 : */
275 0 : DEFPY_YANG (ripng_passive_interface,
276 : ripng_passive_interface_cmd,
277 : "[no] passive-interface IFNAME",
278 : NO_STR
279 : "Suppress routing updates on an interface\n"
280 : "Interface name\n")
281 : {
282 0 : nb_cli_enqueue_change(vty, "./passive-interface",
283 : no ? NB_OP_DESTROY : NB_OP_CREATE, ifname);
284 :
285 0 : return nb_cli_apply_changes(vty, NULL);
286 : }
287 :
288 0 : void cli_show_ripng_passive_interface(struct vty *vty,
289 : const struct lyd_node *dnode,
290 : bool show_defaults)
291 : {
292 0 : vty_out(vty, " passive-interface %s\n",
293 : yang_dnode_get_string(dnode, NULL));
294 0 : }
295 :
296 : /*
297 : * XPath: /frr-ripngd:ripngd/instance/redistribute
298 : */
299 0 : DEFPY_YANG (ripng_redistribute,
300 : ripng_redistribute_cmd,
301 : "[no] redistribute " FRR_REDIST_STR_RIPNGD "$protocol [{metric (0-16)|route-map RMAP_NAME$route_map}]",
302 : NO_STR
303 : REDIST_STR
304 : FRR_REDIST_HELP_STR_RIPNGD
305 : "Metric\n"
306 : "Metric value\n"
307 : "Route map reference\n"
308 : "Pointer to route-map entries\n")
309 : {
310 0 : if (!no) {
311 0 : nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
312 0 : nb_cli_enqueue_change(vty, "./route-map",
313 : route_map ? NB_OP_MODIFY : NB_OP_DESTROY,
314 : route_map);
315 0 : nb_cli_enqueue_change(vty, "./metric",
316 : metric_str ? NB_OP_MODIFY : NB_OP_DESTROY,
317 : metric_str);
318 : } else
319 0 : nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
320 :
321 0 : return nb_cli_apply_changes(vty, "./redistribute[protocol='%s']",
322 : protocol);
323 : }
324 :
325 0 : void cli_show_ripng_redistribute(struct vty *vty, const struct lyd_node *dnode,
326 : bool show_defaults)
327 : {
328 0 : vty_out(vty, " redistribute %s",
329 : yang_dnode_get_string(dnode, "./protocol"));
330 0 : if (yang_dnode_exists(dnode, "./metric"))
331 0 : vty_out(vty, " metric %s",
332 : yang_dnode_get_string(dnode, "./metric"));
333 0 : if (yang_dnode_exists(dnode, "./route-map"))
334 0 : vty_out(vty, " route-map %s",
335 : yang_dnode_get_string(dnode, "./route-map"));
336 0 : vty_out(vty, "\n");
337 0 : }
338 :
339 : /*
340 : * XPath: /frr-ripngd:ripngd/instance/static-route
341 : */
342 0 : DEFPY_YANG (ripng_route,
343 : ripng_route_cmd,
344 : "[no] route X:X::X:X/M",
345 : NO_STR
346 : "Static route setup\n"
347 : "Set static RIPng route announcement\n")
348 : {
349 0 : nb_cli_enqueue_change(vty, "./static-route",
350 : no ? NB_OP_DESTROY : NB_OP_CREATE, route_str);
351 :
352 0 : return nb_cli_apply_changes(vty, NULL);
353 : }
354 :
355 0 : void cli_show_ripng_route(struct vty *vty, const struct lyd_node *dnode,
356 : bool show_defaults)
357 : {
358 0 : vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL));
359 0 : }
360 :
361 : /*
362 : * XPath: /frr-ripngd:ripngd/instance/aggregate-addres
363 : */
364 0 : DEFPY_YANG (ripng_aggregate_address,
365 : ripng_aggregate_address_cmd,
366 : "[no] aggregate-address X:X::X:X/M",
367 : NO_STR
368 : "Set aggregate RIPng route announcement\n"
369 : "Aggregate network\n")
370 : {
371 0 : nb_cli_enqueue_change(vty, "./aggregate-address",
372 : no ? NB_OP_DESTROY : NB_OP_CREATE,
373 : aggregate_address_str);
374 :
375 0 : return nb_cli_apply_changes(vty, NULL);
376 : }
377 :
378 0 : void cli_show_ripng_aggregate_address(struct vty *vty,
379 : const struct lyd_node *dnode,
380 : bool show_defaults)
381 : {
382 0 : vty_out(vty, " aggregate-address %s\n",
383 : yang_dnode_get_string(dnode, NULL));
384 0 : }
385 :
386 : /*
387 : * XPath: /frr-ripngd:ripngd/instance/timers
388 : */
389 0 : DEFPY_YANG (ripng_timers,
390 : ripng_timers_cmd,
391 : "timers basic (1-65535)$update (1-65535)$timeout (1-65535)$garbage",
392 : "RIPng timers setup\n"
393 : "Basic timer\n"
394 : "Routing table update timer value in second. Default is 30.\n"
395 : "Routing information timeout timer. Default is 180.\n"
396 : "Garbage collection timer. Default is 120.\n")
397 : {
398 0 : nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY,
399 : update_str);
400 0 : nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY,
401 : timeout_str);
402 0 : nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY,
403 : garbage_str);
404 :
405 0 : return nb_cli_apply_changes(vty, "./timers");
406 : }
407 :
408 0 : DEFPY_YANG (no_ripng_timers,
409 : no_ripng_timers_cmd,
410 : "no timers basic [(1-65535) (1-65535) (1-65535)]",
411 : NO_STR
412 : "RIPng timers setup\n"
413 : "Basic timer\n"
414 : "Routing table update timer value in second. Default is 30.\n"
415 : "Routing information timeout timer. Default is 180.\n"
416 : "Garbage collection timer. Default is 120.\n")
417 : {
418 0 : nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, NULL);
419 0 : nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, NULL);
420 0 : nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, NULL);
421 :
422 0 : return nb_cli_apply_changes(vty, "./timers");
423 : }
424 :
425 0 : void cli_show_ripng_timers(struct vty *vty, const struct lyd_node *dnode,
426 : bool show_defaults)
427 : {
428 0 : vty_out(vty, " timers basic %s %s %s\n",
429 : yang_dnode_get_string(dnode, "./update-interval"),
430 : yang_dnode_get_string(dnode, "./holddown-interval"),
431 : yang_dnode_get_string(dnode, "./flush-interval"));
432 0 : }
433 :
434 : /*
435 : * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
436 : */
437 0 : DEFPY_YANG (ipv6_ripng_split_horizon,
438 : ipv6_ripng_split_horizon_cmd,
439 : "[no] ipv6 ripng split-horizon [poisoned-reverse$poisoned_reverse]",
440 : NO_STR
441 : IPV6_STR
442 : "Routing Information Protocol\n"
443 : "Perform split horizon\n"
444 : "With poisoned-reverse\n")
445 : {
446 0 : const char *value;
447 :
448 0 : if (no)
449 : value = "disabled";
450 0 : else if (poisoned_reverse)
451 : value = "poison-reverse";
452 : else
453 0 : value = "simple";
454 :
455 0 : nb_cli_enqueue_change(vty, "./split-horizon", NB_OP_MODIFY, value);
456 :
457 0 : return nb_cli_apply_changes(vty, "./frr-ripngd:ripng");
458 : }
459 :
460 0 : void cli_show_ipv6_ripng_split_horizon(struct vty *vty,
461 : const struct lyd_node *dnode,
462 : bool show_defaults)
463 : {
464 0 : int value;
465 :
466 0 : value = yang_dnode_get_enum(dnode, NULL);
467 0 : switch (value) {
468 0 : case RIPNG_NO_SPLIT_HORIZON:
469 0 : vty_out(vty, " no ipv6 ripng split-horizon\n");
470 0 : break;
471 0 : case RIPNG_SPLIT_HORIZON:
472 0 : vty_out(vty, " ipv6 ripng split-horizon\n");
473 0 : break;
474 0 : case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
475 0 : vty_out(vty, " ipv6 ripng split-horizon poisoned-reverse\n");
476 0 : break;
477 : }
478 0 : }
479 :
480 : /*
481 : * XPath: /frr-ripngd:clear-ripng-route
482 : */
483 0 : DEFPY_YANG (clear_ipv6_rip,
484 : clear_ipv6_rip_cmd,
485 : "clear ipv6 ripng [vrf WORD]",
486 : CLEAR_STR
487 : IPV6_STR
488 : "Clear IPv6 RIP database\n"
489 : VRF_CMD_HELP_STR)
490 : {
491 0 : struct list *input;
492 0 : int ret;
493 :
494 0 : input = list_new();
495 0 : if (vrf) {
496 0 : struct yang_data *yang_vrf;
497 :
498 0 : yang_vrf = yang_data_new(
499 : "/frr-ripngd:clear-ripng-route/input/vrf", vrf);
500 0 : listnode_add(input, yang_vrf);
501 : }
502 :
503 0 : ret = nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", input, NULL);
504 :
505 0 : list_delete(&input);
506 :
507 0 : return ret;
508 : }
509 :
510 0 : DEFUN (ripng_ipv6_distribute_list,
511 : ripng_ipv6_distribute_list_cmd,
512 : "ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
513 : "IPv6\n"
514 : "Filter networks in routing updates\n"
515 : "Specify a prefix\n"
516 : "Access-list name\n"
517 : "Filter incoming routing updates\n"
518 : "Filter outgoing routing updates\n"
519 : "Interface name\n")
520 : {
521 0 : const char *ifname = NULL;
522 0 : int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
523 :
524 0 : if (argv[argc - 1]->type == VARIABLE_TKN)
525 0 : ifname = argv[argc - 1]->arg;
526 :
527 0 : return distribute_list_parser(prefix, false, argv[3 + prefix]->text,
528 0 : argv[2 + prefix]->arg, ifname);
529 : }
530 :
531 0 : DEFUN (ripng_no_ipv6_distribute_list,
532 : ripng_no_ipv6_distribute_list_cmd,
533 : "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME <in|out> [WORD]",
534 : NO_STR
535 : "IPv6\n"
536 : "Filter networks in routing updates\n"
537 : "Specify a prefix\n"
538 : "Access-list name\n"
539 : "Filter incoming routing updates\n"
540 : "Filter outgoing routing updates\n"
541 : "Interface name\n")
542 : {
543 0 : const char *ifname = NULL;
544 0 : int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
545 :
546 0 : if (argv[argc - 1]->type == VARIABLE_TKN)
547 0 : ifname = argv[argc - 1]->arg;
548 :
549 0 : return distribute_list_no_parser(vty, prefix, false,
550 0 : argv[4 + prefix]->text,
551 0 : argv[3 + prefix]->arg, ifname);
552 : }
553 :
554 1 : void ripng_cli_init(void)
555 : {
556 1 : install_element(CONFIG_NODE, &router_ripng_cmd);
557 1 : install_element(CONFIG_NODE, &no_router_ripng_cmd);
558 :
559 1 : install_element(RIPNG_NODE, &ripng_ipv6_distribute_list_cmd);
560 1 : install_element(RIPNG_NODE, &ripng_no_ipv6_distribute_list_cmd);
561 :
562 1 : install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd);
563 1 : install_element(RIPNG_NODE, &ripng_default_information_originate_cmd);
564 1 : install_element(RIPNG_NODE, &ripng_default_metric_cmd);
565 1 : install_element(RIPNG_NODE, &no_ripng_default_metric_cmd);
566 1 : install_element(RIPNG_NODE, &ripng_network_prefix_cmd);
567 1 : install_element(RIPNG_NODE, &ripng_network_if_cmd);
568 1 : install_element(RIPNG_NODE, &ripng_offset_list_cmd);
569 1 : install_element(RIPNG_NODE, &ripng_passive_interface_cmd);
570 1 : install_element(RIPNG_NODE, &ripng_redistribute_cmd);
571 1 : install_element(RIPNG_NODE, &ripng_route_cmd);
572 1 : install_element(RIPNG_NODE, &ripng_aggregate_address_cmd);
573 1 : install_element(RIPNG_NODE, &ripng_timers_cmd);
574 1 : install_element(RIPNG_NODE, &no_ripng_timers_cmd);
575 :
576 1 : install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
577 :
578 1 : install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
579 1 : }
|