diff options
Diffstat (limited to 'ripd/rip_cli.c')
-rw-r--r-- | ripd/rip_cli.c | 1112 |
1 files changed, 1112 insertions, 0 deletions
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c new file mode 100644 index 0000000..73442bf --- /dev/null +++ b/ripd/rip_cli.c @@ -0,0 +1,1112 @@ +/* + * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org> + * Copyright (C) 2018 NetDEF, Inc. + * Renato Westphal + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "if.h" +#include "vrf.h" +#include "log.h" +#include "prefix.h" +#include "command.h" +#include "northbound_cli.h" +#include "libfrr.h" + +#include "ripd/ripd.h" +#include "ripd/rip_nb.h" +#ifndef VTYSH_EXTRACT_PL +#include "ripd/rip_cli_clippy.c" +#endif + +/* + * XPath: /frr-ripd:ripd/instance + */ +DEFPY_YANG_NOSH (router_rip, + router_rip_cmd, + "router rip [vrf NAME]", + "Enable a routing process\n" + "Routing Information Protocol (RIP)\n" + VRF_CMD_HELP_STR) +{ + char xpath[XPATH_MAXLEN]; + int ret; + + /* Build RIP instance XPath. */ + if (!vrf) + vrf = VRF_DEFAULT_NAME; + snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']", + vrf); + + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + ret = nb_cli_apply_changes(vty, NULL); + if (ret == CMD_SUCCESS) + VTY_PUSH_XPATH(RIP_NODE, xpath); + + return ret; +} + +DEFPY_YANG (no_router_rip, + no_router_rip_cmd, + "no router rip [vrf NAME]", + NO_STR + "Enable a routing process\n" + "Routing Information Protocol (RIP)\n" + VRF_CMD_HELP_STR) +{ + char xpath[XPATH_MAXLEN]; + + /* Build RIP instance XPath. */ + if (!vrf) + vrf = VRF_DEFAULT_NAME; + snprintf(xpath, sizeof(xpath), "/frr-ripd:ripd/instance[vrf='%s']", + vrf); + + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes_clear_pending(vty, NULL); +} + +void cli_show_router_rip(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *vrf_name; + + vrf_name = yang_dnode_get_string(dnode, "./vrf"); + + vty_out(vty, "!\n"); + vty_out(vty, "router rip"); + if (!strmatch(vrf_name, VRF_DEFAULT_NAME)) + vty_out(vty, " vrf %s", vrf_name); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-ripd:ripd/instance/allow-ecmp + */ +DEFPY_YANG (rip_allow_ecmp, + rip_allow_ecmp_cmd, + "[no] allow-ecmp", + NO_STR + "Allow Equal Cost MultiPath\n") +{ + nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_allow_ecmp(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " allow-ecmp\n"); +} + +/* + * XPath: /frr-ripd:ripd/instance/default-information-originate + */ +DEFPY_YANG (rip_default_information_originate, + rip_default_information_originate_cmd, + "[no] default-information originate", + NO_STR + "Control distribution of default route\n" + "Distribute a default route\n") +{ + nb_cli_enqueue_change(vty, "./default-information-originate", + NB_OP_MODIFY, no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_default_information_originate(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " default-information originate\n"); +} + +/* + * XPath: /frr-ripd:ripd/instance/default-metric + */ +DEFPY_YANG (rip_default_metric, + rip_default_metric_cmd, + "default-metric (1-16)", + "Set a metric of redistribute routes\n" + "Default metric\n") +{ + nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, + default_metric_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_rip_default_metric, + no_rip_default_metric_cmd, + "no default-metric [(1-16)]", + NO_STR + "Set a metric of redistribute routes\n" + "Default metric\n") +{ + nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_default_metric(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " default-metric %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:ripd/instance/distance/default + */ +DEFPY_YANG (rip_distance, + rip_distance_cmd, + "distance (1-255)", + "Administrative distance\n" + "Distance value\n") +{ + nb_cli_enqueue_change(vty, "./distance/default", NB_OP_MODIFY, + distance_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_rip_distance, + no_rip_distance_cmd, + "no distance [(1-255)]", + NO_STR + "Administrative distance\n" + "Distance value\n") +{ + nb_cli_enqueue_change(vty, "./distance/default", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_distance(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (yang_dnode_is_default(dnode, NULL)) + vty_out(vty, " no distance\n"); + else + vty_out(vty, " distance %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:ripd/instance/distance/source + */ +DEFPY_YANG (rip_distance_source, + rip_distance_source_cmd, + "[no] distance (1-255) A.B.C.D/M$prefix [WORD$acl]", + NO_STR + "Administrative distance\n" + "Distance value\n" + "IP source prefix\n" + "Access list name\n") +{ + if (!no) { + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY, + distance_str); + nb_cli_enqueue_change(vty, "./access-list", + acl ? NB_OP_MODIFY : NB_OP_DESTROY, acl); + } else + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, "./distance/source[prefix='%s']", + prefix_str); +} + +void cli_show_rip_distance_source(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " distance %s %s", + yang_dnode_get_string(dnode, "./distance"), + yang_dnode_get_string(dnode, "./prefix")); + if (yang_dnode_exists(dnode, "./access-list")) + vty_out(vty, " %s", + yang_dnode_get_string(dnode, "./access-list")); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-ripd:ripd/instance/explicit-neighbor + */ +DEFPY_YANG (rip_neighbor, + rip_neighbor_cmd, + "[no] neighbor A.B.C.D", + NO_STR + "Specify a neighbor router\n" + "Neighbor address\n") +{ + nb_cli_enqueue_change(vty, "./explicit-neighbor", + no ? NB_OP_DESTROY : NB_OP_CREATE, neighbor_str); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_neighbor(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " neighbor %s\n", yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:ripd/instance/network + */ +DEFPY_YANG (rip_network_prefix, + rip_network_prefix_cmd, + "[no] network A.B.C.D/M", + NO_STR + "Enable routing on an IP network\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") +{ + nb_cli_enqueue_change(vty, "./network", + no ? NB_OP_DESTROY : NB_OP_CREATE, network_str); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_network_prefix(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:ripd/instance/interface + */ +DEFPY_YANG (rip_network_if, + rip_network_if_cmd, + "[no] network WORD", + NO_STR + "Enable routing on an IP network\n" + "Interface name\n") +{ + nb_cli_enqueue_change(vty, "./interface", + no ? NB_OP_DESTROY : NB_OP_CREATE, network); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_network_interface(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:ripd/instance/offset-list + */ +DEFPY_YANG (rip_offset_list, + rip_offset_list_cmd, + "[no] offset-list ACCESSLIST4_NAME$acl <in|out>$direction (0-16)$metric [IFNAME]", + NO_STR + "Modify RIP metric\n" + "Access-list name\n" + "For incoming updates\n" + "For outgoing updates\n" + "Metric value\n" + "Interface to match\n") +{ + if (!no) { + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl); + nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY, + metric_str); + } else + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes( + vty, "./offset-list[interface='%s'][direction='%s']", + ifname ? ifname : "*", direction); +} + +void cli_show_rip_offset_list(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + const char *interface; + + interface = yang_dnode_get_string(dnode, "./interface"); + + vty_out(vty, " offset-list %s %s %s", + yang_dnode_get_string(dnode, "./access-list"), + yang_dnode_get_string(dnode, "./direction"), + yang_dnode_get_string(dnode, "./metric")); + if (!strmatch(interface, "*")) + vty_out(vty, " %s", interface); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-ripd:ripd/instance/passive-default + */ +DEFPY_YANG (rip_passive_default, + rip_passive_default_cmd, + "[no] passive-interface default", + NO_STR + "Suppress routing updates on an interface\n" + "default for all interfaces\n") +{ + nb_cli_enqueue_change(vty, "./passive-default", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_passive_default(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " passive-interface default\n"); +} + +/* + * XPath: /frr-ripd:ripd/instance/passive-interface + * /frr-ripd:ripd/instance/non-passive-interface + */ +DEFPY_YANG (rip_passive_interface, + rip_passive_interface_cmd, + "[no] passive-interface IFNAME", + NO_STR + "Suppress routing updates on an interface\n" + "Interface name\n") +{ + bool passive_default = + yang_dnode_get_bool(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, "/passive-default"); + + if (passive_default) { + nb_cli_enqueue_change(vty, "./non-passive-interface", + no ? NB_OP_CREATE : NB_OP_DESTROY, + ifname); + } else { + nb_cli_enqueue_change(vty, "./passive-interface", + no ? NB_OP_DESTROY : NB_OP_CREATE, + ifname); + } + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_passive_interface(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " passive-interface %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +void cli_show_rip_non_passive_interface(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " no passive-interface %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:ripd/instance/redistribute + */ +DEFPY_YANG (rip_redistribute, + rip_redistribute_cmd, + "[no] redistribute " FRR_REDIST_STR_RIPD "$protocol [{metric (0-16)|route-map RMAP_NAME$route_map}]", + NO_STR + REDIST_STR + FRR_REDIST_HELP_STR_RIPD + "Metric\n" + "Metric value\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + if (!no) { + nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); + nb_cli_enqueue_change(vty, "./route-map", + route_map ? NB_OP_MODIFY : NB_OP_DESTROY, + route_map); + nb_cli_enqueue_change(vty, "./metric", + metric_str ? NB_OP_MODIFY : NB_OP_DESTROY, + metric_str); + } else + nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, "./redistribute[protocol='%s']", + protocol); +} + +void cli_show_rip_redistribute(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " redistribute %s", + yang_dnode_get_string(dnode, "./protocol")); + if (yang_dnode_exists(dnode, "./metric")) + vty_out(vty, " metric %s", + yang_dnode_get_string(dnode, "./metric")); + if (yang_dnode_exists(dnode, "./route-map")) + vty_out(vty, " route-map %s", + yang_dnode_get_string(dnode, "./route-map")); + vty_out(vty, "\n"); +} + +/* + * XPath: /frr-ripd:ripd/instance/static-route + */ +DEFPY_YANG (rip_route, + rip_route_cmd, + "[no] route A.B.C.D/M", + NO_STR + "RIP static route configuration\n" + "IP prefix <network>/<length>\n") +{ + nb_cli_enqueue_change(vty, "./static-route", + no ? NB_OP_DESTROY : NB_OP_CREATE, route_str); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_route(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:ripd/instance/timers + */ +DEFPY_YANG (rip_timers, + rip_timers_cmd, + "timers basic (5-2147483647)$update (5-2147483647)$timeout (5-2147483647)$garbage", + "Adjust routing timers\n" + "Basic routing protocol update timers\n" + "Routing table update timer value in second. Default is 30.\n" + "Routing information timeout timer. Default is 180.\n" + "Garbage collection timer. Default is 120.\n") +{ + nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, + update_str); + nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, + timeout_str); + nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, + garbage_str); + + return nb_cli_apply_changes(vty, "./timers"); +} + +DEFPY_YANG (no_rip_timers, + no_rip_timers_cmd, + "no timers basic [(5-2147483647) (5-2147483647) (5-2147483647)]", + NO_STR + "Adjust routing timers\n" + "Basic routing protocol update timers\n" + "Routing table update timer value in second. Default is 30.\n" + "Routing information timeout timer. Default is 180.\n" + "Garbage collection timer. Default is 120.\n") +{ + nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, "./timers"); +} + +void cli_show_rip_timers(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " timers basic %s %s %s\n", + yang_dnode_get_string(dnode, "./update-interval"), + yang_dnode_get_string(dnode, "./holddown-interval"), + yang_dnode_get_string(dnode, "./flush-interval")); +} + +/* + * XPath: /frr-ripd:ripd/instance/version + */ +DEFPY_YANG (rip_version, + rip_version_cmd, + "version (1-2)", + "Set routing protocol version\n" + "version\n") +{ + nb_cli_enqueue_change(vty, "./version/receive", NB_OP_MODIFY, + version_str); + nb_cli_enqueue_change(vty, "./version/send", NB_OP_MODIFY, version_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY_YANG (no_rip_version, + no_rip_version_cmd, + "no version [(1-2)]", + NO_STR + "Set routing protocol version\n" + "version\n") +{ + nb_cli_enqueue_change(vty, "./version/receive", NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, "./version/send", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_rip_version(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + /* + * We have only one "version" command and three possible combinations of + * send/receive values. + */ + switch (yang_dnode_get_enum(dnode, "./receive")) { + case RI_RIP_VERSION_1: + vty_out(vty, " version 1\n"); + break; + case RI_RIP_VERSION_2: + vty_out(vty, " version 2\n"); + break; + case RI_RIP_VERSION_1_AND_2: + vty_out(vty, " no version\n"); + break; + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/split-horizon + */ +DEFPY_YANG (ip_rip_split_horizon, + ip_rip_split_horizon_cmd, + "[no] ip rip split-horizon [poisoned-reverse$poisoned_reverse]", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Perform split horizon\n" + "With poisoned-reverse\n") +{ + const char *value; + + if (no) + value = "disabled"; + else if (poisoned_reverse) + value = "poison-reverse"; + else + value = "simple"; + + nb_cli_enqueue_change(vty, "./split-horizon", NB_OP_MODIFY, value); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +void cli_show_ip_rip_split_horizon(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + int value; + + value = yang_dnode_get_enum(dnode, NULL); + switch (value) { + case RIP_NO_SPLIT_HORIZON: + vty_out(vty, " no ip rip split-horizon\n"); + break; + case RIP_SPLIT_HORIZON: + vty_out(vty, " ip rip split-horizon\n"); + break; + case RIP_SPLIT_HORIZON_POISONED_REVERSE: + vty_out(vty, " ip rip split-horizon poisoned-reverse\n"); + break; + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/v2-broadcast + */ +DEFPY_YANG (ip_rip_v2_broadcast, + ip_rip_v2_broadcast_cmd, + "[no] ip rip v2-broadcast", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Send ip broadcast v2 update\n") +{ + nb_cli_enqueue_change(vty, "./v2-broadcast", NB_OP_MODIFY, + no ? "false" : "true"); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +void cli_show_ip_rip_v2_broadcast(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + if (!yang_dnode_get_bool(dnode, NULL)) + vty_out(vty, " no"); + + vty_out(vty, " ip rip v2-broadcast\n"); +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-receive + */ +DEFPY_YANG (ip_rip_receive_version, + ip_rip_receive_version_cmd, + "ip rip receive version <{1$v1|2$v2}|none>", + IP_STR + "Routing Information Protocol\n" + "Advertisement reception\n" + "Version control\n" + "RIP version 1\n" + "RIP version 2\n" + "None\n") +{ + const char *value; + + if (v1 && v2) + value = "both"; + else if (v1) + value = "1"; + else if (v2) + value = "2"; + else + value = "none"; + + nb_cli_enqueue_change(vty, "./version-receive", NB_OP_MODIFY, value); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +DEFPY_YANG (no_ip_rip_receive_version, + no_ip_rip_receive_version_cmd, + "no ip rip receive version [<{1|2}|none>]", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Advertisement reception\n" + "Version control\n" + "RIP version 1\n" + "RIP version 2\n" + "None\n") +{ + nb_cli_enqueue_change(vty, "./version-receive", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +void cli_show_ip_rip_receive_version(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + switch (yang_dnode_get_enum(dnode, NULL)) { + case RI_RIP_UNSPEC: + vty_out(vty, " no ip rip receive version\n"); + break; + case RI_RIP_VERSION_1: + vty_out(vty, " ip rip receive version 1\n"); + break; + case RI_RIP_VERSION_2: + vty_out(vty, " ip rip receive version 2\n"); + break; + case RI_RIP_VERSION_1_AND_2: + vty_out(vty, " ip rip receive version 1 2\n"); + break; + case RI_RIP_VERSION_NONE: + vty_out(vty, " ip rip receive version none\n"); + break; + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/version-send + */ +DEFPY_YANG (ip_rip_send_version, + ip_rip_send_version_cmd, + "ip rip send version <{1$v1|2$v2}|none>", + IP_STR + "Routing Information Protocol\n" + "Advertisement transmission\n" + "Version control\n" + "RIP version 1\n" + "RIP version 2\n" + "None\n") +{ + const char *value; + + if (v1 && v2) + value = "both"; + else if (v1) + value = "1"; + else if (v2) + value = "2"; + else + value = "none"; + + nb_cli_enqueue_change(vty, "./version-send", NB_OP_MODIFY, value); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +DEFPY_YANG (no_ip_rip_send_version, + no_ip_rip_send_version_cmd, + "no ip rip send version [<{1|2}|none>]", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Advertisement transmission\n" + "Version control\n" + "RIP version 1\n" + "RIP version 2\n" + "None\n") +{ + nb_cli_enqueue_change(vty, "./version-send", NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +void cli_show_ip_rip_send_version(struct vty *vty, const struct lyd_node *dnode, + bool show_defaults) +{ + switch (yang_dnode_get_enum(dnode, NULL)) { + case RI_RIP_UNSPEC: + vty_out(vty, " no ip rip send version\n"); + break; + case RI_RIP_VERSION_1: + vty_out(vty, " ip rip send version 1\n"); + break; + case RI_RIP_VERSION_2: + vty_out(vty, " ip rip send version 2\n"); + break; + case RI_RIP_VERSION_1_AND_2: + vty_out(vty, " ip rip send version 1 2\n"); + break; + case RI_RIP_VERSION_NONE: + vty_out(vty, " ip rip send version none\n"); + break; + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-scheme + */ +DEFPY_YANG (ip_rip_authentication_mode, + ip_rip_authentication_mode_cmd, + "ip rip authentication mode <md5$mode [auth-length <rfc|old-ripd>$auth_length]|text$mode>", + IP_STR + "Routing Information Protocol\n" + "Authentication control\n" + "Authentication mode\n" + "Keyed message digest\n" + "MD5 authentication data length\n" + "RFC compatible\n" + "Old ripd compatible\n" + "Clear text authentication\n") +{ + const char *value = NULL; + + if (auth_length) { + if (strmatch(auth_length, "rfc")) + value = "16"; + else + value = "20"; + } + + nb_cli_enqueue_change(vty, "./authentication-scheme/mode", NB_OP_MODIFY, + strmatch(mode, "md5") ? "md5" : "plain-text"); + if (strmatch(mode, "md5")) + nb_cli_enqueue_change(vty, + "./authentication-scheme/md5-auth-length", + NB_OP_MODIFY, value); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +DEFPY_YANG (no_ip_rip_authentication_mode, + no_ip_rip_authentication_mode_cmd, + "no ip rip authentication mode [<md5 [auth-length <rfc|old-ripd>]|text>]", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Authentication control\n" + "Authentication mode\n" + "Keyed message digest\n" + "MD5 authentication data length\n" + "RFC compatible\n" + "Old ripd compatible\n" + "Clear text authentication\n") +{ + nb_cli_enqueue_change(vty, "./authentication-scheme/mode", NB_OP_MODIFY, + NULL); + nb_cli_enqueue_change(vty, "./authentication-scheme/md5-auth-length", + NB_OP_DESTROY, NULL); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +void cli_show_ip_rip_authentication_scheme(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + switch (yang_dnode_get_enum(dnode, "./mode")) { + case RIP_NO_AUTH: + vty_out(vty, " no ip rip authentication mode\n"); + break; + case RIP_AUTH_SIMPLE_PASSWORD: + vty_out(vty, " ip rip authentication mode text\n"); + break; + case RIP_AUTH_MD5: + vty_out(vty, " ip rip authentication mode md5"); + if (show_defaults + || !yang_dnode_is_default(dnode, "./md5-auth-length")) { + if (yang_dnode_get_enum(dnode, "./md5-auth-length") + == RIP_AUTH_MD5_SIZE) + vty_out(vty, " auth-length rfc"); + else + vty_out(vty, " auth-length old-ripd"); + } + vty_out(vty, "\n"); + break; + } +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-password + */ +DEFPY_YANG (ip_rip_authentication_string, + ip_rip_authentication_string_cmd, + "ip rip authentication string LINE$password", + IP_STR + "Routing Information Protocol\n" + "Authentication control\n" + "Authentication string\n" + "Authentication string\n") +{ + if (strlen(password) > 16) { + vty_out(vty, + "%% RIPv2 authentication string must be shorter than 16\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, + "/frr-ripd:rip/authentication-key-chain")) { + vty_out(vty, "%% key-chain configuration exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_MODIFY, + password); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +DEFPY_YANG (no_ip_rip_authentication_string, + no_ip_rip_authentication_string_cmd, + "no ip rip authentication string [LINE]", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Authentication control\n" + "Authentication string\n" + "Authentication string\n") +{ + nb_cli_enqueue_change(vty, "./authentication-password", NB_OP_DESTROY, + NULL); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +void cli_show_ip_rip_authentication_string(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " ip rip authentication string %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-interface:lib/interface/frr-ripd:rip/authentication-key-chain + */ +DEFPY_YANG (ip_rip_authentication_key_chain, + ip_rip_authentication_key_chain_cmd, + "ip rip authentication key-chain LINE$keychain", + IP_STR + "Routing Information Protocol\n" + "Authentication control\n" + "Authentication key-chain\n" + "name of key-chain\n") +{ + if (yang_dnode_existsf(vty->candidate_config->dnode, "%s%s", + VTY_CURR_XPATH, + "/frr-ripd:rip/authentication-password")) { + vty_out(vty, "%% authentication string configuration exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + nb_cli_enqueue_change(vty, "./authentication-key-chain", NB_OP_MODIFY, + keychain); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +DEFPY_YANG (no_ip_rip_authentication_key_chain, + no_ip_rip_authentication_key_chain_cmd, + "no ip rip authentication key-chain [LINE]", + NO_STR + IP_STR + "Routing Information Protocol\n" + "Authentication control\n" + "Authentication key-chain\n" + "name of key-chain\n") +{ + nb_cli_enqueue_change(vty, "./authentication-key-chain", NB_OP_DESTROY, + NULL); + + return nb_cli_apply_changes(vty, "./frr-ripd:rip"); +} + +void cli_show_ip_rip_authentication_key_chain(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " ip rip authentication key-chain %s\n", + yang_dnode_get_string(dnode, NULL)); +} + +/* + * XPath: /frr-ripd:clear-rip-route + */ +DEFPY_YANG (clear_ip_rip, + clear_ip_rip_cmd, + "clear ip rip [vrf WORD]", + CLEAR_STR + IP_STR + "Clear IP RIP database\n" + VRF_CMD_HELP_STR) +{ + struct list *input; + int ret; + + input = list_new(); + if (vrf) { + struct yang_data *yang_vrf; + + yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf", + vrf); + listnode_add(input, yang_vrf); + } + + ret = nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", input, NULL); + + list_delete(&input); + + return ret; +} + +DEFUN (rip_distribute_list, + rip_distribute_list_cmd, + "distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]", + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_parser(prefix, true, argv[2 + prefix]->text, + argv[1 + prefix]->arg, ifname); +} + +DEFUN (rip_no_distribute_list, + rip_no_distribute_list_cmd, + "no distribute-list [prefix] ACCESSLIST4_NAME <in|out> [WORD]", + NO_STR + "Filter networks in routing updates\n" + "Specify a prefix\n" + "Access-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") +{ + const char *ifname = NULL; + int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + + if (argv[argc - 1]->type == VARIABLE_TKN) + ifname = argv[argc - 1]->arg; + + return distribute_list_no_parser(vty, prefix, true, + argv[3 + prefix]->text, + argv[2 + prefix]->arg, ifname); +} + +void rip_cli_init(void) +{ + install_element(CONFIG_NODE, &router_rip_cmd); + install_element(CONFIG_NODE, &no_router_rip_cmd); + + install_element(RIP_NODE, &rip_distribute_list_cmd); + install_element(RIP_NODE, &rip_no_distribute_list_cmd); + + install_element(RIP_NODE, &rip_allow_ecmp_cmd); + install_element(RIP_NODE, &rip_default_information_originate_cmd); + install_element(RIP_NODE, &rip_default_metric_cmd); + install_element(RIP_NODE, &no_rip_default_metric_cmd); + install_element(RIP_NODE, &rip_distance_cmd); + install_element(RIP_NODE, &no_rip_distance_cmd); + install_element(RIP_NODE, &rip_distance_source_cmd); + install_element(RIP_NODE, &rip_neighbor_cmd); + install_element(RIP_NODE, &rip_network_prefix_cmd); + install_element(RIP_NODE, &rip_network_if_cmd); + install_element(RIP_NODE, &rip_offset_list_cmd); + install_element(RIP_NODE, &rip_passive_default_cmd); + install_element(RIP_NODE, &rip_passive_interface_cmd); + install_element(RIP_NODE, &rip_redistribute_cmd); + install_element(RIP_NODE, &rip_route_cmd); + install_element(RIP_NODE, &rip_timers_cmd); + install_element(RIP_NODE, &no_rip_timers_cmd); + install_element(RIP_NODE, &rip_version_cmd); + install_element(RIP_NODE, &no_rip_version_cmd); + + install_element(INTERFACE_NODE, &ip_rip_split_horizon_cmd); + install_element(INTERFACE_NODE, &ip_rip_v2_broadcast_cmd); + install_element(INTERFACE_NODE, &ip_rip_receive_version_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_receive_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_send_version_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_send_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_mode_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_string_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_authentication_string_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd); + install_element(INTERFACE_NODE, + &no_ip_rip_authentication_key_chain_cmd); + + install_element(ENABLE_NODE, &clear_ip_rip_cmd); +} |