diff options
| author | Igor Ryzhov <iryzhov@nfware.com> | 2021-08-08 22:38:50 +0300 | 
|---|---|---|
| committer | Igor Ryzhov <iryzhov@nfware.com> | 2021-08-23 22:08:20 +0300 | 
| commit | 07679ad98ab97a4b783f7ae54f88d4d70a5729de (patch) | |
| tree | e2a670c3a68fb5b856cd52426c2f0b972a414bcb | |
| parent | ac9103aadc4a3da65b30952d69fdc535ae87604f (diff) | |
*: 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 <iryzhov@nfware.com>
39 files changed, 112 insertions, 30 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index c1e5ffde3c..615ed9fee3 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 b9623b64b5..b9037423b4 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 26ff4a758a..384bb26fd7 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 dbc35de80b..1bc3fd0dba 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 286612da15..ca3f93899b 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 27f147a4aa..dd4a776a21 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 cc64261388..2437bd8cfe 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 35536979ea..d61f43586f 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 a78e4996b4..6f4a91be67 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 ef86d47b22..70ec66fd7f 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 ecad16229c..f62a8d4813 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 0c2f7b6b7e..4680dd5ded 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 43efa0164d..ebcc9985b4 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 b35d3dfa00..fbd718bb09 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");  	} @@ -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 db5c23b1ba..02f83ef0a8 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 4fee9bde3c..97d70189ff 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 77455d991a..8747c37f16 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");  } @@ -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 60ce1e6523..a77121448e 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 bbb474ba1a..b427a0c9bd 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 fc181a6d18..b159f11396 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 4c248c0df3..1843947dba 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 68baa61fa9..bd629a2b70 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 9c622883bc..1ab8b7f39b 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 caeadd9ccc..6a918b8b82 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 e602fd22df..829df3179c 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 2936d1e346..6c007acb5c 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 6dda66b79a..8a9527d7c0 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 95882cf58f..e4dec9ee8e 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 3d1427c3b6..97edd1c38e 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 cbd2c22893..1f52abd0bf 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 96e5d37d68..0b3efd0b43 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 8f9959cc47..1f38e08b20 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 d22ec3113f..2e1d7c5bad 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 21eeb20543..18f7503f82 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 6b4a815151..d5083d4cbe 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 97935f126e..d2b91b6c07 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 2430b51989..c6737e83f8 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");  	}  | 
