From 07679ad98ab97a4b783f7ae54f88d4d70a5729de Mon Sep 17 00:00:00 2001 From: Igor Ryzhov Date: Sun, 8 Aug 2021 22:38:50 +0300 Subject: [PATCH] *: explicitly print "exit" at the end of every node config There is a possibility that the same line can be matched as a command in some node and its parent node. In this case, when reading the config, this line is always executed as a command of the child node. For example, with the following config: ``` router ospf network 193.168.0.0/16 area 0 ! mpls ldp discovery hello interval 111 ! ``` Line `mpls ldp` is processed as command `mpls ldp-sync` inside the `router ospf` node. This leads to a complete loss of `mpls ldp` node configuration. To eliminate this issue and all possible similar issues, let's print an explicit "exit" at the end of every node config. This commit also changes indentation for a couple of existing exit commands so that all existing commands are on the same level as their corresponding node-entering commands. Fixes #9206. Signed-off-by: Igor Ryzhov --- babeld/babel_interface.c | 2 +- babeld/babeld.c | 2 ++ bfdd/bfdd_cli.c | 2 ++ bgpd/bgp_bmp.c | 2 ++ bgpd/bgp_rpki.c | 2 +- bgpd/bgp_vty.c | 1 + bgpd/rfapi/bgp_rfapi_cfg.c | 8 ++++---- eigrpd/eigrp_cli.c | 1 + isisd/isis_circuit.c | 2 +- isisd/isis_cli.c | 5 +++++ isisd/isis_nb.c | 1 + isisd/isis_nb.h | 1 + isisd/isisd.c | 2 ++ ldpd/ldp_vty_conf.c | 6 ++++++ lib/if.c | 6 ++++++ lib/keychain.c | 1 + lib/nexthop_group.c | 1 + lib/routemap_cli.c | 1 + lib/vty.c | 4 +++- nhrpd/nhrp_vty.c | 2 +- ospf6d/ospf6_interface.c | 2 +- ospf6d/ospf6_top.c | 2 ++ ospfd/ospf_vty.c | 4 +++- pathd/path_cli.c | 22 ++++++++++++++++++++++ pathd/path_nb.c | 3 +++ pathd/path_nb.h | 4 ++++ pathd/path_pcep_cli.c | 9 ++++++++- pbrd/pbr_vty.c | 3 ++- pimd/pim_instance.c | 2 +- pimd/pim_vty.c | 2 +- ripd/ripd.c | 2 ++ ripngd/ripngd.c | 2 ++ staticd/static_vrf.c | 2 +- tests/lib/cli/test_cli.refout.in | 2 -- vtysh/vtysh_config.c | 18 +++++++++--------- zebra/interface.c | 4 ++-- zebra/zebra_pw.c | 1 + zebra/zebra_srv6_vty.c | 4 ++++ zebra/zebra_vrf.c | 2 +- 39 files changed, 112 insertions(+), 30 deletions(-) diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index c1e5ffde3c91..615ed9fee31a 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -1362,7 +1362,7 @@ interface_config_write (struct vty *vty) write++; } } - vty_endframe (vty, "!\n"); + vty_endframe (vty, "exit\n!\n"); write++; } return write; diff --git a/babeld/babeld.c b/babeld/babeld.c index b9623b64b5fa..b9037423b48c 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -132,6 +132,8 @@ babel_config_write (struct vty *vty) lines += config_write_distribute (vty, babel_routing_process->distribute_ctx); + vty_out (vty, "exit\n"); + return lines; } diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 26ff4a758a03..384bb26fd7d3 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -101,6 +101,7 @@ void bfd_cli_show_header(struct vty *vty, void bfd_cli_show_header_end(struct vty *vty, struct lyd_node *dnode __attribute__((__unused__))) { + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } @@ -275,6 +276,7 @@ void bfd_cli_show_multi_hop_peer(struct vty *vty, void bfd_cli_show_peer_end(struct vty *vty, struct lyd_node *dnode __attribute__((__unused__))) { + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); } diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index dbc35de80bd1..1bc3fd0dbae7 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -2400,6 +2400,8 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty) frr_each (bmp_actives, &bt->actives, ba) vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u\n", ba->hostname, ba->port, ba->minretry, ba->maxretry); + + vty_out(vty, " exit\n"); } return 0; diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 286612da15be..ca3f93899b19 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -932,7 +932,7 @@ static int config_write(struct vty *vty) vty_out(vty, "preference %hhu\n", cache->preference); } - vty_out(vty, " exit\n"); + vty_out(vty, "exit\n"); return 1; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 27f147a4aaf9..dd4a776a21c7 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -17213,6 +17213,7 @@ int bgp_config_write(struct vty *vty) bgp_rfapi_cfg_write(vty, bgp); #endif + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } return 0; diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index cc64261388c6..2437bd8cfee8 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -4043,7 +4043,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) rfg->routemap_redist_name [ZEBRA_ROUTE_BGP_DIRECT_EXT]); } - vty_out(vty, " exit-vrf-policy\n"); + vty_out(vty, " exit-vrf-policy\n"); vty_out(vty, "!\n"); } if (hc->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP) { @@ -4121,7 +4121,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) vty, bgp->rfapi->rfp, RFAPI_RFP_CFG_GROUP_L2, rfgc->name, rfgc->rfp_cfg); - vty_out(vty, " exit-vnc\n"); + vty_out(vty, " exit-vnc\n"); vty_out(vty, "!\n"); } } @@ -4199,7 +4199,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) vty, bgp->rfapi->rfp, RFAPI_RFP_CFG_GROUP_DEFAULT, NULL, bgp->rfapi_cfg->default_rfp_cfg); - vty_out(vty, " exit-vnc\n"); + vty_out(vty, " exit-vnc\n"); vty_out(vty, "!\n"); } @@ -4364,7 +4364,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp) vty, bgp->rfapi->rfp, RFAPI_RFP_CFG_GROUP_NVE, rfg->name, rfg->rfp_cfg); - vty_out(vty, " exit-vnc\n"); + vty_out(vty, " exit-vnc\n"); vty_out(vty, "!\n"); } } /* have listen ports */ diff --git a/eigrpd/eigrp_cli.c b/eigrpd/eigrp_cli.c index 35536979ea7f..d61f43586f13 100644 --- a/eigrpd/eigrp_cli.c +++ b/eigrpd/eigrp_cli.c @@ -96,6 +96,7 @@ void eigrp_cli_show_header(struct vty *vty, struct lyd_node *dnode, void eigrp_cli_show_end_header(struct vty *vty, struct lyd_node *dnode) { + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index a78e4996b4a8..6f4a91be67d3 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1290,7 +1290,7 @@ static int isis_interface_config_write(struct vty *vty) write += hook_call(isis_circuit_config_write, circuit, vty); } - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return write; diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index ef86d47b2298..70ec66fd7feb 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -146,6 +146,11 @@ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, vty_out(vty, "\n"); } +void cli_show_router_isis_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, "exit\n"); +} + /* * XPath: /frr-interface:lib/interface/frr-isisd:isis/ * XPath: /frr-interface:lib/interface/frr-isisd:isis/ipv4-routing diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index ecad16229c18..f62a8d481335 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -32,6 +32,7 @@ const struct frr_yang_module_info frr_isisd_info = { .xpath = "/frr-isisd:isis/instance", .cbs = { .cli_show = cli_show_router_isis, + .cli_show_end = cli_show_router_isis_end, .create = isis_instance_create, .destroy = isis_instance_destroy, }, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index 0c2f7b6b7e5a..4680dd5ded9c 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -415,6 +415,7 @@ void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish( /* Optional 'cli_show' callbacks. */ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_router_isis_end(struct vty *vty, struct lyd_node *dnode); void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode, diff --git a/isisd/isisd.c b/isisd/isisd.c index 43efa0164daf..ebcc9985b40b 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -3011,6 +3011,8 @@ static int isis_config_write(struct vty *vty) write += area_write_mt_settings(area, vty); write += fabricd_write_settings(area, vty); + + vty_out(vty, "exit\n"); } } diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index b35d3dfa0079..fbd718bb099d 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -133,6 +133,8 @@ ldp_af_iface_config_write(struct vty *vty, int af) ia->hello_interval != 0) vty_out (vty, " discovery hello interval %u\n", ia->hello_interval); + + vty_out (vty, " exit\n"); } } @@ -314,6 +316,7 @@ ldp_config_write(struct vty *vty) ldp_af_config_write(vty, AF_INET, ldpd_conf, &ldpd_conf->ipv4); ldp_af_config_write(vty, AF_INET6, ldpd_conf, &ldpd_conf->ipv6); vty_out (vty, " !\n"); + vty_out (vty, "exit\n"); vty_out (vty, "!\n"); return (1); @@ -353,6 +356,8 @@ ldp_l2vpn_pw_config_write(struct vty *vty, struct l2vpn_pw *pw) " ! Incomplete config, specify a neighbor lsr-id\n"); if (missing_pwid) vty_out (vty," ! Incomplete config, specify a pw-id\n"); + + vty_out (vty, " exit\n"); } static int @@ -383,6 +388,7 @@ ldp_l2vpn_config_write(struct vty *vty) ldp_l2vpn_pw_config_write(vty, pw); vty_out (vty, " !\n"); + vty_out (vty, "exit\n"); vty_out (vty, "!\n"); } diff --git a/lib/if.c b/lib/if.c index 6c57855ca1f9..424880ff425a 100644 --- a/lib/if.c +++ b/lib/if.c @@ -1291,6 +1291,11 @@ static void cli_show_interface(struct vty *vty, struct lyd_node *dnode, vty_out(vty, "\n"); } +static void cli_show_interface_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, "exit\n"); +} + /* * XPath: /frr-interface:lib/interface/description */ @@ -1652,6 +1657,7 @@ const struct frr_yang_module_info frr_interface_info = { .create = lib_interface_create, .destroy = lib_interface_destroy, .cli_show = cli_show_interface, + .cli_show_end = cli_show_interface_end, .get_next = lib_interface_get_next, .get_keys = lib_interface_get_keys, .lookup_entry = lib_interface_lookup_entry, diff --git a/lib/keychain.c b/lib/keychain.c index db5c23b1bae4..02f83ef0a834 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -1044,6 +1044,7 @@ static int keychain_config_write(struct vty *vty) vty_out(vty, " exit\n"); } + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 4fee9bde3c2c..97d70189ff5f 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -1156,6 +1156,7 @@ static int nexthop_group_write(struct vty *vty) nexthop_group_write_nexthop_internal(vty, nh); } + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c index 77455d991ab9..8747c37f16b4 100644 --- a/lib/routemap_cli.c +++ b/lib/routemap_cli.c @@ -125,6 +125,7 @@ void route_map_instance_show(struct vty *vty, struct lyd_node *dnode, void route_map_instance_show_end(struct vty *vty, struct lyd_node *dnode) { + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/lib/vty.c b/lib/vty.c index f64ab83847af..fef16f1ee7a6 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -3040,7 +3040,7 @@ DEFPY (log_commands, /* Display current configuration. */ static int vty_config_write(struct vty *vty) { - vty_out(vty, "line vty\n"); + vty_frame(vty, "line vty\n"); if (vty_accesslist_name) vty_out(vty, " access-class %s\n", vty_accesslist_name); @@ -3058,6 +3058,8 @@ static int vty_config_write(struct vty *vty) if (no_password_check) vty_out(vty, " no login\n"); + vty_endframe(vty, "exit\n"); + if (do_log_commands) vty_out(vty, "log commands\n"); diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 60ce1e652325..a77121448e2c 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -1225,7 +1225,7 @@ static int interface_config_write(struct vty *vty) } } - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return 0; diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index bbb474ba1a18..b427a0c9bde3 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -2593,7 +2593,7 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) ospf6_bfd_write_config(vty, oi); - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return 0; } diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index fc181a6d188a..b159f11396fc 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -2237,6 +2237,8 @@ static int config_write_ospf6(struct vty *vty) ospf6_distribute_config_write(vty, ospf6); ospf6_asbr_summary_config_write(vty, ospf6); config_write_ospf6_gr_helper(vty, ospf6); + + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } return 0; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 4c248c0df31f..1843947dbabd 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -11970,7 +11970,7 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf) ospf_opaque_config_write_if(vty, ifp); - vty_endframe(vty, NULL); + vty_endframe(vty, "exit\n!\n"); } return write; @@ -12546,6 +12546,8 @@ static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) /* LDP-Sync print */ ospf_ldp_sync_write_config(vty, ospf); + vty_out(vty, "exit\n"); + write++; return write; } diff --git a/pathd/path_cli.c b/pathd/path_cli.c index 68baa61fa99a..bd629a2b7048 100644 --- a/pathd/path_cli.c +++ b/pathd/path_cli.c @@ -305,6 +305,11 @@ void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_string(dnode, "./name")); } +void cli_show_srte_segment_list_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, " exit\n"); +} + static int segment_list_has_src_dst( struct vty *vty, char *xpath, long index, const char *index_str, struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4, @@ -662,6 +667,11 @@ void cli_show_srte_policy(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_string(dnode, "./endpoint")); } +void cli_show_srte_policy_end(struct vty *vty, struct lyd_node *dnode) +{ + vty_out(vty, " exit\n"); +} + /* * XPath: /frr-pathd:pathd/srte/policy/name */ @@ -1233,6 +1243,15 @@ void cli_show_srte_policy_candidate_path(struct vty *vty, } } +void cli_show_srte_policy_candidate_path_end(struct vty *vty, + struct lyd_node *dnode) +{ + const char *type = yang_dnode_get_string(dnode, "./type"); + + if (strmatch(type, "dynamic")) + vty_out(vty, " exit\n"); +} + static int config_write_dnode(const struct lyd_node *dnode, void *arg) { struct vty *vty = arg; @@ -1256,6 +1275,9 @@ int config_write_segment_routing(struct vty *vty) hook_call(pathd_srte_config_write, vty); + vty_out(vty, " exit\n"); + vty_out(vty, "exit\n"); + return 1; } diff --git a/pathd/path_nb.c b/pathd/path_nb.c index 9c622883bc21..1ab8b7f39bc4 100644 --- a/pathd/path_nb.c +++ b/pathd/path_nb.c @@ -56,6 +56,7 @@ const struct frr_yang_module_info frr_pathd_info = { .cbs = { .create = pathd_srte_segment_list_create, .cli_show = cli_show_srte_segment_list, + .cli_show_end = cli_show_srte_segment_list_end, .destroy = pathd_srte_segment_list_destroy, .get_next = pathd_srte_segment_list_get_next, .get_keys = pathd_srte_segment_list_get_keys, @@ -136,6 +137,7 @@ const struct frr_yang_module_info frr_pathd_info = { .cbs = { .create = pathd_srte_policy_create, .cli_show = cli_show_srte_policy, + .cli_show_end = cli_show_srte_policy_end, .destroy = pathd_srte_policy_destroy, .get_next = pathd_srte_policy_get_next, .get_keys = pathd_srte_policy_get_keys, @@ -169,6 +171,7 @@ const struct frr_yang_module_info frr_pathd_info = { .cbs = { .create = pathd_srte_policy_candidate_path_create, .cli_show = cli_show_srte_policy_candidate_path, + .cli_show_end = cli_show_srte_policy_candidate_path_end, .destroy = pathd_srte_policy_candidate_path_destroy, .get_next = pathd_srte_policy_candidate_path_get_next, .get_keys = pathd_srte_policy_candidate_path_get_keys, diff --git a/pathd/path_nb.h b/pathd/path_nb.h index caeadd9cccc1..6a918b8b824d 100644 --- a/pathd/path_nb.h +++ b/pathd/path_nb.h @@ -112,10 +112,12 @@ void pathd_apply_finish(struct nb_cb_apply_finish_args *args); /* Optional 'cli_show' callbacks. */ void cli_show_srte_segment_list(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_srte_segment_list_end(struct vty *vty, struct lyd_node *dnode); void cli_show_srte_segment_list_segment(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_srte_policy(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_srte_policy_end(struct vty *vty, struct lyd_node *dnode); void cli_show_srte_policy_name(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_srte_policy_binding_sid(struct vty *vty, struct lyd_node *dnode, @@ -123,6 +125,8 @@ void cli_show_srte_policy_binding_sid(struct vty *vty, struct lyd_node *dnode, void cli_show_srte_policy_candidate_path(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_srte_policy_candidate_path_end(struct vty *vty, + struct lyd_node *dnode); /* Utility functions */ typedef void (*of_pref_cp_t)(enum objfun_type type, void *arg); diff --git a/pathd/path_pcep_cli.c b/pathd/path_pcep_cli.c index e602fd22df37..829df3179c26 100644 --- a/pathd/path_pcep_cli.c +++ b/pathd/path_pcep_cli.c @@ -1443,6 +1443,7 @@ int pcep_cli_pcep_config_write(struct vty *vty) pcep_cli_pcep_pce_config_write(vty); pcep_cli_pce_config_write(vty); pcep_cli_pcc_config_write(vty); + vty_out(vty, " exit\n"); return 1; } @@ -1467,7 +1468,7 @@ int pcep_cli_pcc_config_write(struct vty *vty) } if (pce_connections_g.num_connections == 0) { - return lines; + goto exit; } buf[0] = 0; @@ -1494,6 +1495,8 @@ int pcep_cli_pcc_config_write(struct vty *vty) lines++; buf[0] = 0; } +exit: + vty_out(vty, " exit\n"); return lines; } @@ -1654,6 +1657,8 @@ int pcep_cli_pce_config_write(struct vty *vty) vty_out(vty, "%s", buf); buf[0] = '\0'; + + vty_out(vty, " exit\n"); } return lines; @@ -1678,6 +1683,8 @@ int pcep_cli_pcep_pce_config_write(struct vty *vty) pcep_cli_print_pce_config(group_opts, buf, sizeof(buf)); vty_out(vty, "%s", buf); buf[0] = 0; + + vty_out(vty, " exit\n"); } return lines; diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 2936d1e34617..6c007acb5cde 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -1118,7 +1118,7 @@ static int pbr_interface_config_write(struct vty *vty) pbr_map_write_interfaces(vty, ifp); - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } } @@ -1184,6 +1184,7 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty, pbrms_nexthop_group_write_individual_nexthop(vty, pbrms); } + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); return 1; } diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index 6dda66b79a68..8a9527d7c005 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -220,7 +220,7 @@ static int pim_vrf_config_write(struct vty *vty) pim_global_config_write_worker(pim, vty); if (vrf->vrf_id != VRF_DEFAULT) - vty_endframe(vty, " exit-vrf\n!\n"); + vty_endframe(vty, "exit-vrf\n!\n"); } return 0; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 95882cf58f96..e4dec9ee8eef 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -451,7 +451,7 @@ int pim_interface_config_write(struct vty *vty) pim_bfd_write_config(vty, ifp); ++writes; } - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); ++writes; } } diff --git a/ripd/ripd.c b/ripd/ripd.c index 3d1427c3b6b3..97edd1c38ef4 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3281,6 +3281,8 @@ static int config_write_rip(struct vty *vty) /* Interface routemap configuration */ config_write_if_rmap(vty, rip->if_rmap_ctx); + vty_out(vty, "exit\n"); + write = 1; } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index cbd2c22893ad..1f52abd0bfe3 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2270,6 +2270,8 @@ static int ripng_config_write(struct vty *vty) config_write_distribute(vty, ripng->distribute_ctx); config_write_if_rmap(vty, ripng->if_rmap_ctx); + vty_out(vty, "exit\n"); + write = 1; } diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 96e5d37d68d9..0b3efd0b4329 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -164,7 +164,7 @@ static int static_vrf_config_write(struct vty *vty) SAFI_UNICAST, "ipv6 route"); if (vrf->vrf_id != VRF_DEFAULT) - vty_endframe(vty, " exit-vrf\n!\n"); + vty_endframe(vty, "exit-vrf\n!\n"); } return 0; diff --git a/tests/lib/cli/test_cli.refout.in b/tests/lib/cli/test_cli.refout.in index 8f9959cc47de..1f38e08b209e 100644 --- a/tests/lib/cli/test_cli.refout.in +++ b/tests/lib/cli/test_cli.refout.in @@ -315,7 +315,6 @@ domainname test.domain ! ! ! -line vty ! end test# conf t @@ -332,7 +331,6 @@ domainname test.domain ! ! ! -line vty ! end foohost(config)# diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index d22ec3113f01..2e1d7c5bad82 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -272,16 +272,11 @@ void vtysh_config_parse_line(void *arg, const char *line) strlen(" ip igmp query-interval")) == 0) { config_add_line_uniq_end(config->line, line); } else if (config->index == LINK_PARAMS_NODE - && strncmp(line, " exit-link-params", - strlen(" exit")) + && strncmp(line, " exit-link-params", + strlen(" exit")) == 0) { config_add_line(config->line, line); config->index = INTERFACE_NODE; - } else if (config->index == VRF_NODE - && strncmp(line, " exit-vrf", - strlen(" exit-vrf")) - == 0) { - config_add_line_uniq_end(config->line, line); } else if (!strncmp(line, " vrrp", strlen(" vrrp")) || !strncmp(line, " no vrrp", strlen(" no vrrp"))) { @@ -300,7 +295,10 @@ void vtysh_config_parse_line(void *arg, const char *line) config_add_line(config_top, line); break; default: - if (strncmp(line, "interface", strlen("interface")) == 0) + if (strncmp(line, "exit", strlen("exit")) == 0) { + if (config) + config_add_line_uniq_end(config->line, line); + } else if (strncmp(line, "interface", strlen("interface")) == 0) config = config_get(INTERFACE_NODE, line); else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0) config = config_get(PW_NODE, line); @@ -496,7 +494,9 @@ void vtysh_config_dump(void) * are not under the VRF node. */ if (config->index == INTERFACE_NODE - && list_isempty(config->line)) { + && (listcount(config->line) == 1) + && (line = listnode_head(config->line)) + && strmatch(line, "exit")) { config_del(config); continue; } diff --git a/zebra/interface.c b/zebra/interface.c index 21eeb2054312..18f7503f82fa 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -4096,7 +4096,7 @@ static int link_params_config_write(struct vty *vty, struct interface *ifp) if (IS_PARAM_SET(iflp, LP_RMT_AS)) vty_out(vty, " neighbor %pI4 as %u\n", &iflp->rmt_ip, iflp->rmt_as); - vty_out(vty, " exit-link-params\n"); + vty_out(vty, " exit-link-params\n"); return 0; } @@ -4188,7 +4188,7 @@ static int if_config_write(struct vty *vty) zebra_evpn_mh_if_write(vty, ifp); link_params_config_write(vty, ifp); - vty_endframe(vty, "!\n"); + vty_endframe(vty, "exit\n!\n"); } return 0; } diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 6b4a815151c3..d5083d4cbef1 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -836,6 +836,7 @@ static int zebra_pw_config(struct vty *vty) if (!(pw->flags & F_PSEUDOWIRE_CWORD)) vty_out(vty, " control-word exclude\n"); + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); write = 1; } diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c index 97935f126e83..d2b91b6c07e1 100644 --- a/zebra/zebra_srv6_vty.c +++ b/zebra/zebra_srv6_vty.c @@ -320,10 +320,14 @@ static int zebra_sr_config(struct vty *vty) vty_out(vty, " locator %s\n", locator->name); vty_out(vty, " prefix %s/%u\n", str, locator->prefix.prefixlen); + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); } + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); + vty_out(vty, " exit\n"); vty_out(vty, " !\n"); + vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } return 0; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 2430b519892b..c6737e83f8c5 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -521,7 +521,7 @@ static int vrf_config_write(struct vty *vty) router_id_write(vty, zvrf); if (zvrf_id(zvrf) != VRF_DEFAULT) - vty_endframe(vty, " exit-vrf\n!\n"); + vty_endframe(vty, "exit-vrf\n!\n"); else vty_out(vty, "!\n"); }