diff options
Diffstat (limited to 'lib/command.c')
-rw-r--r-- | lib/command.c | 3781 |
1 files changed, 1835 insertions, 1946 deletions
diff --git a/lib/command.c b/lib/command.c index c2ee79035..cc5222452 100644 --- a/lib/command.c +++ b/lib/command.c @@ -43,12 +43,12 @@ #include "qobj.h" #include "defaults.h" -DEFINE_MTYPE( LIB, HOST, "Host config") -DEFINE_MTYPE( LIB, STRVEC, "String vector") +DEFINE_MTYPE(LIB, HOST, "Host config") +DEFINE_MTYPE(LIB, STRVEC, "String vector") DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") -DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text") -DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help") -DEFINE_MTYPE( LIB, CMD_ARG, "Command Argument") +DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text") +DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help") +DEFINE_MTYPE(LIB, CMD_ARG, "Command Argument") /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -58,138 +58,118 @@ vector cmdvec = NULL; struct host host; /* Standard command node structures. */ -static struct cmd_node auth_node = -{ - AUTH_NODE, - "Password: ", +static struct cmd_node auth_node = { + AUTH_NODE, "Password: ", }; -static struct cmd_node view_node = -{ - VIEW_NODE, - "%s> ", +static struct cmd_node view_node = { + VIEW_NODE, "%s> ", }; -static struct cmd_node auth_enable_node = -{ - AUTH_ENABLE_NODE, - "Password: ", +static struct cmd_node auth_enable_node = { + AUTH_ENABLE_NODE, "Password: ", }; -static struct cmd_node enable_node = -{ - ENABLE_NODE, - "%s# ", +static struct cmd_node enable_node = { + ENABLE_NODE, "%s# ", }; -static struct cmd_node config_node = -{ - CONFIG_NODE, - "%s(config)# ", - 1 -}; +static struct cmd_node config_node = {CONFIG_NODE, "%s(config)# ", 1}; /* Default motd string. */ static const char *default_motd = FRR_DEFAULT_MOTD; static const struct facility_map { - int facility; - const char *name; - size_t match; -} syslog_facilities[] = - { - { LOG_KERN, "kern", 1 }, - { LOG_USER, "user", 2 }, - { LOG_MAIL, "mail", 1 }, - { LOG_DAEMON, "daemon", 1 }, - { LOG_AUTH, "auth", 1 }, - { LOG_SYSLOG, "syslog", 1 }, - { LOG_LPR, "lpr", 2 }, - { LOG_NEWS, "news", 1 }, - { LOG_UUCP, "uucp", 2 }, - { LOG_CRON, "cron", 1 }, + int facility; + const char *name; + size_t match; +} syslog_facilities[] = { + {LOG_KERN, "kern", 1}, + {LOG_USER, "user", 2}, + {LOG_MAIL, "mail", 1}, + {LOG_DAEMON, "daemon", 1}, + {LOG_AUTH, "auth", 1}, + {LOG_SYSLOG, "syslog", 1}, + {LOG_LPR, "lpr", 2}, + {LOG_NEWS, "news", 1}, + {LOG_UUCP, "uucp", 2}, + {LOG_CRON, "cron", 1}, #ifdef LOG_FTP - { LOG_FTP, "ftp", 1 }, + {LOG_FTP, "ftp", 1}, #endif - { LOG_LOCAL0, "local0", 6 }, - { LOG_LOCAL1, "local1", 6 }, - { LOG_LOCAL2, "local2", 6 }, - { LOG_LOCAL3, "local3", 6 }, - { LOG_LOCAL4, "local4", 6 }, - { LOG_LOCAL5, "local5", 6 }, - { LOG_LOCAL6, "local6", 6 }, - { LOG_LOCAL7, "local7", 6 }, - { 0, NULL, 0 }, - }; + {LOG_LOCAL0, "local0", 6}, + {LOG_LOCAL1, "local1", 6}, + {LOG_LOCAL2, "local2", 6}, + {LOG_LOCAL3, "local3", 6}, + {LOG_LOCAL4, "local4", 6}, + {LOG_LOCAL5, "local5", 6}, + {LOG_LOCAL6, "local6", 6}, + {LOG_LOCAL7, "local7", 6}, + {0, NULL, 0}, +}; -static const char * -facility_name(int facility) +static const char *facility_name(int facility) { - const struct facility_map *fm; + const struct facility_map *fm; - for (fm = syslog_facilities; fm->name; fm++) - if (fm->facility == facility) - return fm->name; - return ""; + for (fm = syslog_facilities; fm->name; fm++) + if (fm->facility == facility) + return fm->name; + return ""; } -static int -facility_match(const char *str) +static int facility_match(const char *str) { - const struct facility_map *fm; + const struct facility_map *fm; - for (fm = syslog_facilities; fm->name; fm++) - if (!strncmp(str,fm->name,fm->match)) - return fm->facility; - return -1; + for (fm = syslog_facilities; fm->name; fm++) + if (!strncmp(str, fm->name, fm->match)) + return fm->facility; + return -1; } -static int -level_match(const char *s) +static int level_match(const char *s) { - int level ; + int level; - for ( level = 0 ; zlog_priority [level] != NULL ; level ++ ) - if (!strncmp (s, zlog_priority[level], 2)) - return level; - return ZLOG_DISABLED; + for (level = 0; zlog_priority[level] != NULL; level++) + if (!strncmp(s, zlog_priority[level], 2)) + return level; + return ZLOG_DISABLED; } /* This is called from main when a daemon is invoked with -v or --version. */ -void -print_version (const char *progname) +void print_version(const char *progname) { - printf ("%s version %s\n", progname, FRR_VERSION); - printf ("%s\n", FRR_COPYRIGHT); - printf ("configured with:\n\t%s\n", FRR_CONFIG_ARGS); + printf("%s version %s\n", progname, FRR_VERSION); + printf("%s\n", FRR_COPYRIGHT); + printf("configured with:\n\t%s\n", FRR_CONFIG_ARGS); } /* Utility function to concatenate argv argument into a single string with inserting ' ' character between each argument. */ -char * -argv_concat (struct cmd_token **argv, int argc, int shift) -{ - int i; - size_t len; - char *str; - char *p; - - len = 0; - for (i = shift; i < argc; i++) - len += strlen(argv[i]->arg)+1; - if (!len) - return NULL; - p = str = XMALLOC(MTYPE_TMP, len); - for (i = shift; i < argc; i++) - { - size_t arglen; - memcpy(p, argv[i]->arg, (arglen = strlen(argv[i]->arg))); - p += arglen; - *p++ = ' '; - } - *(p-1) = '\0'; - return str; +char *argv_concat(struct cmd_token **argv, int argc, int shift) +{ + int i; + size_t len; + char *str; + char *p; + + len = 0; + for (i = shift; i < argc; i++) + len += strlen(argv[i]->arg) + 1; + if (!len) + return NULL; + p = str = XMALLOC(MTYPE_TMP, len); + for (i = shift; i < argc; i++) { + size_t arglen; + memcpy(p, argv[i]->arg, (arglen = strlen(argv[i]->arg))); + p += arglen; + *p++ = ' '; + } + *(p - 1) = '\0'; + return str; } /** @@ -202,41 +182,38 @@ argv_concat (struct cmd_token **argv, int argc, int shift) * index of the found token if it exists * @return 1 if found, 0 otherwise */ -int -argv_find (struct cmd_token **argv, int argc, const char *text, int *index) +int argv_find(struct cmd_token **argv, int argc, const char *text, int *index) { - int found = 0; - for (int i = *index; i < argc && found == 0; i++) - if ((found = strmatch (text, argv[i]->text))) - *index = i; - return found; + int found = 0; + for (int i = *index; i < argc && found == 0; i++) + if ((found = strmatch(text, argv[i]->text))) + *index = i; + return found; } -static unsigned int -cmd_hash_key (void *p) +static unsigned int cmd_hash_key(void *p) { - return (uintptr_t) p; + return (uintptr_t)p; } -static int -cmd_hash_cmp (const void *a, const void *b) +static int cmd_hash_cmp(const void *a, const void *b) { - return a == b; + return a == b; } /* Install top node of command vector. */ -void -install_node (struct cmd_node *node, - int (*func) (struct vty *)) +void install_node(struct cmd_node *node, int (*func)(struct vty *)) { - vector_set_index (cmdvec, node->node, node); - node->func = func; - node->cmdgraph = graph_new (); - node->cmd_vector = vector_init (VECTOR_MIN_SIZE); - // add start node - struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (node->cmdgraph, token, (void (*)(void *)) &del_cmd_token); - node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp); + vector_set_index(cmdvec, node->node, node); + node->func = func; + node->cmdgraph = graph_new(); + node->cmd_vector = vector_init(VECTOR_MIN_SIZE); + // add start node + struct cmd_token *token = + new_cmd_token(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(node->cmdgraph, token, + (void (*)(void *)) & del_cmd_token); + node->cmd_hash = hash_create(cmd_hash_key, cmd_hash_cmp); } /** @@ -248,177 +225,166 @@ install_node (struct cmd_node *node, * @param string to tokenize * @return tokenized string */ -vector -cmd_make_strvec (const char *string) +vector cmd_make_strvec(const char *string) { - if (!string) return NULL; + if (!string) + return NULL; - char *copy, *copystart; - copystart = copy = XSTRDUP (MTYPE_TMP, string); + char *copy, *copystart; + copystart = copy = XSTRDUP(MTYPE_TMP, string); - // skip leading whitespace - while (isspace ((int) *copy) && *copy != '\0') copy++; + // skip leading whitespace + while (isspace((int)*copy) && *copy != '\0') + copy++; - // if the entire string was whitespace or a comment, return - if (*copy == '\0' || *copy == '!' || *copy == '#') - { - XFREE (MTYPE_TMP, copystart); - return NULL; - } + // if the entire string was whitespace or a comment, return + if (*copy == '\0' || *copy == '!' || *copy == '#') { + XFREE(MTYPE_TMP, copystart); + return NULL; + } - vector strvec = vector_init (VECTOR_MIN_SIZE); - const char *delim = " \n\r\t", *tok = NULL; - while (copy) - { - tok = strsep (©, delim); - if (*tok != '\0') - vector_set (strvec, XSTRDUP (MTYPE_STRVEC, tok)); - } + vector strvec = vector_init(VECTOR_MIN_SIZE); + const char *delim = " \n\r\t", *tok = NULL; + while (copy) { + tok = strsep(©, delim); + if (*tok != '\0') + vector_set(strvec, XSTRDUP(MTYPE_STRVEC, tok)); + } - XFREE (MTYPE_TMP, copystart); - return strvec; + XFREE(MTYPE_TMP, copystart); + return strvec; } /* Free allocated string vector. */ -void -cmd_free_strvec (vector v) +void cmd_free_strvec(vector v) { - unsigned int i; - char *cp; + unsigned int i; + char *cp; - if (!v) - return; + if (!v) + return; - for (i = 0; i < vector_active (v); i++) - if ((cp = vector_slot (v, i)) != NULL) - XFREE (MTYPE_STRVEC, cp); + for (i = 0; i < vector_active(v); i++) + if ((cp = vector_slot(v, i)) != NULL) + XFREE(MTYPE_STRVEC, cp); - vector_free (v); + vector_free(v); } /* Return prompt character of specified node. */ -const char * -cmd_prompt (enum node_type node) +const char *cmd_prompt(enum node_type node) { - struct cmd_node *cnode; + struct cmd_node *cnode; - cnode = vector_slot (cmdvec, node); - return cnode->prompt; + cnode = vector_slot(cmdvec, node); + return cnode->prompt; } -static bool -cmd_nodes_link (struct graph_node *from, struct graph_node *to) +static bool cmd_nodes_link(struct graph_node *from, struct graph_node *to) { - for (size_t i = 0; i < vector_active (from->to); i++) - if (vector_slot (from->to, i) == to) - return true; - return false; + for (size_t i = 0; i < vector_active(from->to); i++) + if (vector_slot(from->to, i) == to) + return true; + return false; } -static bool cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb); +static bool cmd_nodes_equal(struct graph_node *ga, struct graph_node *gb); /* returns a single node to be excluded as "next" from iteration * - for JOIN_TKN, never continue back to the FORK_TKN * - in all other cases, don't try the node itself (in case of "...") */ -static inline struct graph_node * -cmd_loopstop(struct graph_node *gn) -{ - struct cmd_token *tok = gn->data; - if (tok->type == JOIN_TKN) - return tok->forkjoin; - else - return gn; -} - -static bool -cmd_subgraph_equal (struct graph_node *ga, struct graph_node *gb, - struct graph_node *a_join) -{ - size_t i, j; - struct graph_node *a_fork, *b_fork; - a_fork = cmd_loopstop (ga); - b_fork = cmd_loopstop (gb); - - if (vector_active (ga->to) != vector_active (gb->to)) - return false; - for (i = 0; i < vector_active (ga->to); i++) - { - struct graph_node *cga = vector_slot (ga->to, i); - - for (j = 0; j < vector_active (gb->to); j++) - { - struct graph_node *cgb = vector_slot (gb->to, i); - - if (cga == a_fork && cgb != b_fork) - continue; - if (cga == a_fork && cgb == b_fork) - break; - - if (cmd_nodes_equal (cga, cgb)) - { - if (cga == a_join) - break; - if (cmd_subgraph_equal (cga, cgb, a_join)) - break; - } - } - if (j == vector_active (gb->to)) - return false; - } - return true; +static inline struct graph_node *cmd_loopstop(struct graph_node *gn) +{ + struct cmd_token *tok = gn->data; + if (tok->type == JOIN_TKN) + return tok->forkjoin; + else + return gn; +} + +static bool cmd_subgraph_equal(struct graph_node *ga, struct graph_node *gb, + struct graph_node *a_join) +{ + size_t i, j; + struct graph_node *a_fork, *b_fork; + a_fork = cmd_loopstop(ga); + b_fork = cmd_loopstop(gb); + + if (vector_active(ga->to) != vector_active(gb->to)) + return false; + for (i = 0; i < vector_active(ga->to); i++) { + struct graph_node *cga = vector_slot(ga->to, i); + + for (j = 0; j < vector_active(gb->to); j++) { + struct graph_node *cgb = vector_slot(gb->to, i); + + if (cga == a_fork && cgb != b_fork) + continue; + if (cga == a_fork && cgb == b_fork) + break; + + if (cmd_nodes_equal(cga, cgb)) { + if (cga == a_join) + break; + if (cmd_subgraph_equal(cga, cgb, a_join)) + break; + } + } + if (j == vector_active(gb->to)) + return false; + } + return true; } /* deep compare -- for FORK_TKN, the entire subgraph is compared. * this is what's needed since we're not currently trying to partially * merge subgraphs */ -static bool -cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb) -{ - struct cmd_token *a = ga->data, *b = gb->data; - - if (a->type != b->type || a->allowrepeat != b->allowrepeat) - return false; - if (a->type < SPECIAL_TKN && strcmp (a->text, b->text)) - return false; - /* one a ..., the other not. */ - if (cmd_nodes_link (ga, ga) != cmd_nodes_link (gb, gb)) - return false; - - switch (a->type) - { - case RANGE_TKN: - return a->min == b->min && a->max == b->max; - - case FORK_TKN: - /* one is keywords, the other just option or selector ... */ - if (cmd_nodes_link (a->forkjoin, ga) != cmd_nodes_link (b->forkjoin, gb)) - return false; - if (cmd_nodes_link (ga, a->forkjoin) != cmd_nodes_link (gb, b->forkjoin)) - return false; - return cmd_subgraph_equal (ga, gb, a->forkjoin); - - default: - return true; - } -} - -static void -cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join, - u_char attr) -{ - size_t i; - struct cmd_token *tok = gn->data; - struct graph_node *stop = cmd_loopstop (gn); - - tok->attr = attr; - for (i = 0; i < vector_active (gn->to); i++) - { - struct graph_node *next = vector_slot (gn->to, i); - if (next == stop || next == join) - continue; - cmd_fork_bump_attr (next, join, attr); - } +static bool cmd_nodes_equal(struct graph_node *ga, struct graph_node *gb) +{ + struct cmd_token *a = ga->data, *b = gb->data; + + if (a->type != b->type || a->allowrepeat != b->allowrepeat) + return false; + if (a->type < SPECIAL_TKN && strcmp(a->text, b->text)) + return false; + /* one a ..., the other not. */ + if (cmd_nodes_link(ga, ga) != cmd_nodes_link(gb, gb)) + return false; + + switch (a->type) { + case RANGE_TKN: + return a->min == b->min && a->max == b->max; + + case FORK_TKN: + /* one is keywords, the other just option or selector ... */ + if (cmd_nodes_link(a->forkjoin, ga) + != cmd_nodes_link(b->forkjoin, gb)) + return false; + if (cmd_nodes_link(ga, a->forkjoin) + != cmd_nodes_link(gb, b->forkjoin)) + return false; + return cmd_subgraph_equal(ga, gb, a->forkjoin); + + default: + return true; + } +} + +static void cmd_fork_bump_attr(struct graph_node *gn, struct graph_node *join, + u_char attr) +{ + size_t i; + struct cmd_token *tok = gn->data; + struct graph_node *stop = cmd_loopstop(gn); + + tok->attr = attr; + for (i = 0; i < vector_active(gn->to); i++) { + struct graph_node *next = vector_slot(gn->to, i); + if (next == stop || next == join) + continue; + cmd_fork_bump_attr(next, join, attr); + } } /* move an entire subtree from the temporary graph resulting from @@ -426,395 +392,386 @@ cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join, * * this touches rather deeply into the graph code unfortunately. */ -static void -cmd_reparent_tree (struct graph *fromgraph, struct graph *tograph, - struct graph_node *node) -{ - struct graph_node *stop = cmd_loopstop (node); - size_t i; - - for (i = 0; i < vector_active (fromgraph->nodes); i++) - if (vector_slot (fromgraph->nodes, i) == node) - { - /* agressive iteration punching through subgraphs - may hit some - * nodes twice. reparent only if found on old graph */ - vector_unset (fromgraph->nodes, i); - vector_set (tograph->nodes, node); - break; - } - - for (i = 0; i < vector_active (node->to); i++) - { - struct graph_node *next = vector_slot (node->to, i); - if (next != stop) - cmd_reparent_tree (fromgraph, tograph, next); - } -} - -static void -cmd_free_recur (struct graph *graph, struct graph_node *node, - struct graph_node *stop) -{ - struct graph_node *next, *nstop; - - for (size_t i = vector_active (node->to); i; i--) - { - next = vector_slot (node->to, i - 1); - if (next == stop) - continue; - nstop = cmd_loopstop (next); - if (nstop != next) - cmd_free_recur (graph, next, nstop); - cmd_free_recur (graph, nstop, stop); - } - graph_delete_node (graph, node); -} - -static void -cmd_free_node (struct graph *graph, struct graph_node *node) -{ - struct cmd_token *tok = node->data; - if (tok->type == JOIN_TKN) - cmd_free_recur (graph, tok->forkjoin, node); - graph_delete_node (graph, node); +static void cmd_reparent_tree(struct graph *fromgraph, struct graph *tograph, + struct graph_node *node) +{ + struct graph_node *stop = cmd_loopstop(node); + size_t i; + + for (i = 0; i < vector_active(fromgraph->nodes); i++) + if (vector_slot(fromgraph->nodes, i) == node) { + /* agressive iteration punching through subgraphs - may + * hit some + * nodes twice. reparent only if found on old graph */ + vector_unset(fromgraph->nodes, i); + vector_set(tograph->nodes, node); + break; + } + + for (i = 0; i < vector_active(node->to); i++) { + struct graph_node *next = vector_slot(node->to, i); + if (next != stop) + cmd_reparent_tree(fromgraph, tograph, next); + } +} + +static void cmd_free_recur(struct graph *graph, struct graph_node *node, + struct graph_node *stop) +{ + struct graph_node *next, *nstop; + + for (size_t i = vector_active(node->to); i; i--) { + next = vector_slot(node->to, i - 1); + if (next == stop) + continue; + nstop = cmd_loopstop(next); + if (nstop != next) + cmd_free_recur(graph, next, nstop); + cmd_free_recur(graph, nstop, stop); + } + graph_delete_node(graph, node); +} + +static void cmd_free_node(struct graph *graph, struct graph_node *node) +{ + struct cmd_token *tok = node->data; + if (tok->type == JOIN_TKN) + cmd_free_recur(graph, tok->forkjoin, node); + graph_delete_node(graph, node); } /* recursive graph merge. call with * old ~= new * (which holds true for old == START_TKN, new == START_TKN) */ -static void -cmd_merge_nodes (struct graph *oldgraph, struct graph *newgraph, - struct graph_node *old, struct graph_node *new, - int direction) -{ - struct cmd_token *tok; - struct graph_node *old_skip, *new_skip; - old_skip = cmd_loopstop (old); - new_skip = cmd_loopstop (new); - - assert (direction == 1 || direction == -1); - - tok = old->data; - tok->refcnt += direction; - - size_t j, i; - for (j = 0; j < vector_active (new->to); j++) - { - struct graph_node *cnew = vector_slot (new->to, j); - if (cnew == new_skip) - continue; - - for (i = 0; i < vector_active (old->to); i++) - { - struct graph_node *cold = vector_slot (old->to, i); - if (cold == old_skip) - continue; - - if (cmd_nodes_equal (cold, cnew)) - { - struct cmd_token *told = cold->data, *tnew = cnew->data; - - if (told->type == END_TKN) - { - if (direction < 0) - { - graph_delete_node (oldgraph, vector_slot (cold->to, 0)); - graph_delete_node (oldgraph, cold); - } - else - /* force no-match handling to install END_TKN */ - i = vector_active (old->to); - break; - } - - /* the entire fork compared as equal, we continue after it. */ - if (told->type == FORK_TKN) - { - if (tnew->attr < told->attr && direction > 0) - cmd_fork_bump_attr (cold, told->forkjoin, tnew->attr); - /* XXX: no reverse bump on uninstall */ - told = (cold = told->forkjoin)->data; - tnew = (cnew = tnew->forkjoin)->data; - } - if (tnew->attr < told->attr) - told->attr = tnew->attr; - - cmd_merge_nodes (oldgraph, newgraph, cold, cnew, direction); - break; - } - } - /* nothing found => add new to old */ - if (i == vector_active (old->to) && direction > 0) - { - assert (vector_count (cnew->from) == - cmd_nodes_link (cnew, cnew) ? 2 : 1); - graph_remove_edge (new, cnew); - - cmd_reparent_tree (newgraph, oldgraph, cnew); - - graph_add_edge (old, cnew); - } - } - - if (!tok->refcnt) - cmd_free_node (oldgraph, old); -} - -void -cmd_merge_graphs (struct graph *old, struct graph *new, int direction) -{ - assert (vector_active (old->nodes) >= 1); - assert (vector_active (new->nodes) >= 1); - - cmd_merge_nodes (old, new, - vector_slot (old->nodes, 0), vector_slot (new->nodes, 0), - direction); +static void cmd_merge_nodes(struct graph *oldgraph, struct graph *newgraph, + struct graph_node *old, struct graph_node *new, + int direction) +{ + struct cmd_token *tok; + struct graph_node *old_skip, *new_skip; + old_skip = cmd_loopstop(old); + new_skip = cmd_loopstop(new); + + assert(direction == 1 || direction == -1); + + tok = old->data; + tok->refcnt += direction; + + size_t j, i; + for (j = 0; j < vector_active(new->to); j++) { + struct graph_node *cnew = vector_slot(new->to, j); + if (cnew == new_skip) + continue; + + for (i = 0; i < vector_active(old->to); i++) { + struct graph_node *cold = vector_slot(old->to, i); + if (cold == old_skip) + continue; + + if (cmd_nodes_equal(cold, cnew)) { + struct cmd_token *told = cold->data, + *tnew = cnew->data; + + if (told->type == END_TKN) { + if (direction < 0) { + graph_delete_node( + oldgraph, + vector_slot(cold->to, + 0)); + graph_delete_node(oldgraph, + cold); + } else + /* force no-match handling to + * install END_TKN */ + i = vector_active(old->to); + break; + } + + /* the entire fork compared as equal, we + * continue after it. */ + if (told->type == FORK_TKN) { + if (tnew->attr < told->attr + && direction > 0) + cmd_fork_bump_attr( + cold, told->forkjoin, + tnew->attr); + /* XXX: no reverse bump on uninstall */ + told = (cold = told->forkjoin)->data; + tnew = (cnew = tnew->forkjoin)->data; + } + if (tnew->attr < told->attr) + told->attr = tnew->attr; + + cmd_merge_nodes(oldgraph, newgraph, cold, cnew, + direction); + break; + } + } + /* nothing found => add new to old */ + if (i == vector_active(old->to) && direction > 0) { + assert(vector_count(cnew->from) + == cmd_nodes_link(cnew, cnew) + ? 2 + : 1); + graph_remove_edge(new, cnew); + + cmd_reparent_tree(newgraph, oldgraph, cnew); + + graph_add_edge(old, cnew); + } + } + + if (!tok->refcnt) + cmd_free_node(oldgraph, old); +} + +void cmd_merge_graphs(struct graph *old, struct graph *new, int direction) +{ + assert(vector_active(old->nodes) >= 1); + assert(vector_active(new->nodes) >= 1); + + cmd_merge_nodes(old, new, vector_slot(old->nodes, 0), + vector_slot(new->nodes, 0), direction); } /* Install a command into a node. */ -void -install_element (enum node_type ntype, struct cmd_element *cmd) +void install_element(enum node_type ntype, struct cmd_element *cmd) { - struct cmd_node *cnode; + struct cmd_node *cnode; - /* cmd_init hasn't been called */ - if (!cmdvec) - { - fprintf (stderr, "%s called before cmd_init, breakage likely\n", - __func__); - return; - } + /* cmd_init hasn't been called */ + if (!cmdvec) { + fprintf(stderr, "%s called before cmd_init, breakage likely\n", + __func__); + return; + } - cnode = vector_slot (cmdvec, ntype); + cnode = vector_slot(cmdvec, ntype); - if (cnode == NULL) - { - fprintf (stderr, "Command node %d doesn't exist, please check it\n", - ntype); - exit (EXIT_FAILURE); - } + if (cnode == NULL) { + fprintf(stderr, + "Command node %d doesn't exist, please check it\n", + ntype); + exit(EXIT_FAILURE); + } - if (hash_lookup (cnode->cmd_hash, cmd) != NULL) - { - fprintf (stderr, - "Multiple command installs to node %d of command:\n%s\n", - ntype, cmd->string); - return; - } + if (hash_lookup(cnode->cmd_hash, cmd) != NULL) { + fprintf(stderr, + "Multiple command installs to node %d of command:\n%s\n", + ntype, cmd->string); + return; + } - assert (hash_get (cnode->cmd_hash, cmd, hash_alloc_intern)); + assert(hash_get(cnode->cmd_hash, cmd, hash_alloc_intern)); - struct graph *graph = graph_new(); - struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token); + struct graph *graph = graph_new(); + struct cmd_token *token = + new_cmd_token(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & del_cmd_token); - command_parse_format (graph, cmd); - cmd_merge_graphs (cnode->cmdgraph, graph, +1); - graph_delete_graph (graph); + command_parse_format(graph, cmd); + cmd_merge_graphs(cnode->cmdgraph, graph, +1); + graph_delete_graph(graph); - vector_set (cnode->cmd_vector, cmd); + vector_set(cnode->cmd_vector, cmd); - if (ntype == VIEW_NODE) - install_element (ENABLE_NODE, cmd); + if (ntype == VIEW_NODE) + install_element(ENABLE_NODE, cmd); } -void -uninstall_element (enum node_type ntype, struct cmd_element *cmd) +void uninstall_element(enum node_type ntype, struct cmd_element *cmd) { - struct cmd_node *cnode; + struct cmd_node *cnode; - /* cmd_init hasn't been called */ - if (!cmdvec) - { - fprintf (stderr, "%s called before cmd_init, breakage likely\n", - __func__); - return; - } + /* cmd_init hasn't been called */ + if (!cmdvec) { + fprintf(stderr, "%s called before cmd_init, breakage likely\n", + __func__); + return; + } - cnode = vector_slot (cmdvec, ntype); + cnode = vector_slot(cmdvec, ntype); - if (cnode == NULL) - { - fprintf (stderr, "Command node %d doesn't exist, please check it\n", - ntype); - exit (EXIT_FAILURE); - } + if (cnode == NULL) { + fprintf(stderr, + "Command node %d doesn't exist, please check it\n", + ntype); + exit(EXIT_FAILURE); + } - if (hash_release (cnode->cmd_hash, cmd) == NULL) - { - fprintf (stderr, - "Trying to uninstall non-installed command (node %d):\n%s\n", - ntype, cmd->string); - return; - } + if (hash_release(cnode->cmd_hash, cmd) == NULL) { + fprintf(stderr, + "Trying to uninstall non-installed command (node %d):\n%s\n", + ntype, cmd->string); + return; + } - vector_unset_value (cnode->cmd_vector, cmd); + vector_unset_value(cnode->cmd_vector, cmd); - struct graph *graph = graph_new(); - struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token); + struct graph *graph = graph_new(); + struct cmd_token *token = + new_cmd_token(START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node(graph, token, (void (*)(void *)) & del_cmd_token); - command_parse_format (graph, cmd); - cmd_merge_graphs (cnode->cmdgraph, graph, -1); - graph_delete_graph (graph); + command_parse_format(graph, cmd); + cmd_merge_graphs(cnode->cmdgraph, graph, -1); + graph_delete_graph(graph); - if (ntype == VIEW_NODE) - uninstall_element (ENABLE_NODE, cmd); + if (ntype == VIEW_NODE) + uninstall_element(ENABLE_NODE, cmd); } static const unsigned char itoa64[] = -"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -static void -to64(char *s, long v, int n) +static void to64(char *s, long v, int n) { - while (--n >= 0) - { - *s++ = itoa64[v&0x3f]; - v >>= 6; - } + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } } -static char * -zencrypt (const char *passwd) +static char *zencrypt(const char *passwd) { - char salt[6]; - struct timeval tv; - char *crypt (const char *, const char *); + char salt[6]; + struct timeval tv; + char *crypt(const char *, const char *); - gettimeofday(&tv,0); + gettimeofday(&tv, 0); - to64(&salt[0], random(), 3); - to64(&salt[3], tv.tv_usec, 3); - salt[5] = '\0'; + to64(&salt[0], random(), 3); + to64(&salt[3], tv.tv_usec, 3); + salt[5] = '\0'; - return crypt (passwd, salt); + return crypt(passwd, salt); } /* This function write configuration of this host. */ -static int -config_write_host (struct vty *vty) -{ - if (host.name) - vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE); - - if (host.encrypt) - { - if (host.password_encrypt) - vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE); - if (host.enable_encrypt) - vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE); - } - else - { - if (host.password) - vty_out (vty, "password %s%s", host.password, VTY_NEWLINE); - if (host.enable) - vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE); - } - - if (zlog_default->default_lvl != LOG_DEBUG) - { - vty_out (vty, "! N.B. The 'log trap' command is deprecated.%s", - VTY_NEWLINE); - vty_out (vty, "log trap %s%s", - zlog_priority[zlog_default->default_lvl], VTY_NEWLINE); - } - - if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) - { - vty_out (vty, "log file %s", host.logfile); - if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl) - vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]); - vty_out (vty, "%s", VTY_NEWLINE); - } - - if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) - { - vty_out (vty, "log stdout"); - if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl) - vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]); - vty_out (vty, "%s", VTY_NEWLINE); - } - - if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) - vty_out(vty,"no log monitor%s",VTY_NEWLINE); - else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl) - vty_out(vty,"log monitor %s%s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE); - - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) - { - vty_out (vty, "log syslog"); - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl) - vty_out (vty, " %s", - zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]); - vty_out (vty, "%s", VTY_NEWLINE); - } - - if (zlog_default->facility != LOG_DAEMON) - vty_out (vty, "log facility %s%s", - facility_name(zlog_default->facility), VTY_NEWLINE); - - if (zlog_default->record_priority == 1) - vty_out (vty, "log record-priority%s", VTY_NEWLINE); - - if (zlog_default->timestamp_precision > 0) - vty_out (vty, "log timestamp precision %d%s", - zlog_default->timestamp_precision, VTY_NEWLINE); - - if (host.advanced) - vty_out (vty, "service advanced-vty%s", VTY_NEWLINE); - - if (host.encrypt) - vty_out (vty, "service password-encryption%s", VTY_NEWLINE); - - if (host.lines >= 0) - vty_out (vty, "service terminal-length %d%s", host.lines, - VTY_NEWLINE); - - if (host.motdfile) - vty_out (vty, "banner motd file %s%s", host.motdfile, VTY_NEWLINE); - else if (! host.motd) - vty_out (vty, "no banner motd%s", VTY_NEWLINE); - - return 1; +static int config_write_host(struct vty *vty) +{ + if (host.name) + vty_out(vty, "hostname %s%s", host.name, VTY_NEWLINE); + + if (host.encrypt) { + if (host.password_encrypt) + vty_out(vty, "password 8 %s%s", host.password_encrypt, + VTY_NEWLINE); + if (host.enable_encrypt) + vty_out(vty, "enable password 8 %s%s", + host.enable_encrypt, VTY_NEWLINE); + } else { + if (host.password) + vty_out(vty, "password %s%s", host.password, + VTY_NEWLINE); + if (host.enable) + vty_out(vty, "enable password %s%s", host.enable, + VTY_NEWLINE); + } + + if (zlog_default->default_lvl != LOG_DEBUG) { + vty_out(vty, "! N.B. The 'log trap' command is deprecated.%s", + VTY_NEWLINE); + vty_out(vty, "log trap %s%s", + zlog_priority[zlog_default->default_lvl], VTY_NEWLINE); + } + + if (host.logfile + && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) { + vty_out(vty, "log file %s", host.logfile); + if (zlog_default->maxlvl[ZLOG_DEST_FILE] + != zlog_default->default_lvl) + vty_out(vty, " %s", + zlog_priority + [zlog_default->maxlvl[ZLOG_DEST_FILE]]); + vty_out(vty, "%s", VTY_NEWLINE); + } + + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) { + vty_out(vty, "log stdout"); + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] + != zlog_default->default_lvl) + vty_out(vty, " %s", + zlog_priority[zlog_default->maxlvl + [ZLOG_DEST_STDOUT]]); + vty_out(vty, "%s", VTY_NEWLINE); + } + + if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out(vty, "no log monitor%s", VTY_NEWLINE); + else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] + != zlog_default->default_lvl) + vty_out(vty, "log monitor %s%s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]], + VTY_NEWLINE); + + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) { + vty_out(vty, "log syslog"); + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] + != zlog_default->default_lvl) + vty_out(vty, " %s", + zlog_priority[zlog_default->maxlvl + [ZLOG_DEST_SYSLOG]]); + vty_out(vty, "%s", VTY_NEWLINE); + } + + if (zlog_default->facility != LOG_DAEMON) + vty_out(vty, "log facility %s%s", + facility_name(zlog_default->facility), VTY_NEWLINE); + + if (zlog_default->record_priority == 1) + vty_out(vty, "log record-priority%s", VTY_NEWLINE); + + if (zlog_default->timestamp_precision > 0) + vty_out(vty, "log timestamp precision %d%s", + zlog_default->timestamp_precision, VTY_NEWLINE); + + if (host.advanced) + vty_out(vty, "service advanced-vty%s", VTY_NEWLINE); + + if (host.encrypt) + vty_out(vty, "service password-encryption%s", VTY_NEWLINE); + + if (host.lines >= 0) + vty_out(vty, "service terminal-length %d%s", host.lines, + VTY_NEWLINE); + + if (host.motdfile) + vty_out(vty, "banner motd file %s%s", host.motdfile, + VTY_NEWLINE); + else if (!host.motd) + vty_out(vty, "no banner motd%s", VTY_NEWLINE); + + return 1; } /* Utility function for getting command graph. */ -static struct graph * -cmd_node_graph (vector v, enum node_type ntype) +static struct graph *cmd_node_graph(vector v, enum node_type ntype) { - struct cmd_node *cnode = vector_slot (v, ntype); - return cnode->cmdgraph; + struct cmd_node *cnode = vector_slot(v, ntype); + return cnode->cmdgraph; } -static int -cmd_try_do_shortcut (enum node_type node, char* first_word) { - if ( first_word != NULL && - node != AUTH_NODE && - node != VIEW_NODE && - node != AUTH_ENABLE_NODE && - node != ENABLE_NODE && - 0 == strcmp( "do", first_word ) ) - return 1; - return 0; +static int cmd_try_do_shortcut(enum node_type node, char *first_word) +{ + if (first_word != NULL && node != AUTH_NODE && node != VIEW_NODE + && node != AUTH_ENABLE_NODE && node != ENABLE_NODE + && 0 == strcmp("do", first_word)) + return 1; + return 0; } /** * Compare function for cmd_token. * Used with qsort to sort command completions. */ -static int -compare_completions (const void *fst, const void *snd) +static int compare_completions(const void *fst, const void *snd) { - struct cmd_token *first = *(struct cmd_token **) fst, - *secnd = *(struct cmd_token **) snd; - return strcmp (first->text, secnd->text); + struct cmd_token *first = *(struct cmd_token **)fst, + *secnd = *(struct cmd_token **)snd; + return strcmp(first->text, secnd->text); } /** @@ -825,51 +782,46 @@ compare_completions (const void *fst, const void *snd) * @param completions linked list of cmd_token * @return deduplicated and sorted vector with */ -vector -completions_to_vec (struct list *completions) -{ - vector comps = vector_init (VECTOR_MIN_SIZE); - - struct listnode *ln; - struct cmd_token *token, *cr = NULL; - unsigned int i, exists; - for (ALL_LIST_ELEMENTS_RO(completions,ln,token)) - { - if (token->type == END_TKN && (cr = token)) - continue; - - // linear search for token in completions vector - exists = 0; - for (i = 0; i < vector_active (comps) && !exists; i++) - { - struct cmd_token *curr = vector_slot (comps, i); +vector completions_to_vec(struct list *completions) +{ + vector comps = vector_init(VECTOR_MIN_SIZE); + + struct listnode *ln; + struct cmd_token *token, *cr = NULL; + unsigned int i, exists; + for (ALL_LIST_ELEMENTS_RO(completions, ln, token)) { + if (token->type == END_TKN && (cr = token)) + continue; + + // linear search for token in completions vector + exists = 0; + for (i = 0; i < vector_active(comps) && !exists; i++) { + struct cmd_token *curr = vector_slot(comps, i); #ifdef VTYSH_DEBUG - exists = !strcmp (curr->text, token->text) && - !strcmp (curr->desc, token->desc); + exists = !strcmp(curr->text, token->text) + && !strcmp(curr->desc, token->desc); #else - exists = !strcmp (curr->text, token->text); + exists = !strcmp(curr->text, token->text); #endif /* VTYSH_DEBUG */ - } + } - if (!exists) - vector_set (comps, token); - } + if (!exists) + vector_set(comps, token); + } - // sort completions - qsort (comps->index, - vector_active (comps), - sizeof (void *), - &compare_completions); + // sort completions + qsort(comps->index, vector_active(comps), sizeof(void *), + &compare_completions); - // make <cr> the first element, if it is present - if (cr) - { - vector_set_index (comps, vector_active (comps), NULL); - memmove (comps->index + 1, comps->index, (comps->alloced - 1) * sizeof (void *)); - vector_set_index (comps, 0, cr); - } + // make <cr> the first element, if it is present + if (cr) { + vector_set_index(comps, vector_active(comps), NULL); + memmove(comps->index + 1, comps->index, + (comps->alloced - 1) * sizeof(void *)); + vector_set_index(comps, 0, cr); + } - return comps; + return comps; } /** * Generates a vector of cmd_token representing possible completions @@ -880,69 +832,66 @@ completions_to_vec (struct list *completions) * @param status pointer to matcher status code * @return vector of struct cmd_token * with possible completions */ -static vector -cmd_complete_command_real (vector vline, struct vty *vty, int *status) +static vector cmd_complete_command_real(vector vline, struct vty *vty, + int *status) { - struct list *completions; - struct graph *cmdgraph = cmd_node_graph (cmdvec, vty->node); + struct list *completions; + struct graph *cmdgraph = cmd_node_graph(cmdvec, vty->node); - enum matcher_rv rv = command_complete (cmdgraph, vline, &completions); + enum matcher_rv rv = command_complete(cmdgraph, vline, &completions); - if (MATCHER_ERROR(rv)) - { - *status = CMD_ERR_NO_MATCH; - return NULL; - } + if (MATCHER_ERROR(rv)) { + *status = CMD_ERR_NO_MATCH; + return NULL; + } - vector comps = completions_to_vec (completions); - list_delete (completions); + vector comps = completions_to_vec(completions); + list_delete(completions); - // set status code appropriately - switch (vector_active (comps)) - { - case 0: - *status = CMD_ERR_NO_MATCH; - break; - case 1: - *status = CMD_COMPLETE_FULL_MATCH; - break; - default: - *status = CMD_COMPLETE_LIST_MATCH; - } + // set status code appropriately + switch (vector_active(comps)) { + case 0: + *status = CMD_ERR_NO_MATCH; + break; + case 1: + *status = CMD_COMPLETE_FULL_MATCH; + break; + default: + *status = CMD_COMPLETE_LIST_MATCH; + } - return comps; + return comps; } -vector -cmd_describe_command (vector vline, struct vty *vty, int *status) +vector cmd_describe_command(vector vline, struct vty *vty, int *status) { - vector ret; + vector ret; - if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) ) - { - enum node_type onode; - vector shifted_vline; - unsigned int index; + if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) { + enum node_type onode; + vector shifted_vline; + unsigned int index; - onode = vty->node; - vty->node = ENABLE_NODE; - /* We can try it on enable node, cos' the vty is authenticated */ + onode = vty->node; + vty->node = ENABLE_NODE; + /* We can try it on enable node, cos' the vty is authenticated + */ - shifted_vline = vector_init (vector_count(vline)); - /* use memcpy? */ - for (index = 1; index < vector_active (vline); index++) - { - vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); - } + shifted_vline = vector_init(vector_count(vline)); + /* use memcpy? */ + for (index = 1; index < vector_active(vline); index++) { + vector_set_index(shifted_vline, index - 1, + vector_lookup(vline, index)); + } - ret = cmd_complete_command_real (shifted_vline, vty, status); + ret = cmd_complete_command_real(shifted_vline, vty, status); - vector_free(shifted_vline); - vty->node = onode; - return ret; - } + vector_free(shifted_vline); + vty->node = onode; + return ret; + } - return cmd_complete_command_real (vline, vty, status); + return cmd_complete_command_real(vline, vty, status); } /** @@ -957,188 +906,182 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) * @return set of valid strings for use with Readline as tab-completions. */ -char ** -cmd_complete_command (vector vline, struct vty *vty, int *status) -{ - char **ret = NULL; - int original_node = vty->node; - vector input_line = vector_init (vector_count (vline)); - - // if the first token is 'do' we'll want to execute the command in the enable node - int do_shortcut = cmd_try_do_shortcut (vty->node, vector_slot (vline, 0)); - vty->node = do_shortcut ? ENABLE_NODE : original_node; - - // construct the input line we'll be matching on - unsigned int offset = (do_shortcut) ? 1 : 0; - for (unsigned index = 0; index + offset < vector_active (vline); index++) - vector_set_index (input_line, index, vector_lookup (vline, index + offset)); - - // get token completions -- this is a copying operation - vector comps = NULL, initial_comps; - initial_comps = cmd_complete_command_real (input_line, vty, status); - - if (!MATCHER_ERROR (*status)) - { - assert (initial_comps); - // filter out everything that is not suitable for a tab-completion - comps = vector_init (VECTOR_MIN_SIZE); - for (unsigned int i = 0; i < vector_active(initial_comps); i++) - { - struct cmd_token *token = vector_slot (initial_comps, i); - if (token->type == WORD_TKN) - vector_set (comps, token); - } - vector_free (initial_comps); - - // since we filtered results, we need to re-set status code - switch (vector_active (comps)) - { - case 0: - *status = CMD_ERR_NO_MATCH; - break; - case 1: - *status = CMD_COMPLETE_FULL_MATCH; - break; - default: - *status = CMD_COMPLETE_LIST_MATCH; - } - - // copy completions text into an array of char* - ret = XMALLOC (MTYPE_TMP, (vector_active (comps)+1) * sizeof (char *)); - unsigned int i; - for (i = 0; i < vector_active (comps); i++) - { - struct cmd_token *token = vector_slot (comps, i); - ret[i] = XSTRDUP (MTYPE_TMP, token->text); - vector_unset (comps, i); - } - // set the last element to NULL, because this array is used in - // a Readline completion_generator function which expects NULL - // as a sentinel value - ret[i] = NULL; - vector_free (comps); - comps = NULL; - } - else if (initial_comps) - vector_free (initial_comps); - - // comps should always be null here - assert (!comps); - - // free the adjusted input line - vector_free (input_line); - - // reset vty->node to its original value - vty->node = original_node; - - return ret; +char **cmd_complete_command(vector vline, struct vty *vty, int *status) +{ + char **ret = NULL; + int original_node = vty->node; + vector input_line = vector_init(vector_count(vline)); + + // if the first token is 'do' we'll want to execute the command in the + // enable node + int do_shortcut = cmd_try_do_shortcut(vty->node, vector_slot(vline, 0)); + vty->node = do_shortcut ? ENABLE_NODE : original_node; + + // construct the input line we'll be matching on + unsigned int offset = (do_shortcut) ? 1 : 0; + for (unsigned index = 0; index + offset < vector_active(vline); index++) + vector_set_index(input_line, index, + vector_lookup(vline, index + offset)); + + // get token completions -- this is a copying operation + vector comps = NULL, initial_comps; + initial_comps = cmd_complete_command_real(input_line, vty, status); + + if (!MATCHER_ERROR(*status)) { + assert(initial_comps); + // filter out everything that is not suitable for a + // tab-completion + comps = vector_init(VECTOR_MIN_SIZE); + for (unsigned int i = 0; i < vector_active(initial_comps); + i++) { + struct cmd_token *token = vector_slot(initial_comps, i); + if (token->type == WORD_TKN) + vector_set(comps, token); + } + vector_free(initial_comps); + + // since we filtered results, we need to re-set status code + switch (vector_active(comps)) { + case 0: + *status = CMD_ERR_NO_MATCH; + break; + case 1: + *status = CMD_COMPLETE_FULL_MATCH; + break; + default: + *status = CMD_COMPLETE_LIST_MATCH; + } + + // copy completions text into an array of char* + ret = XMALLOC(MTYPE_TMP, + (vector_active(comps) + 1) * sizeof(char *)); + unsigned int i; + for (i = 0; i < vector_active(comps); i++) { + struct cmd_token *token = vector_slot(comps, i); + ret[i] = XSTRDUP(MTYPE_TMP, token->text); + vector_unset(comps, i); + } + // set the last element to NULL, because this array is used in + // a Readline completion_generator function which expects NULL + // as a sentinel value + ret[i] = NULL; + vector_free(comps); + comps = NULL; + } else if (initial_comps) + vector_free(initial_comps); + + // comps should always be null here + assert(!comps); + + // free the adjusted input line + vector_free(input_line); + + // reset vty->node to its original value + vty->node = original_node; + + return ret; } /* return parent node */ /* MUST eventually converge on CONFIG_NODE */ -enum node_type -node_parent ( enum node_type node ) -{ - enum node_type ret; - - assert (node > CONFIG_NODE); - - switch (node) - { - case BGP_VPNV4_NODE: - case BGP_VPNV6_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_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - ret = BGP_NODE; - break; - case KEYCHAIN_KEY_NODE: - ret = KEYCHAIN_NODE; - break; - case LINK_PARAMS_NODE: - ret = INTERFACE_NODE; - break; - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - ret = LDP_NODE; - break; - case LDP_IPV4_IFACE_NODE: - ret = LDP_IPV4_NODE; - break; - case LDP_IPV6_IFACE_NODE: - ret = LDP_IPV6_NODE; - break; - case LDP_PSEUDOWIRE_NODE: - ret = LDP_L2VPN_NODE; - break; - default: - ret = CONFIG_NODE; - break; - } - - return ret; +enum node_type node_parent(enum node_type node) +{ + enum node_type ret; + + assert(node > CONFIG_NODE); + + switch (node) { + case BGP_VPNV4_NODE: + case BGP_VPNV6_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_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_EVPN_NODE: + ret = BGP_NODE; + break; + case KEYCHAIN_KEY_NODE: + ret = KEYCHAIN_NODE; + break; + case LINK_PARAMS_NODE: + ret = INTERFACE_NODE; + break; + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + ret = LDP_NODE; + break; + case LDP_IPV4_IFACE_NODE: + ret = LDP_IPV4_NODE; + break; + case LDP_IPV6_IFACE_NODE: + ret = LDP_IPV6_NODE; + break; + case LDP_PSEUDOWIRE_NODE: + ret = LDP_L2VPN_NODE; + break; + default: + ret = CONFIG_NODE; + break; + } + + return ret; } /* Execute command by argument vline vector. */ -static int -cmd_execute_command_real (vector vline, - enum filter_type filter, - struct vty *vty, - const struct cmd_element **cmd) -{ - struct list *argv_list; - enum matcher_rv status; - const struct cmd_element *matched_element = NULL; - - struct graph *cmdgraph = cmd_node_graph (cmdvec, vty->node); - status = command_match (cmdgraph, vline, &argv_list, &matched_element); - - if (cmd) - *cmd = matched_element; - - // if matcher error, return corresponding CMD_ERR - if (MATCHER_ERROR(status)) - { - if (argv_list) - list_delete (argv_list); - switch (status) - { - case MATCHER_INCOMPLETE: - return CMD_ERR_INCOMPLETE; - case MATCHER_AMBIGUOUS: - return CMD_ERR_AMBIGUOUS; - default: - return CMD_ERR_NO_MATCH; - } - } - - // build argv array from argv list - struct cmd_token **argv = XMALLOC (MTYPE_TMP, argv_list->count * sizeof (struct cmd_token *)); - struct listnode *ln; - struct cmd_token *token; - unsigned int i = 0; - for (ALL_LIST_ELEMENTS_RO(argv_list,ln,token)) - argv[i++] = token; - - int argc = argv_list->count; - - int ret; - if (matched_element->daemon) - ret = CMD_SUCCESS_DAEMON; - else - ret = matched_element->func (matched_element, vty, argc, argv); - - // delete list and cmd_token's in it - list_delete (argv_list); - XFREE (MTYPE_TMP, argv); - - return ret; +static int cmd_execute_command_real(vector vline, enum filter_type filter, + struct vty *vty, + const struct cmd_element **cmd) +{ + struct list *argv_list; + enum matcher_rv status; + const struct cmd_element *matched_element = NULL; + + struct graph *cmdgraph = cmd_node_graph(cmdvec, vty->node); + status = command_match(cmdgraph, vline, &argv_list, &matched_element); + + if (cmd) + *cmd = matched_element; + + // if matcher error, return corresponding CMD_ERR + if (MATCHER_ERROR(status)) { + if (argv_list) + list_delete(argv_list); + switch (status) { + case MATCHER_INCOMPLETE: + return CMD_ERR_INCOMPLETE; + case MATCHER_AMBIGUOUS: + return CMD_ERR_AMBIGUOUS; + default: + return CMD_ERR_NO_MATCH; + } + } + + // build argv array from argv list + struct cmd_token **argv = XMALLOC( + MTYPE_TMP, argv_list->count * sizeof(struct cmd_token *)); + struct listnode *ln; + struct cmd_token *token; + unsigned int i = 0; + for (ALL_LIST_ELEMENTS_RO(argv_list, ln, token)) + argv[i++] = token; + + int argc = argv_list->count; + + int ret; + if (matched_element->daemon) + ret = CMD_SUCCESS_DAEMON; + else + ret = matched_element->func(matched_element, vty, argc, argv); + + // delete list and cmd_token's in it + list_delete(argv_list); + XFREE(MTYPE_TMP, argv); + + return ret; } /** @@ -1156,58 +1099,59 @@ cmd_execute_command_real (vector vline, * @return The status of the command that has been executed or an error code * as to why no command could be executed. */ -int -cmd_execute_command (vector vline, struct vty *vty, - const struct cmd_element **cmd, - int vtysh) +int cmd_execute_command(vector vline, struct vty *vty, + const struct cmd_element **cmd, int vtysh) { - int ret, saved_ret = 0; - enum node_type onode, try_node; + int ret, saved_ret = 0; + enum node_type onode, try_node; - onode = try_node = vty->node; + onode = try_node = vty->node; - if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) - { - vector shifted_vline; - unsigned int index; + if (cmd_try_do_shortcut(vty->node, vector_slot(vline, 0))) { + vector shifted_vline; + unsigned int index; - vty->node = ENABLE_NODE; - /* We can try it on enable node, cos' the vty is authenticated */ + vty->node = ENABLE_NODE; + /* We can try it on enable node, cos' the vty is authenticated + */ - shifted_vline = vector_init (vector_count(vline)); - /* use memcpy? */ - for (index = 1; index < vector_active (vline); index++) - vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); + shifted_vline = vector_init(vector_count(vline)); + /* use memcpy? */ + for (index = 1; index < vector_active(vline); index++) + vector_set_index(shifted_vline, index - 1, + vector_lookup(vline, index)); - ret = cmd_execute_command_real (shifted_vline, FILTER_RELAXED, vty, cmd); + ret = cmd_execute_command_real(shifted_vline, FILTER_RELAXED, + vty, cmd); - vector_free(shifted_vline); - vty->node = onode; - return ret; - } + vector_free(shifted_vline); + vty->node = onode; + return ret; + } - saved_ret = ret = cmd_execute_command_real (vline, FILTER_RELAXED, vty, cmd); + saved_ret = ret = + cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd); - if (vtysh) - return saved_ret; + if (vtysh) + return saved_ret; - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - { - /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */ - while (vty->node > CONFIG_NODE) - { - try_node = node_parent(try_node); - vty->node = try_node; - ret = cmd_execute_command_real (vline, FILTER_RELAXED, vty, cmd); - if (ret == CMD_SUCCESS || ret == CMD_WARNING) - return ret; - } - /* no command succeeded, reset the vty to the original node */ - vty->node = onode; - } + if (ret != CMD_SUCCESS && ret != CMD_WARNING) { + /* This assumes all nodes above CONFIG_NODE are childs of + * CONFIG_NODE */ + while (vty->node > CONFIG_NODE) { + try_node = node_parent(try_node); + vty->node = try_node; + ret = cmd_execute_command_real(vline, FILTER_RELAXED, + vty, cmd); + if (ret == CMD_SUCCESS || ret == CMD_WARNING) + return ret; + } + /* no command succeeded, reset the vty to the original node */ + vty->node = onode; + } - /* return command status for original node */ - return saved_ret; + /* return command status for original node */ + return saved_ret; } /** @@ -1223,102 +1167,97 @@ cmd_execute_command (vector vline, struct vty *vty, * @return The status of the command that has been executed or an error code * as to why no command could be executed. */ -int -cmd_execute_command_strict (vector vline, struct vty *vty, - const struct cmd_element **cmd) +int cmd_execute_command_strict(vector vline, struct vty *vty, + const struct cmd_element **cmd) { - return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd); + return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd); } /** - * Parse one line of config, walking up the parse tree attempting to find a match + * Parse one line of config, walking up the parse tree attempting to find a + * match * * @param vty The vty context in which the command should be executed. * @param cmd Pointer where the struct cmd_element* of the match command * will be stored, if any. May be set to NULL if this info is * not needed. - * @param use_daemon Boolean to control whether or not we match on CMD_SUCCESS_DAEMON + * @param use_daemon Boolean to control whether or not we match on + * CMD_SUCCESS_DAEMON * or not. * @return The status of the command that has been executed or an error code * as to why no command could be executed. */ -int -command_config_read_one_line (struct vty *vty, const struct cmd_element **cmd, int use_daemon) +int command_config_read_one_line(struct vty *vty, + const struct cmd_element **cmd, int use_daemon) { - vector vline; - int saved_node; - int ret; + vector vline; + int saved_node; + int ret; - vline = cmd_make_strvec (vty->buf); + vline = cmd_make_strvec(vty->buf); - /* In case of comment line */ - if (vline == NULL) - return CMD_SUCCESS; + /* In case of comment line */ + if (vline == NULL) + return CMD_SUCCESS; - /* Execute configuration command : this is strict match */ - ret = cmd_execute_command_strict (vline, vty, cmd); + /* Execute configuration command : this is strict match */ + ret = cmd_execute_command_strict(vline, vty, cmd); - // Climb the tree and try the command again at each node - if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) && - !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) && - ret != CMD_SUCCESS && - ret != CMD_WARNING && - vty->node != CONFIG_NODE) { + // Climb the tree and try the command again at each node + if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) + && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) + && ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node != CONFIG_NODE) { - saved_node = vty->node; + saved_node = vty->node; - while (!(use_daemon && ret == CMD_SUCCESS_DAEMON) && - !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) && - ret != CMD_SUCCESS && - ret != CMD_WARNING && - vty->node > CONFIG_NODE) { - vty->node = node_parent(vty->node); - ret = cmd_execute_command_strict (vline, vty, cmd); - } + while (!(use_daemon && ret == CMD_SUCCESS_DAEMON) + && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) + && ret != CMD_SUCCESS && ret != CMD_WARNING + && vty->node > CONFIG_NODE) { + vty->node = node_parent(vty->node); + ret = cmd_execute_command_strict(vline, vty, cmd); + } - // If climbing the tree did not work then ignore the command and - // stay at the same node - if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) && - !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) && - ret != CMD_SUCCESS && - ret != CMD_WARNING) - { - vty->node = saved_node; - } - } + // If climbing the tree did not work then ignore the command and + // stay at the same node + if (!(use_daemon && ret == CMD_SUCCESS_DAEMON) + && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO) + && ret != CMD_SUCCESS && ret != CMD_WARNING) { + vty->node = saved_node; + } + } - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - memcpy (vty->error_buf, vty->buf, VTY_BUFSIZ); + if (ret != CMD_SUCCESS && ret != CMD_WARNING) + memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ); - cmd_free_strvec (vline); + cmd_free_strvec(vline); - return ret; + return ret; } /* Configuration make from file. */ -int -config_from_file (struct vty *vty, FILE *fp, unsigned int *line_num) +int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num) { - int ret, error_ret=0; - *line_num = 0; + int ret, error_ret = 0; + *line_num = 0; - while (fgets (vty->buf, VTY_BUFSIZ, fp)) - { - if (!error_ret) - ++(*line_num); + while (fgets(vty->buf, VTY_BUFSIZ, fp)) { + if (!error_ret) + ++(*line_num); - ret = command_config_read_one_line (vty, NULL, 0); + ret = command_config_read_one_line(vty, NULL, 0); - if (ret != CMD_SUCCESS && ret != CMD_WARNING && - ret != CMD_ERR_NOTHING_TODO) - error_ret = ret; - } + if (ret != CMD_SUCCESS && ret != CMD_WARNING + && ret != CMD_ERR_NOTHING_TODO) + error_ret = ret; + } - if (error_ret) { - return error_ret; - } + if (error_ret) { + return error_ret; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Configuration from terminal */ @@ -1328,14 +1267,14 @@ DEFUN (config_terminal, "Configuration from vty interface\n" "Configuration terminal\n") { - if (vty_config_lock (vty)) - vty->node = CONFIG_NODE; - else - { - vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE); - return CMD_WARNING; - } - return CMD_SUCCESS; + if (vty_config_lock(vty)) + vty->node = CONFIG_NODE; + else { + vty_out(vty, "VTY configuration is locked by other VTY%s", + VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; } /* Enable command */ @@ -1344,14 +1283,14 @@ DEFUN (enable, "enable", "Turn on privileged mode command\n") { - /* If enable password is NULL, change to ENABLE_NODE */ - if ((host.enable == NULL && host.enable_encrypt == NULL) || - vty->type == VTY_SHELL_SERV) - vty->node = ENABLE_NODE; - else - vty->node = AUTH_ENABLE_NODE; + /* If enable password is NULL, change to ENABLE_NODE */ + if ((host.enable == NULL && host.enable_encrypt == NULL) + || vty->type == VTY_SHELL_SERV) + vty->node = ENABLE_NODE; + else + vty->node = AUTH_ENABLE_NODE; - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Disable command */ @@ -1360,9 +1299,9 @@ DEFUN (disable, "disable", "Turn off privileged mode command\n") { - if (vty->node == ENABLE_NODE) - vty->node = VIEW_NODE; - return CMD_SUCCESS; + if (vty->node == ENABLE_NODE) + vty->node = VIEW_NODE; + return CMD_SUCCESS; } /* Down vty node level. */ @@ -1371,81 +1310,79 @@ DEFUN (config_exit, "exit", "Exit current mode and down to previous mode\n") { - cmd_exit (vty); - return CMD_SUCCESS; -} - -void -cmd_exit (struct vty *vty) -{ - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - if (vty_shell (vty)) - exit (0); - else - vty->status = VTY_CLOSE; - break; - case CONFIG_NODE: - vty->node = ENABLE_NODE; - vty_config_unlock (vty); - break; - case INTERFACE_NODE: - case PW_NODE: - case NS_NODE: - case VRF_NODE: - case ZEBRA_NODE: - case BGP_NODE: - case RIP_NODE: - case RIPNG_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_L2VPN_NODE: - case ISIS_NODE: - case KEYCHAIN_NODE: - case MASC_NODE: - case RMAP_NODE: - case PIM_NODE: - case VTY_NODE: - vty->node = CONFIG_NODE; - break; - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_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: - vty->node = BGP_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; - default: - break; - } + cmd_exit(vty); + return CMD_SUCCESS; +} + +void cmd_exit(struct vty *vty) +{ + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + if (vty_shell(vty)) + exit(0); + else + vty->status = VTY_CLOSE; + break; + case CONFIG_NODE: + vty->node = ENABLE_NODE; + vty_config_unlock(vty); + break; + case INTERFACE_NODE: + case PW_NODE: + case NS_NODE: + case VRF_NODE: + case ZEBRA_NODE: + case BGP_NODE: + case RIP_NODE: + case RIPNG_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case LDP_NODE: + case LDP_L2VPN_NODE: + case ISIS_NODE: + case KEYCHAIN_NODE: + case MASC_NODE: + case RMAP_NODE: + case PIM_NODE: + case VTY_NODE: + vty->node = CONFIG_NODE; + break; + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_VPNV4_NODE: + case BGP_VPNV6_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: + vty->node = BGP_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; + default: + break; + } } /* ALIAS_FIXME */ @@ -1454,7 +1391,7 @@ DEFUN (config_quit, "quit", "Exit current mode and down to previous mode\n") { - return config_exit (self, vty, argc, argv); + return config_exit(self, vty, argc, argv); } @@ -1464,56 +1401,55 @@ DEFUN (config_end, "end", "End current mode and change to enable mode.") { - switch (vty->node) - { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case PW_NODE: - case NS_NODE: - case VRF_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case BGP_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_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case RMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case MASC_NODE: - case PIM_NODE: - case VTY_NODE: - case LINK_PARAMS_NODE: - vty_config_unlock (vty); - vty->node = ENABLE_NODE; - break; - default: - break; - } - return CMD_SUCCESS; + switch (vty->node) { + case VIEW_NODE: + case ENABLE_NODE: + /* Nothing to do. */ + break; + case CONFIG_NODE: + case INTERFACE_NODE: + case PW_NODE: + case NS_NODE: + case VRF_NODE: + case ZEBRA_NODE: + case RIP_NODE: + case RIPNG_NODE: + case BGP_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_VPNV4_NODE: + case BGP_VPNV6_NODE: + case BGP_IPV4_NODE: + case BGP_IPV4M_NODE: + case BGP_IPV6_NODE: + case BGP_IPV6M_NODE: + case BGP_EVPN_NODE: + case RMAP_NODE: + case OSPF_NODE: + case OSPF6_NODE: + case LDP_NODE: + case LDP_IPV4_NODE: + case LDP_IPV6_NODE: + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + case LDP_L2VPN_NODE: + case LDP_PSEUDOWIRE_NODE: + case ISIS_NODE: + case KEYCHAIN_NODE: + case KEYCHAIN_KEY_NODE: + case MASC_NODE: + case PIM_NODE: + case VTY_NODE: + case LINK_PARAMS_NODE: + vty_config_unlock(vty); + vty->node = ENABLE_NODE; + break; + default: + break; + } + return CMD_SUCCESS; } /* Show version. */ @@ -1523,14 +1459,13 @@ DEFUN (show_version, SHOW_STR "Displays zebra version\n") { - vty_out (vty, "%s %s (%s).%s", FRR_FULL_NAME, FRR_VERSION, - host.name ? host.name : "", - VTY_NEWLINE); - vty_out (vty, "%s%s%s", FRR_COPYRIGHT, GIT_INFO, VTY_NEWLINE); - vty_out (vty, "configured with:%s %s%s", VTY_NEWLINE, - FRR_CONFIG_ARGS, VTY_NEWLINE); + vty_out(vty, "%s %s (%s).%s", FRR_FULL_NAME, FRR_VERSION, + host.name ? host.name : "", VTY_NEWLINE); + vty_out(vty, "%s%s%s", FRR_COPYRIGHT, GIT_INFO, VTY_NEWLINE); + vty_out(vty, "configured with:%s %s%s", VTY_NEWLINE, FRR_CONFIG_ARGS, + VTY_NEWLINE); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* "Set" version ... ignore version tags */ @@ -1542,12 +1477,13 @@ DEFUN (frr_version_defaults, "set of configuration defaults used\n" "version string\n") { - if (vty->type == VTY_TERM || vty->type == VTY_SHELL) - /* only print this when the user tries to do run it */ - vty_out (vty, "%% NOTE: This command currently does nothing.%s" - "%% It is written to the configuration for future reference.%s", - VTY_NEWLINE, VTY_NEWLINE); - return CMD_SUCCESS; + if (vty->type == VTY_TERM || vty->type == VTY_SHELL) + /* only print this when the user tries to do run it */ + vty_out(vty, + "%% NOTE: This command currently does nothing.%s" + "%% It is written to the configuration for future reference.%s", + VTY_NEWLINE, VTY_NEWLINE); + return CMD_SUCCESS; } /* Help display function for all node. */ @@ -1556,8 +1492,8 @@ DEFUN (config_help, "help", "Description of the interactive help system\n") { - vty_out (vty, - "Quagga VTY provides advanced help feature. When you need help,%s\ + vty_out(vty, + "Quagga VTY provides advanced help feature. When you need help,%s\ anytime at the command line please press '?'.%s\ %s\ If nothing matches, the help list will be empty and you must backup%s\ @@ -1568,79 +1504,74 @@ command argument (e.g. 'show ?') and describes each possible%s\ argument.%s\ 2. Partial help is provided when an abbreviated argument is entered%s\ and you want to know what arguments match the input%s\ - (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - return CMD_SUCCESS; -} - -static void -permute (struct graph_node *start, struct vty *vty) -{ - static struct list *position = NULL; - if (!position) position = list_new (); - - struct cmd_token *stok = start->data; - struct graph_node *gnn; - struct listnode *ln; - - // recursive dfs - listnode_add (position, start); - for (unsigned int i = 0; i < vector_active (start->to); i++) - { - struct graph_node *gn = vector_slot (start->to, i); - struct cmd_token *tok = gn->data; - if (tok->attr == CMD_ATTR_HIDDEN || - tok->attr == CMD_ATTR_DEPRECATED) - continue; - else if (tok->type == END_TKN || gn == start) - { - vty_out (vty, " "); - for (ALL_LIST_ELEMENTS_RO (position,ln,gnn)) - { - struct cmd_token *tt = gnn->data; - if (tt->type < SPECIAL_TKN) - vty_out (vty, " %s", tt->text); - } - if (gn == start) - vty_out (vty, "..."); - vty_out (vty, VTY_NEWLINE); - } - else - { - bool skip = false; - if (stok->type == FORK_TKN && tok->type != FORK_TKN) - for (ALL_LIST_ELEMENTS_RO (position, ln, gnn)) - if (gnn == gn) - { - skip = true; - break; - } - if (!skip) - permute (gn, vty); - } - } - list_delete_node (position, listtail(position)); -} - -int -cmd_list_cmds (struct vty *vty, int do_permute) -{ - struct cmd_node *node = vector_slot (cmdvec, vty->node); - - if (do_permute) - permute (vector_slot (node->cmdgraph->nodes, 0), vty); - else - { - /* loop over all commands at this node */ - struct cmd_element *element = NULL; - for (unsigned int i = 0; i < vector_active(node->cmd_vector); i++) - if ((element = vector_slot (node->cmd_vector, i)) && - element->attr != CMD_ATTR_DEPRECATED && - element->attr != CMD_ATTR_HIDDEN) - vty_out (vty, " %s%s", element->string, VTY_NEWLINE); - } - return CMD_SUCCESS; + (e.g. 'show me?'.)%s%s", + VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, + VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, + VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); + return CMD_SUCCESS; +} + +static void permute(struct graph_node *start, struct vty *vty) +{ + static struct list *position = NULL; + if (!position) + position = list_new(); + + struct cmd_token *stok = start->data; + struct graph_node *gnn; + struct listnode *ln; + + // recursive dfs + listnode_add(position, start); + for (unsigned int i = 0; i < vector_active(start->to); i++) { + struct graph_node *gn = vector_slot(start->to, i); + struct cmd_token *tok = gn->data; + if (tok->attr == CMD_ATTR_HIDDEN + || tok->attr == CMD_ATTR_DEPRECATED) + continue; + else if (tok->type == END_TKN || gn == start) { + vty_out(vty, " "); + for (ALL_LIST_ELEMENTS_RO(position, ln, gnn)) { + struct cmd_token *tt = gnn->data; + if (tt->type < SPECIAL_TKN) + vty_out(vty, " %s", tt->text); + } + if (gn == start) + vty_out(vty, "..."); + vty_out(vty, VTY_NEWLINE); + } else { + bool skip = false; + if (stok->type == FORK_TKN && tok->type != FORK_TKN) + for (ALL_LIST_ELEMENTS_RO(position, ln, gnn)) + if (gnn == gn) { + skip = true; + break; + } + if (!skip) + permute(gn, vty); + } + } + list_delete_node(position, listtail(position)); +} + +int cmd_list_cmds(struct vty *vty, int do_permute) +{ + struct cmd_node *node = vector_slot(cmdvec, vty->node); + + if (do_permute) + permute(vector_slot(node->cmdgraph->nodes, 0), vty); + else { + /* loop over all commands at this node */ + struct cmd_element *element = NULL; + for (unsigned int i = 0; i < vector_active(node->cmd_vector); + i++) + if ((element = vector_slot(node->cmd_vector, i)) + && element->attr != CMD_ATTR_DEPRECATED + && element->attr != CMD_ATTR_HIDDEN) + vty_out(vty, " %s%s", element->string, + VTY_NEWLINE); + } + return CMD_SUCCESS; } /* Help display function for all node. */ @@ -1650,7 +1581,7 @@ DEFUN (config_list, "Print command list\n" "Print all possible command permutations\n") { - return cmd_list_cmds (vty, argc == 2); + return cmd_list_cmds(vty, argc == 2); } DEFUN (show_commandtree, @@ -1660,38 +1591,34 @@ DEFUN (show_commandtree, "Show command tree\n" "Permutations that we are interested in\n") { - return cmd_list_cmds (vty, argc == 3); + return cmd_list_cmds(vty, argc == 3); } -static void -vty_write_config (struct vty *vty) +static void vty_write_config(struct vty *vty) { - size_t i; - struct cmd_node *node; + size_t i; + struct cmd_node *node; - if (vty->type == VTY_TERM) - { - vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE, - VTY_NEWLINE); - vty_out (vty, "!%s", VTY_NEWLINE); - } + if (vty->type == VTY_TERM) { + vty_out(vty, "%sCurrent configuration:%s", VTY_NEWLINE, + VTY_NEWLINE); + vty_out(vty, "!%s", VTY_NEWLINE); + } - vty_out (vty, "frr version %s%s", FRR_VER_SHORT, VTY_NEWLINE); - vty_out (vty, "frr defaults %s%s", DFLT_NAME, VTY_NEWLINE); - vty_out (vty, "!%s", VTY_NEWLINE); + vty_out(vty, "frr version %s%s", FRR_VER_SHORT, VTY_NEWLINE); + vty_out(vty, "frr defaults %s%s", DFLT_NAME, VTY_NEWLINE); + vty_out(vty, "!%s", VTY_NEWLINE); - for (i = 0; i < vector_active (cmdvec); i++) - if ((node = vector_slot (cmdvec, i)) && node->func - && (node->vtysh || vty->type != VTY_SHELL)) - { - if ((*node->func) (vty)) - vty_out (vty, "!%s", VTY_NEWLINE); - } + for (i = 0; i < vector_active(cmdvec); i++) + if ((node = vector_slot(cmdvec, i)) && node->func + && (node->vtysh || vty->type != VTY_SHELL)) { + if ((*node->func)(vty)) + vty_out(vty, "!%s", VTY_NEWLINE); + } - if (vty->type == VTY_TERM) - { - vty_out (vty, "end%s",VTY_NEWLINE); - } + if (vty->type == VTY_TERM) { + vty_out(vty, "end%s", VTY_NEWLINE); + } } /* Write current configuration into file. */ @@ -1704,127 +1631,119 @@ DEFUN (config_write, "Write configuration currently in memory\n" "Write configuration to terminal\n") { - int idx_type = 1; - int fd, dirfd; - char *config_file, *slash; - char *config_file_tmp = NULL; - char *config_file_sav = NULL; - int ret = CMD_WARNING; - struct vty *file_vty; - struct stat conf_stat; - - // if command was 'write terminal' or 'show running-config' - if (argc == 2 && (!strcmp(argv[idx_type]->text, "terminal") || - !strcmp(argv[0]->text, "show"))) - { - vty_write_config (vty); - return CMD_SUCCESS; - } - - if (host.noconfig) - return CMD_SUCCESS; - - /* Check and see if we are operating under vtysh configuration */ - if (host.config == NULL) - { - vty_out (vty, "Can't save to configuration file, using vtysh.%s", - VTY_NEWLINE); - return CMD_WARNING; - } - - /* Get filename. */ - config_file = host.config; + int idx_type = 1; + int fd, dirfd; + char *config_file, *slash; + char *config_file_tmp = NULL; + char *config_file_sav = NULL; + int ret = CMD_WARNING; + struct vty *file_vty; + struct stat conf_stat; + + // if command was 'write terminal' or 'show running-config' + if (argc == 2 && (!strcmp(argv[idx_type]->text, "terminal") + || !strcmp(argv[0]->text, "show"))) { + vty_write_config(vty); + return CMD_SUCCESS; + } + + if (host.noconfig) + return CMD_SUCCESS; + + /* Check and see if we are operating under vtysh configuration */ + if (host.config == NULL) { + vty_out(vty, "Can't save to configuration file, using vtysh.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* Get filename. */ + config_file = host.config; #ifndef O_DIRECTORY #define O_DIRECTORY 0 #endif - slash = strrchr (config_file, '/'); - if (slash) - { - char *config_dir = XSTRDUP (MTYPE_TMP, config_file); - config_dir[slash - config_file] = '\0'; - dirfd = open(config_dir, O_DIRECTORY | O_RDONLY); - XFREE (MTYPE_TMP, config_dir); - } - else - dirfd = open(".", O_DIRECTORY | O_RDONLY); - /* if dirfd is invalid, directory sync fails, but we're still OK */ - - config_file_sav = - XMALLOC (MTYPE_TMP, strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1); - strcpy (config_file_sav, config_file); - strcat (config_file_sav, CONF_BACKUP_EXT); - - - config_file_tmp = XMALLOC (MTYPE_TMP, strlen (config_file) + 8); - sprintf (config_file_tmp, "%s.XXXXXX", config_file); - - /* Open file to configuration write. */ - fd = mkstemp (config_file_tmp); - if (fd < 0) - { - vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp, - VTY_NEWLINE); - goto finished; - } - if (fchmod (fd, CONFIGFILE_MASK) != 0) - { - vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s", - config_file_tmp, safe_strerror(errno), errno, VTY_NEWLINE); - goto finished; - } - - /* Make vty for configuration file. */ - file_vty = vty_new (); - file_vty->wfd = fd; - file_vty->type = VTY_FILE; - - /* Config file header print. */ - vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! "); - vty_time_print (file_vty, 1); - vty_out (file_vty, "!\n"); - vty_write_config (file_vty); - vty_close (file_vty); - - if (stat(config_file, &conf_stat) >= 0) - { - if (unlink (config_file_sav) != 0) - if (errno != ENOENT) - { - vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav, - VTY_NEWLINE); - goto finished; - } - if (link (config_file, config_file_sav) != 0) - { - vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav, - VTY_NEWLINE); - goto finished; - } - if (dirfd >= 0) - fsync (dirfd); - } - if (rename (config_file_tmp, config_file) != 0) - { - vty_out (vty, "Can't save configuration file %s.%s", config_file, - VTY_NEWLINE); - goto finished; - } - if (dirfd >= 0) - fsync (dirfd); - - vty_out (vty, "Configuration saved to %s%s", config_file, - VTY_NEWLINE); - ret = CMD_SUCCESS; + slash = strrchr(config_file, '/'); + if (slash) { + char *config_dir = XSTRDUP(MTYPE_TMP, config_file); + config_dir[slash - config_file] = '\0'; + dirfd = open(config_dir, O_DIRECTORY | O_RDONLY); + XFREE(MTYPE_TMP, config_dir); + } else + dirfd = open(".", O_DIRECTORY | O_RDONLY); + /* if dirfd is invalid, directory sync fails, but we're still OK */ + + config_file_sav = XMALLOC( + MTYPE_TMP, strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1); + strcpy(config_file_sav, config_file); + strcat(config_file_sav, CONF_BACKUP_EXT); + + + config_file_tmp = XMALLOC(MTYPE_TMP, strlen(config_file) + 8); + sprintf(config_file_tmp, "%s.XXXXXX", config_file); + + /* Open file to configuration write. */ + fd = mkstemp(config_file_tmp); + if (fd < 0) { + vty_out(vty, "Can't open configuration file %s.%s", + config_file_tmp, VTY_NEWLINE); + goto finished; + } + if (fchmod(fd, CONFIGFILE_MASK) != 0) { + vty_out(vty, "Can't chmod configuration file %s: %s (%d).%s", + config_file_tmp, safe_strerror(errno), errno, + VTY_NEWLINE); + goto finished; + } + + /* Make vty for configuration file. */ + file_vty = vty_new(); + file_vty->wfd = fd; + file_vty->type = VTY_FILE; + + /* Config file header print. */ + vty_out(file_vty, "!\n! Zebra configuration saved from vty\n! "); + vty_time_print(file_vty, 1); + vty_out(file_vty, "!\n"); + vty_write_config(file_vty); + vty_close(file_vty); + + if (stat(config_file, &conf_stat) >= 0) { + if (unlink(config_file_sav) != 0) + if (errno != ENOENT) { + vty_out(vty, + "Can't unlink backup configuration file %s.%s", + config_file_sav, VTY_NEWLINE); + goto finished; + } + if (link(config_file, config_file_sav) != 0) { + vty_out(vty, + "Can't backup old configuration file %s.%s", + config_file_sav, VTY_NEWLINE); + goto finished; + } + if (dirfd >= 0) + fsync(dirfd); + } + if (rename(config_file_tmp, config_file) != 0) { + vty_out(vty, "Can't save configuration file %s.%s", config_file, + VTY_NEWLINE); + goto finished; + } + if (dirfd >= 0) + fsync(dirfd); + + vty_out(vty, "Configuration saved to %s%s", config_file, VTY_NEWLINE); + ret = CMD_SUCCESS; finished: - if (ret != CMD_SUCCESS) - unlink (config_file_tmp); - if (dirfd >= 0) - close (dirfd); - XFREE (MTYPE_TMP, config_file_tmp); - XFREE (MTYPE_TMP, config_file_sav); - return ret; + if (ret != CMD_SUCCESS) + unlink(config_file_tmp); + if (dirfd >= 0) + close(dirfd); + XFREE(MTYPE_TMP, config_file_tmp); + XFREE(MTYPE_TMP, config_file_sav); + return ret; } /* ALIAS_FIXME for 'write <terminal|memory>' */ @@ -1834,7 +1753,7 @@ DEFUN (show_running_config, SHOW_STR "running configuration (same as write terminal/memory)\n") { - return config_write (self, vty, argc, argv); + return config_write(self, vty, argc, argv); } /* ALIAS_FIXME for 'write file' */ @@ -1845,9 +1764,9 @@ DEFUN (copy_runningconf_startupconf, "Copy running config to... \n" "Copy running config to startup config (same as write file)\n") { - if (!host.noconfig) - vty_write_config (vty); - return CMD_SUCCESS; + if (!host.noconfig) + vty_write_config(vty); + return CMD_SUCCESS; } /** -- **/ @@ -1858,44 +1777,41 @@ DEFUN (show_startup_config, SHOW_STR "Contents of startup configuration\n") { - char buf[BUFSIZ]; - FILE *confp; + char buf[BUFSIZ]; + FILE *confp; - if (host.noconfig) - return CMD_SUCCESS; - if (host.config == NULL) - return CMD_WARNING; + if (host.noconfig) + return CMD_SUCCESS; + if (host.config == NULL) + return CMD_WARNING; - confp = fopen (host.config, "r"); - if (confp == NULL) - { - vty_out (vty, "Can't open configuration file [%s] due to '%s'%s", - host.config, safe_strerror(errno), VTY_NEWLINE); - return CMD_WARNING; - } + confp = fopen(host.config, "r"); + if (confp == NULL) { + vty_out(vty, "Can't open configuration file [%s] due to '%s'%s", + host.config, safe_strerror(errno), VTY_NEWLINE); + return CMD_WARNING; + } - while (fgets (buf, BUFSIZ, confp)) - { - char *cp = buf; + while (fgets(buf, BUFSIZ, confp)) { + char *cp = buf; - while (*cp != '\r' && *cp != '\n' && *cp != '\0') - cp++; - *cp = '\0'; + while (*cp != '\r' && *cp != '\n' && *cp != '\0') + cp++; + *cp = '\0'; - vty_out (vty, "%s%s", buf, VTY_NEWLINE); - } + vty_out(vty, "%s%s", buf, VTY_NEWLINE); + } - fclose (confp); + fclose(confp); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -cmd_hostname_set (const char *hostname) +int cmd_hostname_set(const char *hostname) { - XFREE (MTYPE_HOST, host.name); - host.name = hostname ? XSTRDUP (MTYPE_HOST, hostname) : NULL; - return CMD_SUCCESS; + XFREE(MTYPE_HOST, host.name); + host.name = hostname ? XSTRDUP(MTYPE_HOST, hostname) : NULL; + return CMD_SUCCESS; } /* Hostname configuration */ @@ -1905,15 +1821,15 @@ DEFUN (config_hostname, "Set system's network name\n" "This system's network name\n") { - struct cmd_token *word = argv[1]; + struct cmd_token *word = argv[1]; - if (!isalpha((int) word->arg[0])) - { - vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE); - return CMD_WARNING; - } + if (!isalpha((int)word->arg[0])) { + vty_out(vty, "Please specify string starting with alphabet%s", + VTY_NEWLINE); + return CMD_WARNING; + } - return cmd_hostname_set (word->arg); + return cmd_hostname_set(word->arg); } DEFUN (config_no_hostname, @@ -1923,7 +1839,7 @@ DEFUN (config_no_hostname, "Reset system's network name\n" "Host name of this router\n") { - return cmd_hostname_set (NULL); + return cmd_hostname_set(NULL); } /* VTY interface password set. */ @@ -1934,40 +1850,40 @@ DEFUN (config_password, "Specifies a HIDDEN password will follow\n" "The password string\n") { - int idx_8 = 1; - int idx_word = 2; - if (argc == 3) // '8' was specified - { - if (host.password) - XFREE (MTYPE_HOST, host.password); - host.password = NULL; - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = XSTRDUP (MTYPE_HOST, argv[idx_word]->arg); - return CMD_SUCCESS; - } - - if (!isalnum (argv[idx_8]->arg[0])) - { - vty_out (vty, - "Please specify string starting with alphanumeric%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (host.password) - XFREE (MTYPE_HOST, host.password); - host.password = NULL; - - if (host.encrypt) - { - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[idx_8]->arg)); - } - else - host.password = XSTRDUP (MTYPE_HOST, argv[idx_8]->arg); - - return CMD_SUCCESS; + int idx_8 = 1; + int idx_word = 2; + if (argc == 3) // '8' was specified + { + if (host.password) + XFREE(MTYPE_HOST, host.password); + host.password = NULL; + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = + XSTRDUP(MTYPE_HOST, argv[idx_word]->arg); + return CMD_SUCCESS; + } + + if (!isalnum(argv[idx_8]->arg[0])) { + vty_out(vty, + "Please specify string starting with alphanumeric%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + if (host.password) + XFREE(MTYPE_HOST, host.password); + host.password = NULL; + + if (host.encrypt) { + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(argv[idx_8]->arg)); + } else + host.password = XSTRDUP(MTYPE_HOST, argv[idx_8]->arg); + + return CMD_SUCCESS; } /* VTY enable password set. */ @@ -1979,53 +1895,49 @@ DEFUN (config_enable_password, "Specifies a HIDDEN password will follow\n" "The HIDDEN 'enable' password string\n") { - int idx_8 = 2; - int idx_word = 3; - - /* Crypt type is specified. */ - if (argc == 4) - { - if (argv[idx_8]->arg[0] == '8') - { - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - host.enable = NULL; - - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (MTYPE_HOST, argv[idx_word]->arg); - - return CMD_SUCCESS; - } - else - { - vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE); - return CMD_WARNING; - } - } - - if (!isalnum (argv[idx_8]->arg[0])) - { - vty_out (vty, - "Please specify string starting with alphanumeric%s", VTY_NEWLINE); - return CMD_WARNING; - } - - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - host.enable = NULL; - - /* Plain password input. */ - if (host.encrypt) - { - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (argv[idx_8]->arg)); - } - else - host.enable = XSTRDUP (MTYPE_HOST, argv[idx_8]->arg); - - return CMD_SUCCESS; + int idx_8 = 2; + int idx_word = 3; + + /* Crypt type is specified. */ + if (argc == 4) { + if (argv[idx_8]->arg[0] == '8') { + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + host.enable = NULL; + + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = + XSTRDUP(MTYPE_HOST, argv[idx_word]->arg); + + return CMD_SUCCESS; + } else { + vty_out(vty, "Unknown encryption type.%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + if (!isalnum(argv[idx_8]->arg[0])) { + vty_out(vty, + "Please specify string starting with alphanumeric%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + host.enable = NULL; + + /* Plain password input. */ + if (host.encrypt) { + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(argv[idx_8]->arg)); + } else + host.enable = XSTRDUP(MTYPE_HOST, argv[idx_8]->arg); + + return CMD_SUCCESS; } /* VTY enable password delete. */ @@ -2036,15 +1948,15 @@ DEFUN (no_config_enable_password, "Modify enable password parameters\n" "Assign the privileged level password\n") { - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - host.enable = NULL; + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + host.enable = NULL; - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = NULL; + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (service_password_encrypt, @@ -2053,25 +1965,25 @@ DEFUN (service_password_encrypt, "Set up miscellaneous service\n" "Enable encrypted passwords\n") { - if (host.encrypt) - return CMD_SUCCESS; + if (host.encrypt) + return CMD_SUCCESS; - host.encrypt = 1; + host.encrypt = 1; - if (host.password) - { - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.password)); - } - if (host.enable) - { - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = XSTRDUP (MTYPE_HOST, zencrypt (host.enable)); - } + if (host.password) { + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(host.password)); + } + if (host.enable) { + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = + XSTRDUP(MTYPE_HOST, zencrypt(host.enable)); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_service_password_encrypt, @@ -2081,20 +1993,20 @@ DEFUN (no_service_password_encrypt, "Set up miscellaneous service\n" "Enable encrypted passwords\n") { - if (! host.encrypt) - return CMD_SUCCESS; + if (!host.encrypt) + return CMD_SUCCESS; - host.encrypt = 0; + host.encrypt = 0; - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - host.password_encrypt = NULL; + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + host.password_encrypt = NULL; - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - host.enable_encrypt = NULL; + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + host.enable_encrypt = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_terminal_length, @@ -2104,19 +2016,18 @@ DEFUN (config_terminal_length, "Set number of lines on a screen\n" "Number of lines on screen (0 for no pausing)\n") { - int idx_number = 2; - int lines; - char *endptr = NULL; + int idx_number = 2; + int lines; + char *endptr = NULL; - lines = strtol (argv[idx_number]->arg, &endptr, 10); - if (lines < 0 || lines > 512 || *endptr != '\0') - { - vty_out (vty, "length is malformed%s", VTY_NEWLINE); - return CMD_WARNING; - } - vty->lines = lines; + lines = strtol(argv[idx_number]->arg, &endptr, 10); + if (lines < 0 || lines > 512 || *endptr != '\0') { + vty_out(vty, "length is malformed%s", VTY_NEWLINE); + return CMD_WARNING; + } + vty->lines = lines; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_terminal_no_length, @@ -2126,8 +2037,8 @@ DEFUN (config_terminal_no_length, NO_STR "Set number of lines on a screen\n") { - vty->lines = -1; - return CMD_SUCCESS; + vty->lines = -1; + return CMD_SUCCESS; } DEFUN (service_terminal_length, @@ -2137,19 +2048,18 @@ DEFUN (service_terminal_length, "System wide terminal length configuration\n" "Number of lines of VTY (0 means no line control)\n") { - int idx_number = 2; - int lines; - char *endptr = NULL; + int idx_number = 2; + int lines; + char *endptr = NULL; - lines = strtol (argv[idx_number]->arg, &endptr, 10); - if (lines < 0 || lines > 512 || *endptr != '\0') - { - vty_out (vty, "length is malformed%s", VTY_NEWLINE); - return CMD_WARNING; - } - host.lines = lines; + lines = strtol(argv[idx_number]->arg, &endptr, 10); + if (lines < 0 || lines > 512 || *endptr != '\0') { + vty_out(vty, "length is malformed%s", VTY_NEWLINE); + return CMD_WARNING; + } + host.lines = lines; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_service_terminal_length, @@ -2160,8 +2070,8 @@ DEFUN (no_service_terminal_length, "System wide terminal length configuration\n" "Number of lines of VTY (0 means no line control)\n") { - host.lines = -1; - return CMD_SUCCESS; + host.lines = -1; + return CMD_SUCCESS; } DEFUN_HIDDEN (do_echo, @@ -2170,13 +2080,14 @@ DEFUN_HIDDEN (do_echo, "Echo a message back to the vty\n" "The message to echo\n") { - char *message; + char *message; - vty_out (vty, "%s%s", ((message = argv_concat (argv, argc, 1)) ? message : ""), - VTY_NEWLINE); - if (message) - XFREE(MTYPE_TMP, message); - return CMD_SUCCESS; + vty_out(vty, "%s%s", + ((message = argv_concat(argv, argc, 1)) ? message : ""), + VTY_NEWLINE); + if (message) + XFREE(MTYPE_TMP, message); + return CMD_SUCCESS; } DEFUN (config_logmsg, @@ -2186,19 +2097,20 @@ DEFUN (config_logmsg, LOG_LEVEL_DESC "The message to send\n") { - int idx_log_level = 1; - int idx_message = 2; - int level; - char *message; + int idx_log_level = 1; + int idx_message = 2; + int level; + char *message; - if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; + if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; - zlog(level, "%s", ((message = argv_concat(argv, argc, idx_message)) ? message : "")); - if (message) - XFREE(MTYPE_TMP, message); + zlog(level, "%s", + ((message = argv_concat(argv, argc, idx_message)) ? message : "")); + if (message) + XFREE(MTYPE_TMP, message); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (show_logging, @@ -2207,51 +2119,49 @@ DEFUN (show_logging, SHOW_STR "Show current logging configuration\n") { - struct zlog *zl = zlog_default; - - vty_out (vty, "Syslog logging: "); - if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s, facility %s, ident %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]], - facility_name(zl->facility), zl->ident); - vty_out (vty, "%s", VTY_NEWLINE); - - vty_out (vty, "Stdout logging: "); - if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]); - vty_out (vty, "%s", VTY_NEWLINE); - - vty_out (vty, "Monitor logging: "); - if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]); - vty_out (vty, "%s", VTY_NEWLINE); - - vty_out (vty, "File logging: "); - if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || - !zl->fp) - vty_out (vty, "disabled"); - else - vty_out (vty, "level %s, filename %s", - zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]], - zl->filename); - vty_out (vty, "%s", VTY_NEWLINE); - - vty_out (vty, "Protocol name: %s%s", - zl->protoname, VTY_NEWLINE); - vty_out (vty, "Record priority: %s%s", - (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE); - vty_out (vty, "Timestamp precision: %d%s", - zl->timestamp_precision, VTY_NEWLINE); - - return CMD_SUCCESS; + struct zlog *zl = zlog_default; + + vty_out(vty, "Syslog logging: "); + if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s, facility %s, ident %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]], + facility_name(zl->facility), zl->ident); + vty_out(vty, "%s", VTY_NEWLINE); + + vty_out(vty, "Stdout logging: "); + if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]); + vty_out(vty, "%s", VTY_NEWLINE); + + vty_out(vty, "Monitor logging: "); + if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]); + vty_out(vty, "%s", VTY_NEWLINE); + + vty_out(vty, "File logging: "); + if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || !zl->fp) + vty_out(vty, "disabled"); + else + vty_out(vty, "level %s, filename %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]], + zl->filename); + vty_out(vty, "%s", VTY_NEWLINE); + + vty_out(vty, "Protocol name: %s%s", zl->protoname, VTY_NEWLINE); + vty_out(vty, "Record priority: %s%s", + (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE); + vty_out(vty, "Timestamp precision: %d%s", zl->timestamp_precision, + VTY_NEWLINE); + + return CMD_SUCCESS; } DEFUN (config_log_stdout, @@ -2261,19 +2171,18 @@ DEFUN (config_log_stdout, "Set stdout logging level\n" LOG_LEVEL_DESC) { - int idx_log_level = 2; + int idx_log_level = 2; - if (argc == idx_log_level) - { - zlog_set_level (ZLOG_DEST_STDOUT, zlog_default->default_lvl); - return CMD_SUCCESS; - } - int level; + if (argc == idx_log_level) { + zlog_set_level(ZLOG_DEST_STDOUT, zlog_default->default_lvl); + return CMD_SUCCESS; + } + int level; - if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - zlog_set_level (ZLOG_DEST_STDOUT, level); - return CMD_SUCCESS; + if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level(ZLOG_DEST_STDOUT, level); + return CMD_SUCCESS; } DEFUN (no_config_log_stdout, @@ -2284,8 +2193,8 @@ DEFUN (no_config_log_stdout, "Cancel logging to stdout\n" LOG_LEVEL_DESC) { - zlog_set_level (ZLOG_DEST_STDOUT, ZLOG_DISABLED); - return CMD_SUCCESS; + zlog_set_level(ZLOG_DEST_STDOUT, ZLOG_DISABLED); + return CMD_SUCCESS; } DEFUN (config_log_monitor, @@ -2295,19 +2204,18 @@ DEFUN (config_log_monitor, "Set terminal line (monitor) logging level\n" LOG_LEVEL_DESC) { - int idx_log_level = 2; + int idx_log_level = 2; - if (argc == idx_log_level) - { - zlog_set_level (ZLOG_DEST_MONITOR, zlog_default->default_lvl); - return CMD_SUCCESS; - } - int level; + if (argc == idx_log_level) { + zlog_set_level(ZLOG_DEST_MONITOR, zlog_default->default_lvl); + return CMD_SUCCESS; + } + int level; - if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - zlog_set_level (ZLOG_DEST_MONITOR, level); - return CMD_SUCCESS; + if ((level = level_match(argv[idx_log_level]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level(ZLOG_DEST_MONITOR, level); + return CMD_SUCCESS; } DEFUN (no_config_log_monitor, @@ -2318,62 +2226,56 @@ DEFUN (no_config_log_monitor, "Disable terminal line (monitor) logging\n" LOG_LEVEL_DESC) { - zlog_set_level (ZLOG_DEST_MONITOR, ZLOG_DISABLED); - return CMD_SUCCESS; + zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED); + return CMD_SUCCESS; } -static int -set_log_file(struct vty *vty, const char *fname, int loglevel) +static int set_log_file(struct vty *vty, const char *fname, int loglevel) { - int ret; - char *p = NULL; - const char *fullpath; + int ret; + char *p = NULL; + const char *fullpath; - /* Path detection. */ - if (! IS_DIRECTORY_SEP (*fname)) - { - char cwd[MAXPATHLEN+1]; - cwd[MAXPATHLEN] = '\0'; + /* Path detection. */ + if (!IS_DIRECTORY_SEP(*fname)) { + char cwd[MAXPATHLEN + 1]; + cwd[MAXPATHLEN] = '\0'; - if (getcwd (cwd, MAXPATHLEN) == NULL) - { - zlog_err ("config_log_file: Unable to alloc mem!"); - return CMD_WARNING; - } + if (getcwd(cwd, MAXPATHLEN) == NULL) { + zlog_err("config_log_file: Unable to alloc mem!"); + return CMD_WARNING; + } - if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2)) - == NULL) - { - zlog_err ("config_log_file: Unable to alloc mem!"); - return CMD_WARNING; - } - sprintf (p, "%s/%s", cwd, fname); - fullpath = p; - } - else - fullpath = fname; + if ((p = XMALLOC(MTYPE_TMP, strlen(cwd) + strlen(fname) + 2)) + == NULL) { + zlog_err("config_log_file: Unable to alloc mem!"); + return CMD_WARNING; + } + sprintf(p, "%s/%s", cwd, fname); + fullpath = p; + } else + fullpath = fname; - ret = zlog_set_file (fullpath, loglevel); + ret = zlog_set_file(fullpath, loglevel); - if (p) - XFREE (MTYPE_TMP, p); + if (p) + XFREE(MTYPE_TMP, p); - if (!ret) - { - vty_out (vty, "can't open logfile %s\n", fname); - return CMD_WARNING; - } + if (!ret) { + vty_out(vty, "can't open logfile %s\n", fname); + return CMD_WARNING; + } - if (host.logfile) - XFREE (MTYPE_HOST, host.logfile); + if (host.logfile) + XFREE(MTYPE_HOST, host.logfile); - host.logfile = XSTRDUP (MTYPE_HOST, fname); + host.logfile = XSTRDUP(MTYPE_HOST, fname); #if defined(HAVE_CUMULUS) - if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) - zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED; + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) + zlog_default->maxlvl[ZLOG_DEST_SYSLOG] = ZLOG_DISABLED; #endif - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_log_file, @@ -2384,17 +2286,17 @@ DEFUN (config_log_file, "Logging filename\n" LOG_LEVEL_DESC) { - int idx_filename = 2; - int idx_log_levels = 3; - if (argc == 4) - { - int level; - if ((level = level_match(argv[idx_log_levels]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - return set_log_file(vty, argv[idx_filename]->arg, level); - } - else - return set_log_file(vty, argv[idx_filename]->arg, zlog_default->default_lvl); + int idx_filename = 2; + int idx_log_levels = 3; + if (argc == 4) { + int level; + if ((level = level_match(argv[idx_log_levels]->arg)) + == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + return set_log_file(vty, argv[idx_filename]->arg, level); + } else + return set_log_file(vty, argv[idx_filename]->arg, + zlog_default->default_lvl); } DEFUN (no_config_log_file, @@ -2407,14 +2309,14 @@ DEFUN (no_config_log_file, "Logging file name\n" "Logging level\n") { - zlog_reset_file (); + zlog_reset_file(); - if (host.logfile) - XFREE (MTYPE_HOST, host.logfile); + if (host.logfile) + XFREE(MTYPE_HOST, host.logfile); - host.logfile = NULL; + host.logfile = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (config_log_syslog, @@ -2424,20 +2326,18 @@ DEFUN (config_log_syslog, "Set syslog logging level\n" LOG_LEVEL_DESC) { - int idx_log_levels = 2; - if (argc == 3) - { - int level; - if ((level = level_match (argv[idx_log_levels]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; - zlog_set_level (ZLOG_DEST_SYSLOG, level); - return CMD_SUCCESS; - } - else - { - zlog_set_level (ZLOG_DEST_SYSLOG, zlog_default->default_lvl); - return CMD_SUCCESS; - } + int idx_log_levels = 2; + if (argc == 3) { + int level; + if ((level = level_match(argv[idx_log_levels]->arg)) + == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level(ZLOG_DEST_SYSLOG, level); + return CMD_SUCCESS; + } else { + zlog_set_level(ZLOG_DEST_SYSLOG, zlog_default->default_lvl); + return CMD_SUCCESS; + } } DEFUN (no_config_log_syslog, @@ -2449,8 +2349,8 @@ DEFUN (no_config_log_syslog, LOG_FACILITY_DESC LOG_LEVEL_DESC) { - zlog_set_level (ZLOG_DEST_SYSLOG, ZLOG_DISABLED); - return CMD_SUCCESS; + zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + return CMD_SUCCESS; } DEFUN (config_log_facility, @@ -2460,11 +2360,11 @@ DEFUN (config_log_facility, "Facility parameter for syslog messages\n" LOG_FACILITY_DESC) { - int idx_target = 2; - int facility = facility_match(argv[idx_target]->arg); + int idx_target = 2; + int facility = facility_match(argv[idx_target]->arg); - zlog_default->facility = facility; - return CMD_SUCCESS; + zlog_default->facility = facility; + return CMD_SUCCESS; } DEFUN (no_config_log_facility, @@ -2475,40 +2375,38 @@ DEFUN (no_config_log_facility, "Reset syslog facility to default (daemon)\n" LOG_FACILITY_DESC) { - zlog_default->facility = LOG_DAEMON; - return CMD_SUCCESS; + zlog_default->facility = LOG_DAEMON; + return CMD_SUCCESS; } -DEFUN_DEPRECATED (config_log_trap, - config_log_trap_cmd, - "log trap <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>", - "Logging control\n" - "(Deprecated) Set logging level and default for all destinations\n" - LOG_LEVEL_DESC) +DEFUN_DEPRECATED( + config_log_trap, config_log_trap_cmd, + "log trap <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>", + "Logging control\n" + "(Deprecated) Set logging level and default for all destinations\n" LOG_LEVEL_DESC) { - int new_level ; - int i; + int new_level; + int i; - if ((new_level = level_match(argv[2]->arg)) == ZLOG_DISABLED) - return CMD_ERR_NO_MATCH; + if ((new_level = level_match(argv[2]->arg)) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; - zlog_default->default_lvl = new_level; - for (i = 0; i < ZLOG_NUM_DESTS; i++) - if (zlog_default->maxlvl[i] != ZLOG_DISABLED) - zlog_default->maxlvl[i] = new_level; - return CMD_SUCCESS; + zlog_default->default_lvl = new_level; + for (i = 0; i < ZLOG_NUM_DESTS; i++) + if (zlog_default->maxlvl[i] != ZLOG_DISABLED) + zlog_default->maxlvl[i] = new_level; + return CMD_SUCCESS; } -DEFUN_DEPRECATED (no_config_log_trap, - no_config_log_trap_cmd, - "no log trap [emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]", - NO_STR - "Logging control\n" - "Permit all logging information\n" - LOG_LEVEL_DESC) +DEFUN_DEPRECATED( + no_config_log_trap, no_config_log_trap_cmd, + "no log trap [emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]", + NO_STR + "Logging control\n" + "Permit all logging information\n" LOG_LEVEL_DESC) { - zlog_default->default_lvl = LOG_DEBUG; - return CMD_SUCCESS; + zlog_default->default_lvl = LOG_DEBUG; + return CMD_SUCCESS; } DEFUN (config_log_record_priority, @@ -2517,8 +2415,8 @@ DEFUN (config_log_record_priority, "Logging control\n" "Log the priority of the message within the message\n") { - zlog_default->record_priority = 1 ; - return CMD_SUCCESS; + zlog_default->record_priority = 1; + return CMD_SUCCESS; } DEFUN (no_config_log_record_priority, @@ -2528,8 +2426,8 @@ DEFUN (no_config_log_record_priority, "Logging control\n" "Do not log the priority of the message within the message\n") { - zlog_default->record_priority = 0 ; - return CMD_SUCCESS; + zlog_default->record_priority = 0; + return CMD_SUCCESS; } DEFUN (config_log_timestamp_precision, @@ -2540,10 +2438,11 @@ DEFUN (config_log_timestamp_precision, "Set the timestamp precision\n" "Number of subsecond digits\n") { - int idx_number = 3; - VTY_GET_INTEGER_RANGE("Timestamp Precision", - zlog_default->timestamp_precision, argv[idx_number]->arg, 0, 6); - return CMD_SUCCESS; + int idx_number = 3; + VTY_GET_INTEGER_RANGE("Timestamp Precision", + zlog_default->timestamp_precision, + argv[idx_number]->arg, 0, 6); + return CMD_SUCCESS; } DEFUN (no_config_log_timestamp_precision, @@ -2554,32 +2453,29 @@ DEFUN (no_config_log_timestamp_precision, "Timestamp configuration\n" "Reset the timestamp precision to the default value of 0\n") { - zlog_default->timestamp_precision = 0 ; - return CMD_SUCCESS; + zlog_default->timestamp_precision = 0; + return CMD_SUCCESS; } -int -cmd_banner_motd_file (const char *file) +int cmd_banner_motd_file(const char *file) { - int success = CMD_SUCCESS; - char p[PATH_MAX]; - char *rpath; - char *in; + int success = CMD_SUCCESS; + char p[PATH_MAX]; + char *rpath; + char *in; - rpath = realpath (file, p); - if (!rpath) - return CMD_ERR_NO_FILE; - in = strstr (rpath, SYSCONFDIR); - if (in == rpath) - { - if (host.motdfile) - XFREE (MTYPE_HOST, host.motdfile); - host.motdfile = XSTRDUP (MTYPE_HOST, file); - } - else - success = CMD_WARNING; + rpath = realpath(file, p); + if (!rpath) + return CMD_ERR_NO_FILE; + in = strstr(rpath, SYSCONFDIR); + if (in == rpath) { + if (host.motdfile) + XFREE(MTYPE_HOST, host.motdfile); + host.motdfile = XSTRDUP(MTYPE_HOST, file); + } else + success = CMD_WARNING; - return success; + return success; } DEFUN (banner_motd_file, @@ -2590,16 +2486,16 @@ DEFUN (banner_motd_file, "Banner from a file\n" "Filename\n") { - int idx_file = 3; - const char *filename = argv[idx_file]->arg; - int cmd = cmd_banner_motd_file (filename); + int idx_file = 3; + const char *filename = argv[idx_file]->arg; + int cmd = cmd_banner_motd_file(filename); - if (cmd == CMD_ERR_NO_FILE) - vty_out (vty, "%s does not exist", filename); - else if (cmd == CMD_WARNING) - vty_out (vty, "%s must be in %s", filename, SYSCONFDIR); + if (cmd == CMD_ERR_NO_FILE) + vty_out(vty, "%s does not exist", filename); + else if (cmd == CMD_WARNING) + vty_out(vty, "%s must be in %s", filename, SYSCONFDIR); - return cmd; + return cmd; } DEFUN (banner_motd_default, @@ -2609,8 +2505,8 @@ DEFUN (banner_motd_default, "Strings for motd\n" "Default string\n") { - host.motd = default_motd; - return CMD_SUCCESS; + host.motd = default_motd; + return CMD_SUCCESS; } DEFUN (no_banner_motd, @@ -2620,39 +2516,36 @@ DEFUN (no_banner_motd, "Set banner string\n" "Strings for motd\n") { - host.motd = NULL; - if (host.motdfile) - XFREE (MTYPE_HOST, host.motdfile); - host.motdfile = NULL; - return CMD_SUCCESS; + host.motd = NULL; + if (host.motdfile) + XFREE(MTYPE_HOST, host.motdfile); + host.motdfile = NULL; + return CMD_SUCCESS; } /* Set config filename. Called from vty.c */ -void -host_config_set (const char *filename) +void host_config_set(const char *filename) { - if (host.config) - XFREE (MTYPE_HOST, host.config); - host.config = XSTRDUP (MTYPE_HOST, filename); + if (host.config) + XFREE(MTYPE_HOST, host.config); + host.config = XSTRDUP(MTYPE_HOST, filename); } -const char * -host_config_get (void) +const char *host_config_get(void) { - return host.config; + return host.config; } -void -install_default (enum node_type node) +void install_default(enum node_type node) { - install_element (node, &config_exit_cmd); - install_element (node, &config_quit_cmd); - install_element (node, &config_end_cmd); - install_element (node, &config_help_cmd); - install_element (node, &config_list_cmd); + install_element(node, &config_exit_cmd); + install_element(node, &config_quit_cmd); + install_element(node, &config_end_cmd); + install_element(node, &config_help_cmd); + install_element(node, &config_list_cmd); - install_element (node, &config_write_cmd); - install_element (node, &show_running_config_cmd); + install_element(node, &config_write_cmd); + install_element(node, &show_running_config_cmd); } /* Initialize command interface. Install basic nodes and commands. @@ -2660,192 +2553,188 @@ install_default (enum node_type node) * terminal = 0 -- vtysh / no logging, no config control * terminal = 1 -- normal daemon * terminal = -1 -- watchfrr / no logging, but minimal config control */ -void -cmd_init (int terminal) -{ - qobj_init (); - - /* Allocate initial top vector of commands. */ - cmdvec = vector_init (VECTOR_MIN_SIZE); - - /* Default host value settings. */ - host.name = NULL; - host.password = NULL; - host.enable = NULL; - host.logfile = NULL; - host.config = NULL; - host.noconfig = (terminal < 0); - host.lines = -1; - host.motd = default_motd; - host.motdfile = NULL; - - /* Install top nodes. */ - install_node (&view_node, NULL); - install_node (&enable_node, NULL); - install_node (&auth_node, NULL); - install_node (&auth_enable_node, NULL); - install_node (&config_node, config_write_host); - - /* Each node's basic commands. */ - install_element (VIEW_NODE, &show_version_cmd); - if (terminal) - { - install_element (VIEW_NODE, &config_list_cmd); - install_element (VIEW_NODE, &config_exit_cmd); - install_element (VIEW_NODE, &config_quit_cmd); - install_element (VIEW_NODE, &config_help_cmd); - install_element (VIEW_NODE, &config_enable_cmd); - install_element (VIEW_NODE, &config_terminal_length_cmd); - install_element (VIEW_NODE, &config_terminal_no_length_cmd); - install_element (VIEW_NODE, &show_logging_cmd); - install_element (VIEW_NODE, &show_commandtree_cmd); - install_element (VIEW_NODE, &echo_cmd); - } - - if (terminal) - { - install_element (ENABLE_NODE, &config_end_cmd); - install_element (ENABLE_NODE, &config_disable_cmd); - install_element (ENABLE_NODE, &config_terminal_cmd); - install_element (ENABLE_NODE, ©_runningconf_startupconf_cmd); - install_element (ENABLE_NODE, &config_write_cmd); - install_element (ENABLE_NODE, &show_running_config_cmd); - } - install_element (ENABLE_NODE, &show_startup_config_cmd); - - if (terminal) - { - install_element (ENABLE_NODE, &config_logmsg_cmd); - install_default (CONFIG_NODE); - - thread_cmd_init (); - workqueue_cmd_init (); - } - - install_element (CONFIG_NODE, &hostname_cmd); - install_element (CONFIG_NODE, &no_hostname_cmd); - install_element (CONFIG_NODE, &frr_version_defaults_cmd); - - if (terminal > 0) - { - install_element (CONFIG_NODE, &password_cmd); - install_element (CONFIG_NODE, &enable_password_cmd); - install_element (CONFIG_NODE, &no_enable_password_cmd); - - install_element (CONFIG_NODE, &config_log_stdout_cmd); - install_element (CONFIG_NODE, &no_config_log_stdout_cmd); - install_element (CONFIG_NODE, &config_log_monitor_cmd); - install_element (CONFIG_NODE, &no_config_log_monitor_cmd); - install_element (CONFIG_NODE, &config_log_file_cmd); - install_element (CONFIG_NODE, &no_config_log_file_cmd); - install_element (CONFIG_NODE, &config_log_syslog_cmd); - install_element (CONFIG_NODE, &no_config_log_syslog_cmd); - install_element (CONFIG_NODE, &config_log_facility_cmd); - install_element (CONFIG_NODE, &no_config_log_facility_cmd); - install_element (CONFIG_NODE, &config_log_trap_cmd); - install_element (CONFIG_NODE, &no_config_log_trap_cmd); - install_element (CONFIG_NODE, &config_log_record_priority_cmd); - install_element (CONFIG_NODE, &no_config_log_record_priority_cmd); - install_element (CONFIG_NODE, &config_log_timestamp_precision_cmd); - install_element (CONFIG_NODE, &no_config_log_timestamp_precision_cmd); - install_element (CONFIG_NODE, &service_password_encrypt_cmd); - install_element (CONFIG_NODE, &no_service_password_encrypt_cmd); - install_element (CONFIG_NODE, &banner_motd_default_cmd); - install_element (CONFIG_NODE, &banner_motd_file_cmd); - install_element (CONFIG_NODE, &no_banner_motd_cmd); - install_element (CONFIG_NODE, &service_terminal_length_cmd); - install_element (CONFIG_NODE, &no_service_terminal_length_cmd); - - vrf_install_commands (); - } +void cmd_init(int terminal) +{ + qobj_init(); + + /* Allocate initial top vector of commands. */ + cmdvec = vector_init(VECTOR_MIN_SIZE); + + /* Default host value settings. */ + host.name = NULL; + host.password = NULL; + host.enable = NULL; + host.logfile = NULL; + host.config = NULL; + host.noconfig = (terminal < 0); + host.lines = -1; + host.motd = default_motd; + host.motdfile = NULL; + + /* Install top nodes. */ + install_node(&view_node, NULL); + install_node(&enable_node, NULL); + install_node(&auth_node, NULL); + install_node(&auth_enable_node, NULL); + install_node(&config_node, config_write_host); + + /* Each node's basic commands. */ + install_element(VIEW_NODE, &show_version_cmd); + if (terminal) { + install_element(VIEW_NODE, &config_list_cmd); + install_element(VIEW_NODE, &config_exit_cmd); + install_element(VIEW_NODE, &config_quit_cmd); + install_element(VIEW_NODE, &config_help_cmd); + install_element(VIEW_NODE, &config_enable_cmd); + install_element(VIEW_NODE, &config_terminal_length_cmd); + install_element(VIEW_NODE, &config_terminal_no_length_cmd); + install_element(VIEW_NODE, &show_logging_cmd); + install_element(VIEW_NODE, &show_commandtree_cmd); + install_element(VIEW_NODE, &echo_cmd); + } + + if (terminal) { + install_element(ENABLE_NODE, &config_end_cmd); + install_element(ENABLE_NODE, &config_disable_cmd); + install_element(ENABLE_NODE, &config_terminal_cmd); + install_element(ENABLE_NODE, ©_runningconf_startupconf_cmd); + install_element(ENABLE_NODE, &config_write_cmd); + install_element(ENABLE_NODE, &show_running_config_cmd); + } + install_element(ENABLE_NODE, &show_startup_config_cmd); + + if (terminal) { + install_element(ENABLE_NODE, &config_logmsg_cmd); + install_default(CONFIG_NODE); + + thread_cmd_init(); + workqueue_cmd_init(); + } + + install_element(CONFIG_NODE, &hostname_cmd); + install_element(CONFIG_NODE, &no_hostname_cmd); + install_element(CONFIG_NODE, &frr_version_defaults_cmd); + + if (terminal > 0) { + install_element(CONFIG_NODE, &password_cmd); + install_element(CONFIG_NODE, &enable_password_cmd); + install_element(CONFIG_NODE, &no_enable_password_cmd); + + install_element(CONFIG_NODE, &config_log_stdout_cmd); + install_element(CONFIG_NODE, &no_config_log_stdout_cmd); + install_element(CONFIG_NODE, &config_log_monitor_cmd); + install_element(CONFIG_NODE, &no_config_log_monitor_cmd); + install_element(CONFIG_NODE, &config_log_file_cmd); + install_element(CONFIG_NODE, &no_config_log_file_cmd); + install_element(CONFIG_NODE, &config_log_syslog_cmd); + install_element(CONFIG_NODE, &no_config_log_syslog_cmd); + install_element(CONFIG_NODE, &config_log_facility_cmd); + install_element(CONFIG_NODE, &no_config_log_facility_cmd); + install_element(CONFIG_NODE, &config_log_trap_cmd); + install_element(CONFIG_NODE, &no_config_log_trap_cmd); + install_element(CONFIG_NODE, &config_log_record_priority_cmd); + install_element(CONFIG_NODE, + &no_config_log_record_priority_cmd); + install_element(CONFIG_NODE, + &config_log_timestamp_precision_cmd); + install_element(CONFIG_NODE, + &no_config_log_timestamp_precision_cmd); + install_element(CONFIG_NODE, &service_password_encrypt_cmd); + install_element(CONFIG_NODE, &no_service_password_encrypt_cmd); + install_element(CONFIG_NODE, &banner_motd_default_cmd); + install_element(CONFIG_NODE, &banner_motd_file_cmd); + install_element(CONFIG_NODE, &no_banner_motd_cmd); + install_element(CONFIG_NODE, &service_terminal_length_cmd); + install_element(CONFIG_NODE, &no_service_terminal_length_cmd); + + vrf_install_commands(); + } #ifdef DEV_BUILD - grammar_sandbox_init(); + grammar_sandbox_init(); #endif } -struct cmd_token * -new_cmd_token (enum cmd_token_type type, u_char attr, - const char *text, const char *desc) -{ - struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token)); - token->type = type; - token->attr = attr; - token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL; - token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL; - token->refcnt = 1; - token->arg = NULL; - token->allowrepeat = false; - - return token; -} - -void -del_cmd_token (struct cmd_token *token) -{ - if (!token) return; - - if (token->text) - XFREE (MTYPE_CMD_TEXT, token->text); - if (token->desc) - XFREE (MTYPE_CMD_DESC, token->desc); - if (token->arg) - XFREE (MTYPE_CMD_ARG, token->arg); - - XFREE (MTYPE_CMD_TOKENS, token); -} - -struct cmd_token * -copy_cmd_token (struct cmd_token *token) -{ - struct cmd_token *copy = new_cmd_token (token->type, token->attr, NULL, NULL); - copy->max = token->max; - copy->min = token->min; - copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL; - copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL; - copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL; - - return copy; -} - -void -cmd_terminate () -{ - struct cmd_node *cmd_node; - - if (cmdvec) - { - for (unsigned int i = 0; i < vector_active (cmdvec); i++) - if ((cmd_node = vector_slot (cmdvec, i)) != NULL) - { - // deleting the graph delets the cmd_element as well - graph_delete_graph (cmd_node->cmdgraph); - vector_free (cmd_node->cmd_vector); - hash_clean (cmd_node->cmd_hash, NULL); - hash_free (cmd_node->cmd_hash); - cmd_node->cmd_hash = NULL; - } - - vector_free (cmdvec); - cmdvec = NULL; - } - - if (host.name) - XFREE (MTYPE_HOST, host.name); - if (host.password) - XFREE (MTYPE_HOST, host.password); - if (host.password_encrypt) - XFREE (MTYPE_HOST, host.password_encrypt); - if (host.enable) - XFREE (MTYPE_HOST, host.enable); - if (host.enable_encrypt) - XFREE (MTYPE_HOST, host.enable_encrypt); - if (host.logfile) - XFREE (MTYPE_HOST, host.logfile); - if (host.motdfile) - XFREE (MTYPE_HOST, host.motdfile); - if (host.config) - XFREE (MTYPE_HOST, host.config); - - qobj_finish (); +struct cmd_token *new_cmd_token(enum cmd_token_type type, u_char attr, + const char *text, const char *desc) +{ + struct cmd_token *token = + XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct cmd_token)); + token->type = type; + token->attr = attr; + token->text = text ? XSTRDUP(MTYPE_CMD_TEXT, text) : NULL; + token->desc = desc ? XSTRDUP(MTYPE_CMD_DESC, desc) : NULL; + token->refcnt = 1; + token->arg = NULL; + token->allowrepeat = false; + + return token; +} + +void del_cmd_token(struct cmd_token *token) +{ + if (!token) + return; + + if (token->text) + XFREE(MTYPE_CMD_TEXT, token->text); + if (token->desc) + XFREE(MTYPE_CMD_DESC, token->desc); + if (token->arg) + XFREE(MTYPE_CMD_ARG, token->arg); + + XFREE(MTYPE_CMD_TOKENS, token); +} + +struct cmd_token *copy_cmd_token(struct cmd_token *token) +{ + struct cmd_token *copy = + new_cmd_token(token->type, token->attr, NULL, NULL); + copy->max = token->max; + copy->min = token->min; + copy->text = token->text ? XSTRDUP(MTYPE_CMD_TEXT, token->text) : NULL; + copy->desc = token->desc ? XSTRDUP(MTYPE_CMD_DESC, token->desc) : NULL; + copy->arg = token->arg ? XSTRDUP(MTYPE_CMD_ARG, token->arg) : NULL; + + return copy; +} + +void cmd_terminate() +{ + struct cmd_node *cmd_node; + + if (cmdvec) { + for (unsigned int i = 0; i < vector_active(cmdvec); i++) + if ((cmd_node = vector_slot(cmdvec, i)) != NULL) { + // deleting the graph delets the cmd_element as + // well + graph_delete_graph(cmd_node->cmdgraph); + vector_free(cmd_node->cmd_vector); + hash_clean(cmd_node->cmd_hash, NULL); + hash_free(cmd_node->cmd_hash); + cmd_node->cmd_hash = NULL; + } + + vector_free(cmdvec); + cmdvec = NULL; + } + + if (host.name) + XFREE(MTYPE_HOST, host.name); + if (host.password) + XFREE(MTYPE_HOST, host.password); + if (host.password_encrypt) + XFREE(MTYPE_HOST, host.password_encrypt); + if (host.enable) + XFREE(MTYPE_HOST, host.enable); + if (host.enable_encrypt) + XFREE(MTYPE_HOST, host.enable_encrypt); + if (host.logfile) + XFREE(MTYPE_HOST, host.logfile); + if (host.motdfile) + XFREE(MTYPE_HOST, host.motdfile); + if (host.config) + XFREE(MTYPE_HOST, host.config); + + qobj_finish(); } |