mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +00:00
vtysh: fix duplicated output of key chain configuration
When both ripd and eigrpd run at the same time, all key configuration in key chain node is duplicated. This change adds a concept of nested nodes into vtysh to fix the issue. Before: ``` key chain test key 1 key-string 1 exit key 1 key-string 1 exit exit ! ``` After: ``` key chain test key 1 key-string 1 exit exit ! ``` Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
parent
31ccdb903f
commit
4b639f9967
@ -44,8 +44,12 @@ struct config {
|
|||||||
/* Configuration string line. */
|
/* Configuration string line. */
|
||||||
struct list *line;
|
struct list *line;
|
||||||
|
|
||||||
/* Configuration can be nest. */
|
/* Configuration can be nested. */
|
||||||
struct config *config;
|
struct config *parent;
|
||||||
|
vector nested;
|
||||||
|
|
||||||
|
/* Exit command. */
|
||||||
|
char *exit;
|
||||||
|
|
||||||
/* Index of this config. */
|
/* Index of this config. */
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
@ -76,7 +80,10 @@ static struct config *config_new(void)
|
|||||||
|
|
||||||
static void config_del(struct config *config)
|
static void config_del(struct config *config)
|
||||||
{
|
{
|
||||||
|
vector_free(config->nested);
|
||||||
list_delete(&config->line);
|
list_delete(&config->line);
|
||||||
|
if (config->exit)
|
||||||
|
XFREE(MTYPE_VTYSH_CONFIG_LINE, config->exit);
|
||||||
XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name);
|
XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name);
|
||||||
XFREE(MTYPE_VTYSH_CONFIG, config);
|
XFREE(MTYPE_VTYSH_CONFIG, config);
|
||||||
}
|
}
|
||||||
@ -104,7 +111,7 @@ struct configuration {
|
|||||||
struct config_master_hash_head hash_master;
|
struct config_master_hash_head hash_master;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct config *config_get(int index, const char *line)
|
static struct config *config_get_vec(vector vec, int index, const char *line)
|
||||||
{
|
{
|
||||||
struct config *config, *config_loop;
|
struct config *config, *config_loop;
|
||||||
struct configuration *configuration;
|
struct configuration *configuration;
|
||||||
@ -112,14 +119,14 @@ static struct config *config_get(int index, const char *line)
|
|||||||
|
|
||||||
config = config_loop = NULL;
|
config = config_loop = NULL;
|
||||||
|
|
||||||
configuration = vector_lookup_ensure(configvec, index);
|
configuration = vector_lookup_ensure(vec, index);
|
||||||
|
|
||||||
if (!configuration) {
|
if (!configuration) {
|
||||||
configuration = XMALLOC(MTYPE_VTYSH_CONFIG,
|
configuration = XMALLOC(MTYPE_VTYSH_CONFIG,
|
||||||
sizeof(struct configuration));
|
sizeof(struct configuration));
|
||||||
config_master_init(&configuration->master);
|
config_master_init(&configuration->master);
|
||||||
config_master_hash_init(&configuration->hash_master);
|
config_master_hash_init(&configuration->hash_master);
|
||||||
vector_set_index(configvec, index, configuration);
|
vector_set_index(vec, index, configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup.name = (char *)line;
|
lookup.name = (char *)line;
|
||||||
@ -131,13 +138,31 @@ static struct config *config_get(int index, const char *line)
|
|||||||
config->line->del = (void (*)(void *))line_del;
|
config->line->del = (void (*)(void *))line_del;
|
||||||
config->line->cmp = (int (*)(void *, void *))line_cmp;
|
config->line->cmp = (int (*)(void *, void *))line_cmp;
|
||||||
config->name = XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line);
|
config->name = XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line);
|
||||||
|
config->exit = NULL;
|
||||||
config->index = index;
|
config->index = index;
|
||||||
|
config->nested = vector_init(1);
|
||||||
config_master_add_tail(&configuration->master, config);
|
config_master_add_tail(&configuration->master, config);
|
||||||
config_master_hash_add(&configuration->hash_master, config);
|
config_master_hash_add(&configuration->hash_master, config);
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct config *config_get(int index, const char *line)
|
||||||
|
{
|
||||||
|
return config_get_vec(configvec, index, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct config *config_get_nested(struct config *parent, int index,
|
||||||
|
const char *line)
|
||||||
|
{
|
||||||
|
struct config *config;
|
||||||
|
|
||||||
|
config = config_get_vec(parent->nested, index, line);
|
||||||
|
config->parent = parent;
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
void config_add_line(struct list *config, const char *line)
|
void config_add_line(struct list *config, const char *line)
|
||||||
{
|
{
|
||||||
listnode_add(config, XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line));
|
listnode_add(config, XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line));
|
||||||
@ -259,9 +284,23 @@ void vtysh_config_parse_line(void *arg, const char *line)
|
|||||||
case ' ':
|
case ' ':
|
||||||
/* Store line to current configuration. */
|
/* Store line to current configuration. */
|
||||||
if (config) {
|
if (config) {
|
||||||
if (strncmp(line, " link-params",
|
if (config->index == KEYCHAIN_NODE
|
||||||
strlen(" link-params"))
|
&& strncmp(line, " key", strlen(" key")) == 0) {
|
||||||
== 0) {
|
config = config_get_nested(
|
||||||
|
config, KEYCHAIN_KEY_NODE, line);
|
||||||
|
} else if (config->index == KEYCHAIN_KEY_NODE) {
|
||||||
|
if (strncmp(line, " exit", strlen(" exit"))
|
||||||
|
== 0) {
|
||||||
|
config_add_line_uniq_end(config->line,
|
||||||
|
line);
|
||||||
|
config = config->parent;
|
||||||
|
} else {
|
||||||
|
config_add_line_uniq(config->line,
|
||||||
|
line);
|
||||||
|
}
|
||||||
|
} else if (strncmp(line, " link-params",
|
||||||
|
strlen(" link-params"))
|
||||||
|
== 0) {
|
||||||
config_add_line(config->line, line);
|
config_add_line(config->line, line);
|
||||||
config->index = LINK_PARAMS_NODE;
|
config->index = LINK_PARAMS_NODE;
|
||||||
} else if (strncmp(line, " ip multicast boundary",
|
} else if (strncmp(line, " ip multicast boundary",
|
||||||
@ -269,7 +308,8 @@ void vtysh_config_parse_line(void *arg, const char *line)
|
|||||||
== 0) {
|
== 0) {
|
||||||
config_add_line_uniq_end(config->line, line);
|
config_add_line_uniq_end(config->line, line);
|
||||||
} else if (strncmp(line, " ip igmp query-interval",
|
} else if (strncmp(line, " ip igmp query-interval",
|
||||||
strlen(" ip igmp query-interval")) == 0) {
|
strlen(" ip igmp query-interval"))
|
||||||
|
== 0) {
|
||||||
config_add_line_uniq_end(config->line, line);
|
config_add_line_uniq_end(config->line, line);
|
||||||
} else if (config->index == LINK_PARAMS_NODE
|
} else if (config->index == LINK_PARAMS_NODE
|
||||||
&& strncmp(line, " exit-link-params",
|
&& strncmp(line, " exit-link-params",
|
||||||
@ -281,7 +321,8 @@ void vtysh_config_parse_line(void *arg, const char *line)
|
|||||||
|| !strncmp(line, " no vrrp",
|
|| !strncmp(line, " no vrrp",
|
||||||
strlen(" no vrrp"))) {
|
strlen(" no vrrp"))) {
|
||||||
config_add_line(config->line, line);
|
config_add_line(config->line, line);
|
||||||
} else if (!strncmp(line, " ip mroute", strlen(" ip mroute"))) {
|
} else if (!strncmp(line, " ip mroute",
|
||||||
|
strlen(" ip mroute"))) {
|
||||||
config_add_line_uniq_end(config->line, line);
|
config_add_line_uniq_end(config->line, line);
|
||||||
} else if (config->index == RMAP_NODE
|
} else if (config->index == RMAP_NODE
|
||||||
|| config->index == INTERFACE_NODE
|
|| config->index == INTERFACE_NODE
|
||||||
@ -296,7 +337,8 @@ void vtysh_config_parse_line(void *arg, const char *line)
|
|||||||
default:
|
default:
|
||||||
if (strncmp(line, "exit", strlen("exit")) == 0) {
|
if (strncmp(line, "exit", strlen("exit")) == 0) {
|
||||||
if (config)
|
if (config)
|
||||||
config_add_line_uniq_end(config->line, line);
|
config->exit =
|
||||||
|
XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line);
|
||||||
} else if (strncmp(line, "interface", strlen("interface")) == 0)
|
} else if (strncmp(line, "interface", strlen("interface")) == 0)
|
||||||
config = config_get(INTERFACE_NODE, line);
|
config = config_get(INTERFACE_NODE, line);
|
||||||
else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0)
|
else if (strncmp(line, "pseudowire", strlen("pseudowire")) == 0)
|
||||||
@ -463,25 +505,18 @@ void vtysh_config_parse_line(void *arg, const char *line)
|
|||||||
|| (I) == FORWARDING_NODE || (I) == DEBUG_NODE || (I) == AAA_NODE \
|
|| (I) == FORWARDING_NODE || (I) == DEBUG_NODE || (I) == AAA_NODE \
|
||||||
|| (I) == VRF_DEBUG_NODE || (I) == NORTHBOUND_DEBUG_NODE \
|
|| (I) == VRF_DEBUG_NODE || (I) == NORTHBOUND_DEBUG_NODE \
|
||||||
|| (I) == RMAP_DEBUG_NODE || (I) == RESOLVER_DEBUG_NODE \
|
|| (I) == RMAP_DEBUG_NODE || (I) == RESOLVER_DEBUG_NODE \
|
||||||
|| (I) == MPLS_NODE)
|
|| (I) == MPLS_NODE || (I) == KEYCHAIN_KEY_NODE)
|
||||||
|
|
||||||
/* Display configuration to file pointer. */
|
static void configvec_dump(vector vec, bool nested)
|
||||||
void vtysh_config_dump(void)
|
|
||||||
{
|
{
|
||||||
struct listnode *node, *nnode;
|
|
||||||
struct listnode *mnode, *mnnode;
|
struct listnode *mnode, *mnnode;
|
||||||
struct config *config;
|
struct config *config;
|
||||||
struct configuration *configuration;
|
struct configuration *configuration;
|
||||||
char *line;
|
char *line;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS(config_top, node, nnode, line))
|
for (i = 0; i < vector_active(vec); i++)
|
||||||
vty_out(vty, "%s\n", line);
|
if ((configuration = vector_slot(vec, i)) != NULL) {
|
||||||
|
|
||||||
vty_out(vty, "!\n");
|
|
||||||
|
|
||||||
for (i = 0; i < vector_active(configvec); i++)
|
|
||||||
if ((configuration = vector_slot(configvec, i)) != NULL) {
|
|
||||||
while ((config = config_master_pop(
|
while ((config = config_master_pop(
|
||||||
&configuration->master))) {
|
&configuration->master))) {
|
||||||
config_master_hash_del(
|
config_master_hash_del(
|
||||||
@ -507,23 +542,39 @@ void vtysh_config_dump(void)
|
|||||||
for (ALL_LIST_ELEMENTS(config->line, mnode,
|
for (ALL_LIST_ELEMENTS(config->line, mnode,
|
||||||
mnnode, line))
|
mnnode, line))
|
||||||
vty_out(vty, "%s\n", line);
|
vty_out(vty, "%s\n", line);
|
||||||
|
|
||||||
|
configvec_dump(config->nested, true);
|
||||||
|
|
||||||
|
if (config->exit)
|
||||||
|
vty_out(vty, "%s\n", config->exit);
|
||||||
|
|
||||||
if (!NO_DELIMITER(i))
|
if (!NO_DELIMITER(i))
|
||||||
vty_out(vty, "!\n");
|
vty_out(vty, "!\n");
|
||||||
|
|
||||||
config_del(config);
|
config_del(config);
|
||||||
}
|
}
|
||||||
if (NO_DELIMITER(i))
|
|
||||||
vty_out(vty, "!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < vector_active(configvec); i++)
|
|
||||||
if ((configuration = vector_slot(configvec, i)) != NULL) {
|
|
||||||
config_master_fini(&configuration->master);
|
config_master_fini(&configuration->master);
|
||||||
config_master_hash_fini(&configuration->hash_master);
|
config_master_hash_fini(&configuration->hash_master);
|
||||||
XFREE(MTYPE_VTYSH_CONFIG, configuration);
|
XFREE(MTYPE_VTYSH_CONFIG, configuration);
|
||||||
vector_slot(configvec, i) = NULL;
|
vector_slot(vec, i) = NULL;
|
||||||
|
if (!nested && NO_DELIMITER(i))
|
||||||
|
vty_out(vty, "!\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtysh_config_dump(void)
|
||||||
|
{
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS(config_top, node, nnode, line))
|
||||||
|
vty_out(vty, "%s\n", line);
|
||||||
|
|
||||||
list_delete_all_node(config_top);
|
list_delete_all_node(config_top);
|
||||||
|
|
||||||
|
vty_out(vty, "!\n");
|
||||||
|
|
||||||
|
configvec_dump(configvec, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read up configuration file from file_name. */
|
/* Read up configuration file from file_name. */
|
||||||
|
Loading…
Reference in New Issue
Block a user