summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c72
-rw-r--r--lib/command.h1
-rw-r--r--lib/keychain.c2
-rw-r--r--lib/nexthop_group.c1
-rw-r--r--lib/routemap_cli.c1
-rw-r--r--lib/vrf.c1
-rw-r--r--lib/vty.c19
7 files changed, 30 insertions, 67 deletions
diff --git a/lib/command.c b/lib/command.c
index 7d46202da..dad35bfbf 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -203,6 +203,7 @@ static struct cmd_node enable_node = {
static int config_write_host(struct vty *vty);
static struct cmd_node config_node = {
.node = CONFIG_NODE,
+ .parent_node = ENABLE_NODE,
.prompt = "%s(config)# ",
.config_write = config_write_host,
};
@@ -1458,6 +1459,8 @@ DEFUN (config_exit,
void cmd_exit(struct vty *vty)
{
+ struct cmd_node *cnode = vector_lookup(cmdvec, vty->node);
+
switch (vty->node) {
case VIEW_NODE:
case ENABLE_NODE:
@@ -1470,73 +1473,9 @@ void cmd_exit(struct vty *vty)
vty->node = ENABLE_NODE;
vty_config_exit(vty);
break;
- case INTERFACE_NODE:
- case PW_NODE:
- case VRF_NODE:
- case NH_GROUP_NODE:
- case ZEBRA_NODE:
- case BGP_NODE:
- case RIP_NODE:
- case EIGRP_NODE:
- case BABEL_NODE:
- case RIPNG_NODE:
- case OSPF_NODE:
- case OSPF6_NODE:
- case LDP_NODE:
- case LDP_L2VPN_NODE:
- case ISIS_NODE:
- case OPENFABRIC_NODE:
- case KEYCHAIN_NODE:
- case RMAP_NODE:
- case PBRMAP_NODE:
- case VTY_NODE:
- case BFD_NODE:
- vty->node = CONFIG_NODE;
- break;
- case BGP_IPV4_NODE:
- case BGP_IPV4M_NODE:
- case BGP_IPV4L_NODE:
- case BGP_VPNV4_NODE:
- case BGP_VPNV6_NODE:
- case BGP_FLOWSPECV4_NODE:
- case BGP_FLOWSPECV6_NODE:
- case BGP_VRF_POLICY_NODE:
- case BGP_VNC_DEFAULTS_NODE:
- case BGP_VNC_NVE_GROUP_NODE:
- case BGP_VNC_L2_GROUP_NODE:
- case BGP_IPV6_NODE:
- case BGP_IPV6M_NODE:
- case BGP_EVPN_NODE:
- case BGP_IPV6L_NODE:
- case BMP_NODE:
- vty->node = BGP_NODE;
- break;
- case BGP_EVPN_VNI_NODE:
- vty->node = BGP_EVPN_NODE;
- break;
- case LDP_IPV4_NODE:
- case LDP_IPV6_NODE:
- vty->node = LDP_NODE;
- break;
- case LDP_IPV4_IFACE_NODE:
- vty->node = LDP_IPV4_NODE;
- break;
- case LDP_IPV6_IFACE_NODE:
- vty->node = LDP_IPV6_NODE;
- break;
- case LDP_PSEUDOWIRE_NODE:
- vty->node = LDP_L2VPN_NODE;
- break;
- case KEYCHAIN_KEY_NODE:
- vty->node = KEYCHAIN_NODE;
- break;
- case LINK_PARAMS_NODE:
- vty->node = INTERFACE_NODE;
- break;
- case BFD_PEER_NODE:
- vty->node = BFD_NODE;
- break;
default:
+ if (cnode->parent_node)
+ vty->node = cnode->parent_node;
break;
}
@@ -1564,7 +1503,6 @@ DEFUN (config_end,
vty_config_exit(vty);
vty->node = ENABLE_NODE;
}
-
return CMD_SUCCESS;
}
diff --git a/lib/command.h b/lib/command.h
index ed7706c30..c1de67e10 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -172,6 +172,7 @@ extern const char *const node_names[];
struct cmd_node {
/* Node index. */
enum node_type node;
+ enum node_type parent_node;
/* Prompt character at vty interface. */
const char *prompt;
diff --git a/lib/keychain.c b/lib/keychain.c
index bbe2070b1..bfeaa7fec 100644
--- a/lib/keychain.c
+++ b/lib/keychain.c
@@ -962,12 +962,14 @@ DEFUN (no_send_lifetime,
static int keychain_config_write(struct vty *vty);
static struct cmd_node keychain_node = {
.node = KEYCHAIN_NODE,
+ .parent_node = CONFIG_NODE,
.prompt = "%s(config-keychain)# ",
.config_write = keychain_config_write,
};
static struct cmd_node keychain_key_node = {
.node = KEYCHAIN_KEY_NODE,
+ .parent_node = KEYCHAIN_NODE,
.prompt = "%s(config-keychain-key)# ",
};
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index cce5af1e7..554460529 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -936,6 +936,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
static int nexthop_group_write(struct vty *vty);
static struct cmd_node nexthop_group_node = {
.node = NH_GROUP_NODE,
+ .parent_node = CONFIG_NODE,
.prompt = "%s(config-nh-group)# ",
.config_write = nexthop_group_write,
};
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index b97948d5c..16ecd1194 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -1067,6 +1067,7 @@ static int route_map_config_write(struct vty *vty)
static int route_map_config_write(struct vty *vty);
static struct cmd_node rmap_node = {
.node = RMAP_NODE,
+ .parent_node = CONFIG_NODE,
.prompt = "%s(config-route-map)# ",
.config_write = route_map_config_write,
};
diff --git a/lib/vrf.c b/lib/vrf.c
index b825ff03f..1fadf5c0c 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -760,6 +760,7 @@ DEFUN (no_vrf,
static struct cmd_node vrf_node = {
.node = VRF_NODE,
+ .parent_node = CONFIG_NODE,
.prompt = "%s(config-vrf)# ",
};
diff --git a/lib/vty.c b/lib/vty.c
index 1d94d3d31..24cdfeda4 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2605,6 +2605,24 @@ int vty_config_enter(struct vty *vty, bool private_config, bool exclusive)
void vty_config_exit(struct vty *vty)
{
+ enum node_type node = vty->node;
+ struct cmd_node *cnode;
+
+ /* unlock and jump up to ENABLE_NODE if -and only if- we're
+ * somewhere below CONFIG_NODE */
+ while (node && node != CONFIG_NODE) {
+ cnode = vector_lookup(cmdvec, node);
+ node = cnode->parent_node;
+ }
+ if (node != CONFIG_NODE) {
+ vty_out(vty,
+ "WARNING: vty_config_exit() from outside CONFIG_NODE!\n");
+ return;
+ }
+
+ while (vty->node != ENABLE_NODE)
+ cmd_exit(vty);
+
/* Check if there's a pending confirmed commit. */
if (vty->t_confirmed_commit_timeout) {
vty_out(vty,
@@ -2992,6 +3010,7 @@ static int vty_config_write(struct vty *vty)
static int vty_config_write(struct vty *vty);
struct cmd_node vty_node = {
.node = VTY_NODE,
+ .parent_node = CONFIG_NODE,
.prompt = "%s(config-line)# ",
.config_write = vty_config_write,
};