2 * CLI backend interface.
5 * Copyright (C) 2016 Cumulus Networks, Inc.
6 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
7 * Copyright (C) 2013 by Open Source Routing.
8 * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC")
10 * This file is part of GNU Zebra.
12 * GNU Zebra is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2, or (at your option) any
17 * GNU Zebra is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU Zebra; see the file COPYING. If not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
33 #include <lib/version.h>
39 #include "workqueue.h"
41 #include "command_match.h"
42 #include "command_parse.h"
44 DEFINE_MTYPE( LIB
, HOST
, "Host config")
45 DEFINE_MTYPE( LIB
, STRVEC
, "String vector")
46 DEFINE_MTYPE_STATIC(LIB
, CMD_TOKENS
, "Command desc")
48 /* Command vector which includes some level of command lists. Normally
49 each daemon maintains each own cmdvec. */
52 /* Host information structure. */
55 /* Standard command node structures. */
56 static struct cmd_node auth_node
=
62 static struct cmd_node view_node
=
68 static struct cmd_node restricted_node
=
74 static struct cmd_node auth_enable_node
=
80 static struct cmd_node enable_node
=
86 static struct cmd_node config_node
=
93 /* Default motd string. */
94 static const char *default_motd
=
96 Hello, this is " QUAGGA_PROGNAME
" (version " QUAGGA_VERSION
").\r\n\
97 " QUAGGA_COPYRIGHT
"\r\n\
101 static const struct facility_map
{
105 } syslog_facilities
[] =
107 { LOG_KERN
, "kern", 1 },
108 { LOG_USER
, "user", 2 },
109 { LOG_MAIL
, "mail", 1 },
110 { LOG_DAEMON
, "daemon", 1 },
111 { LOG_AUTH
, "auth", 1 },
112 { LOG_SYSLOG
, "syslog", 1 },
113 { LOG_LPR
, "lpr", 2 },
114 { LOG_NEWS
, "news", 1 },
115 { LOG_UUCP
, "uucp", 2 },
116 { LOG_CRON
, "cron", 1 },
118 { LOG_FTP
, "ftp", 1 },
120 { LOG_LOCAL0
, "local0", 6 },
121 { LOG_LOCAL1
, "local1", 6 },
122 { LOG_LOCAL2
, "local2", 6 },
123 { LOG_LOCAL3
, "local3", 6 },
124 { LOG_LOCAL4
, "local4", 6 },
125 { LOG_LOCAL5
, "local5", 6 },
126 { LOG_LOCAL6
, "local6", 6 },
127 { LOG_LOCAL7
, "local7", 6 },
132 facility_name(int facility
)
134 const struct facility_map
*fm
;
136 for (fm
= syslog_facilities
; fm
->name
; fm
++)
137 if (fm
->facility
== facility
)
143 facility_match(const char *str
)
145 const struct facility_map
*fm
;
147 for (fm
= syslog_facilities
; fm
->name
; fm
++)
148 if (!strncmp(str
,fm
->name
,fm
->match
))
154 level_match(const char *s
)
158 for ( level
= 0 ; zlog_priority
[level
] != NULL
; level
++ )
159 if (!strncmp (s
, zlog_priority
[level
], 2))
161 return ZLOG_DISABLED
;
164 /* This is called from main when a daemon is invoked with -v or --version. */
166 print_version (const char *progname
)
168 printf ("%s version %s\n", progname
, QUAGGA_VERSION
);
169 printf ("%s\n", QUAGGA_COPYRIGHT
);
170 printf ("configured with:\n\t%s\n", QUAGGA_CONFIG_ARGS
);
174 /* Utility function to concatenate argv argument into a single string
175 with inserting ' ' character between each argument. */
177 argv_concat (struct cmd_token
**argv
, int argc
, int shift
)
185 for (i
= shift
; i
< argc
; i
++)
186 len
+= strlen(argv
[i
]->arg
)+1;
189 p
= str
= XMALLOC(MTYPE_TMP
, len
);
190 for (i
= shift
; i
< argc
; i
++)
193 memcpy(p
, argv
[i
]->arg
, (arglen
= strlen(argv
[i
]->arg
)));
201 /* Install top node of command vector. */
203 install_node (struct cmd_node
*node
,
204 int (*func
) (struct vty
*))
206 vector_set_index (cmdvec
, node
->node
, node
);
208 node
->cmdgraph
= graph_new ();
211 /* Breaking up string into each command piece. I assume given
212 character is separated by a space character. Return value is a
213 vector which includes char ** data element. */
215 cmd_make_strvec (const char *string
)
217 const char *cp
, *start
;
227 /* Skip white spaces. */
228 while (isspace ((int) *cp
) && *cp
!= '\0')
231 /* Return if there is only white spaces */
235 if (*cp
== '!' || *cp
== '#')
238 /* Prepare return vector. */
239 strvec
= vector_init (VECTOR_MIN_SIZE
);
241 /* Copy each command piece and set into vector. */
245 while (!(isspace ((int) *cp
) || *cp
== '\r' || *cp
== '\n') &&
249 token
= XMALLOC (MTYPE_STRVEC
, strlen
+ 1);
250 memcpy (token
, start
, strlen
);
251 *(token
+ strlen
) = '\0';
252 vector_set (strvec
, token
);
254 while ((isspace ((int) *cp
) || *cp
== '\n' || *cp
== '\r') &&
263 /* Free allocated string vector. */
265 cmd_free_strvec (vector v
)
273 for (i
= 0; i
< vector_active (v
); i
++)
274 if ((cp
= vector_slot (v
, i
)) != NULL
)
275 XFREE (MTYPE_STRVEC
, cp
);
281 /* Return prompt character of specified node. */
283 cmd_prompt (enum node_type node
)
285 struct cmd_node
*cnode
;
287 cnode
= vector_slot (cmdvec
, node
);
288 return cnode
->prompt
;
291 /* Install a command into a node. */
293 install_element (enum node_type ntype
, struct cmd_element
*cmd
)
295 struct cmd_node
*cnode
;
297 /* cmd_init hasn't been called */
301 cnode
= vector_slot (cmdvec
, ntype
);
305 fprintf (stderr
, "Command node %d doesn't exist, please check it\n",
310 // add node to command graph and command vector
311 command_parse_format (cnode
->cmdgraph
, cmd
);
312 vector_set (cnode
->cmd_vector
, cmd
);
315 static const unsigned char itoa64
[] =
316 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
319 to64(char *s
, long v
, int n
)
323 *s
++ = itoa64
[v
&0x3f];
329 zencrypt (const char *passwd
)
333 char *crypt (const char *, const char *);
337 to64(&salt
[0], random(), 3);
338 to64(&salt
[3], tv
.tv_usec
, 3);
341 return crypt (passwd
, salt
);
344 /* This function write configuration of this host. */
346 config_write_host (struct vty
*vty
)
349 vty_out (vty
, "hostname %s%s", host
.name
, VTY_NEWLINE
);
353 if (host
.password_encrypt
)
354 vty_out (vty
, "password 8 %s%s", host
.password_encrypt
, VTY_NEWLINE
);
355 if (host
.enable_encrypt
)
356 vty_out (vty
, "enable password 8 %s%s", host
.enable_encrypt
, VTY_NEWLINE
);
361 vty_out (vty
, "password %s%s", host
.password
, VTY_NEWLINE
);
363 vty_out (vty
, "enable password %s%s", host
.enable
, VTY_NEWLINE
);
366 if (zlog_default
->default_lvl
!= LOG_DEBUG
)
368 vty_out (vty
, "! N.B. The 'log trap' command is deprecated.%s",
370 vty_out (vty
, "log trap %s%s",
371 zlog_priority
[zlog_default
->default_lvl
], VTY_NEWLINE
);
374 if (host
.logfile
&& (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != ZLOG_DISABLED
))
376 vty_out (vty
, "log file %s", host
.logfile
);
377 if (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != zlog_default
->default_lvl
)
379 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_FILE
]]);
380 vty_out (vty
, "%s", VTY_NEWLINE
);
383 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != ZLOG_DISABLED
)
385 vty_out (vty
, "log stdout");
386 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != zlog_default
->default_lvl
)
388 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
]]);
389 vty_out (vty
, "%s", VTY_NEWLINE
);
392 if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
393 vty_out(vty
,"no log monitor%s",VTY_NEWLINE
);
394 else if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] != zlog_default
->default_lvl
)
395 vty_out(vty
,"log monitor %s%s",
396 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
]],VTY_NEWLINE
);
398 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != ZLOG_DISABLED
)
400 vty_out (vty
, "log syslog");
401 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != zlog_default
->default_lvl
)
403 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
]]);
404 vty_out (vty
, "%s", VTY_NEWLINE
);
407 if (zlog_default
->facility
!= LOG_DAEMON
)
408 vty_out (vty
, "log facility %s%s",
409 facility_name(zlog_default
->facility
), VTY_NEWLINE
);
411 if (zlog_default
->record_priority
== 1)
412 vty_out (vty
, "log record-priority%s", VTY_NEWLINE
);
414 if (zlog_default
->timestamp_precision
> 0)
415 vty_out (vty
, "log timestamp precision %d%s",
416 zlog_default
->timestamp_precision
, VTY_NEWLINE
);
419 vty_out (vty
, "service advanced-vty%s", VTY_NEWLINE
);
422 vty_out (vty
, "service password-encryption%s", VTY_NEWLINE
);
425 vty_out (vty
, "service terminal-length %d%s", host
.lines
,
429 vty_out (vty
, "banner motd file %s%s", host
.motdfile
, VTY_NEWLINE
);
430 else if (! host
.motd
)
431 vty_out (vty
, "no banner motd%s", VTY_NEWLINE
);
436 /* Utility function for getting command vector. */
438 cmd_node_vector (vector v
, enum node_type ntype
)
440 struct cmd_node
*cnode
= vector_slot (v
, ntype
);
441 return cnode
->cmd_vector
;
444 /* Utility function for getting command graph. */
445 static struct graph
*
446 cmd_node_graph (vector v
, enum node_type ntype
)
448 struct cmd_node
*cnode
= vector_slot (v
, ntype
);
449 return cnode
->cmdgraph
;
453 cmd_try_do_shortcut (enum node_type node
, char* first_word
) {
454 if ( first_word
!= NULL
&&
457 node
!= AUTH_ENABLE_NODE
&&
458 node
!= ENABLE_NODE
&&
459 node
!= RESTRICTED_NODE
&&
460 0 == strcmp( "do", first_word
) )
466 * Compare function for cmd_token.
467 * Used with qsort to sort command completions.
470 compare_completions (const void *fst
, const void *snd
)
472 struct cmd_token
*first
= *(struct cmd_token
**) fst
,
473 *secnd
= *(struct cmd_token
**) snd
;
474 return strcmp (first
->text
, secnd
->text
);
478 * Takes a list of completions returned by command_complete,
479 * dedeuplicates them based on both text and description,
480 * and returns them as a vector.
483 completions_to_vec (struct list
*completions
)
485 vector comps
= vector_init (VECTOR_MIN_SIZE
);
488 struct cmd_token
*token
;
489 unsigned int i
, exists
;
490 for (ALL_LIST_ELEMENTS_RO(completions
,ln
,token
))
492 // linear search for token in completions vector
494 for (i
= 0; i
< vector_active (comps
) && !exists
; i
++)
496 struct cmd_token
*curr
= vector_slot (comps
, i
);
497 exists
= !strcmp (curr
->text
, token
->text
) &&
498 !strcmp (curr
->desc
, token
->desc
);
502 vector_set (comps
, copy_cmd_token (token
));
507 vector_active (comps
),
509 &compare_completions
);
514 * Generates a vector of cmd_token representing possible completions
515 * on the current input.
517 * @param vline the vectorized input line
518 * @param vty the vty with the node to match on
519 * @param status pointer to matcher status code
522 cmd_complete_command_real (vector vline
, struct vty
*vty
, int *status
)
524 struct list
*completions
;
525 struct graph
*cmdgraph
= cmd_node_graph (cmdvec
, vty
->node
);
527 enum matcher_rv rv
= command_complete (cmdgraph
, vline
, &completions
);
529 if (MATCHER_ERROR(rv
))
533 case MATCHER_AMBIGUOUS
:
534 *status
= CMD_ERR_AMBIGUOUS
;
536 *status
= CMD_ERR_NO_MATCH
;
541 vector comps
= completions_to_vec (completions
);
542 list_delete (completions
);
544 // set status code appropriately
545 switch (vector_active (comps
))
548 *status
= CMD_ERR_NO_MATCH
;
551 *status
= CMD_COMPLETE_FULL_MATCH
;
554 *status
= CMD_COMPLETE_LIST_MATCH
;
561 cmd_describe_command (vector vline
, struct vty
*vty
, int *status
)
565 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
567 enum node_type onode
;
568 vector shifted_vline
;
572 vty
->node
= ENABLE_NODE
;
573 /* We can try it on enable node, cos' the vty is authenticated */
575 shifted_vline
= vector_init (vector_count(vline
));
577 for (index
= 1; index
< vector_active (vline
); index
++)
579 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
582 ret
= cmd_complete_command_real (shifted_vline
, vty
, status
);
584 vector_free(shifted_vline
);
589 return cmd_complete_command_real (vline
, vty
, status
);
593 cmd_complete_command_lib (vector vline
, struct vty
*vty
, int *status
, int islib
)
597 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
599 enum node_type onode
;
600 vector shifted_vline
;
604 vty
->node
= ENABLE_NODE
;
605 /* We can try it on enable node, cos' the vty is authenticated */
607 shifted_vline
= vector_init (vector_count(vline
));
609 for (index
= 1; index
< vector_active (vline
); index
++)
611 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
614 // get token completions
615 vector comps
= cmd_complete_command_real (shifted_vline
, vty
, status
);
616 ret
= XMALLOC (MTYPE_TMP
, vector_active (comps
) * sizeof (char *));
617 for (unsigned int i
= 0; i
< vector_active (comps
); i
++)
619 struct cmd_token
*token
= vector_slot (comps
, i
);
620 ret
[i
] = XSTRDUP (MTYPE_TMP
, token
->text
);
621 vector_unset (comps
, i
);
622 del_cmd_token (token
);
626 vector_free(shifted_vline
);
631 // get token completions
632 vector comps
= cmd_complete_command_real (vline
, vty
, status
);
633 ret
= XMALLOC (MTYPE_TMP
, vector_active (comps
) * sizeof (char *));
634 for (unsigned int i
= 0; i
< vector_active (comps
); i
++)
636 struct cmd_token
*token
= vector_slot (comps
, i
);
637 ret
[i
] = XSTRDUP (MTYPE_TMP
, token
->text
);
638 vector_unset (comps
, i
);
639 del_cmd_token (token
);
647 cmd_complete_command (vector vline
, struct vty
*vty
, int *status
)
649 return cmd_complete_command_lib (vline
, vty
, status
, 0);
652 /* return parent node */
653 /* MUST eventually converge on CONFIG_NODE */
655 node_parent ( enum node_type node
)
659 assert (node
> CONFIG_NODE
);
666 case BGP_ENCAPV6_NODE
:
673 case KEYCHAIN_KEY_NODE
:
676 case LINK_PARAMS_NODE
:
677 ret
= INTERFACE_NODE
;
687 /* Execute command by argument vline vector. */
689 cmd_execute_command_real (vector vline
,
690 enum filter_type filter
,
692 struct cmd_element
**cmd
)
694 struct list
*argv_list
;
695 enum matcher_rv status
;
696 struct graph
*cmdgraph
= cmd_node_graph (cmdvec
, vty
->node
);
697 status
= command_match (cmdgraph
, vline
, &argv_list
, cmd
);
699 // if matcher error, return corresponding CMD_ERR
700 if (MATCHER_ERROR(status
))
703 case MATCHER_INCOMPLETE
:
704 return CMD_ERR_INCOMPLETE
;
705 case MATCHER_AMBIGUOUS
:
706 return CMD_ERR_AMBIGUOUS
;
708 return CMD_ERR_NO_MATCH
;
711 // build argv array from argv list
712 struct cmd_token
**argv
= XMALLOC (MTYPE_TMP
, argv_list
->count
* sizeof (struct cmd_token
*));
714 struct cmd_token
*token
;
716 for (ALL_LIST_ELEMENTS_RO(argv_list
,ln
,token
))
719 int argc
= argv_list
->count
;
723 ret
= CMD_SUCCESS_DAEMON
;
725 ret
= (*cmd
)->func (*cmd
, vty
, argc
, argv
);
727 // delete list and cmd_token's in it
728 list_delete (argv_list
);
734 * Execute a given command, handling things like "do ..." and checking
735 * whether the given command might apply at a parent node if doesn't
736 * apply for the current node.
738 * @param vline Command line input, vector of char* where each element is
740 * @param vty The vty context in which the command should be executed.
741 * @param cmd Pointer where the struct cmd_element of the matched command
742 * will be stored, if any. May be set to NULL if this info is
744 * @param vtysh If set != 0, don't lookup the command at parent nodes.
745 * @return The status of the command that has been executed or an error code
746 * as to why no command could be executed.
749 cmd_execute_command (vector vline
, struct vty
*vty
, struct cmd_element
**cmd
,
751 int ret
, saved_ret
= 0;
752 enum node_type onode
, try_node
;
754 onode
= try_node
= vty
->node
;
756 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
758 vector shifted_vline
;
761 vty
->node
= ENABLE_NODE
;
762 /* We can try it on enable node, cos' the vty is authenticated */
764 shifted_vline
= vector_init (vector_count(vline
));
766 for (index
= 1; index
< vector_active (vline
); index
++)
767 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
769 ret
= cmd_execute_command_real (shifted_vline
, FILTER_RELAXED
, vty
, cmd
);
771 vector_free(shifted_vline
);
777 saved_ret
= ret
= cmd_execute_command_real (vline
, FILTER_RELAXED
, vty
, cmd
);
782 if (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
)
784 /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
785 while (vty
->node
> CONFIG_NODE
)
787 try_node
= node_parent(try_node
);
788 vty
->node
= try_node
;
789 ret
= cmd_execute_command_real (vline
, FILTER_RELAXED
, vty
, cmd
);
790 if (ret
== CMD_SUCCESS
|| ret
== CMD_WARNING
)
793 /* no command succeeded, reset the vty to the original node */
797 /* return command status for original node */
802 * Execute a given command, matching it strictly against the current node.
803 * This mode is used when reading config files.
805 * @param vline Command line input, vector of char* where each element is
807 * @param vty The vty context in which the command should be executed.
808 * @param cmd Pointer where the struct cmd_element* of the matched command
809 * will be stored, if any. May be set to NULL if this info is
811 * @return The status of the command that has been executed or an error code
812 * as to why no command could be executed.
815 cmd_execute_command_strict (vector vline
, struct vty
*vty
,
816 struct cmd_element
**cmd
)
818 return cmd_execute_command_real(vline
, FILTER_STRICT
, vty
, cmd
);
822 * Parse one line of config, walking up the parse tree attempting to find a match
824 * @param vty The vty context in which the command should be executed.
825 * @param cmd Pointer where the struct cmd_element* of the match command
826 * will be stored, if any. May be set to NULL if this info is
828 * @param use_daemon Boolean to control whether or not we match on CMD_SUCCESS_DAEMON
830 * @return The status of the command that has been executed or an error code
831 * as to why no command could be executed.
834 command_config_read_one_line (struct vty
*vty
, struct cmd_element
**cmd
, int use_daemon
)
840 vline
= cmd_make_strvec (vty
->buf
);
842 /* In case of comment line */
846 /* Execute configuration command : this is strict match */
847 ret
= cmd_execute_command_strict (vline
, vty
, cmd
);
849 // Climb the tree and try the command again at each node
850 if (!(use_daemon
&& ret
== CMD_SUCCESS_DAEMON
) &&
851 !(!use_daemon
&& ret
== CMD_ERR_NOTHING_TODO
) &&
852 ret
!= CMD_SUCCESS
&&
853 ret
!= CMD_WARNING
&&
854 vty
->node
!= CONFIG_NODE
) {
856 saved_node
= vty
->node
;
858 while (!(use_daemon
&& ret
== CMD_SUCCESS_DAEMON
) &&
859 !(!use_daemon
&& ret
== CMD_ERR_NOTHING_TODO
) &&
860 ret
!= CMD_SUCCESS
&&
861 ret
!= CMD_WARNING
&&
862 vty
->node
> CONFIG_NODE
) {
863 vty
->node
= node_parent(vty
->node
);
864 ret
= cmd_execute_command_strict (vline
, vty
, cmd
);
867 // If climbing the tree did not work then ignore the command and
868 // stay at the same node
869 if (!(use_daemon
&& ret
== CMD_SUCCESS_DAEMON
) &&
870 !(!use_daemon
&& ret
== CMD_ERR_NOTHING_TODO
) &&
871 ret
!= CMD_SUCCESS
&&
874 vty
->node
= saved_node
;
875 memcpy(vty
->error_buf
, vty
->buf
, VTY_BUFSIZ
);
879 cmd_free_strvec (vline
);
884 /* Configuration make from file. */
886 config_from_file (struct vty
*vty
, FILE *fp
, unsigned int *line_num
)
888 int ret
, error_ret
=0;
891 while (fgets (vty
->buf
, VTY_BUFSIZ
, fp
))
896 ret
= command_config_read_one_line (vty
, NULL
, 0);
898 if (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
&&
899 ret
!= CMD_ERR_NOTHING_TODO
)
910 /* Configuration from terminal */
911 DEFUN (config_terminal
,
913 "configure terminal",
914 "Configuration from vty interface\n"
915 "Configuration terminal\n")
917 if (vty_config_lock (vty
))
918 vty
->node
= CONFIG_NODE
;
921 vty_out (vty
, "VTY configuration is locked by other VTY%s", VTY_NEWLINE
);
931 "Turn on privileged mode command\n")
933 /* If enable password is NULL, change to ENABLE_NODE */
934 if ((host
.enable
== NULL
&& host
.enable_encrypt
== NULL
) ||
935 vty
->type
== VTY_SHELL_SERV
)
936 vty
->node
= ENABLE_NODE
;
938 vty
->node
= AUTH_ENABLE_NODE
;
943 /* Disable command */
947 "Turn off privileged mode command\n")
949 if (vty
->node
== ENABLE_NODE
)
950 vty
->node
= VIEW_NODE
;
954 /* Down vty node level. */
956 * CHECK ME - The following ALIASes need to be implemented in this DEFUN
958 * "Exit current mode and down to previous mode\n"
964 "Exit current mode and down to previous mode\n")
970 case RESTRICTED_NODE
:
974 vty
->status
= VTY_CLOSE
;
977 vty
->node
= ENABLE_NODE
;
978 vty_config_unlock (vty
);
995 vty
->node
= CONFIG_NODE
;
1000 case BGP_VPNV6_NODE
:
1001 case BGP_ENCAP_NODE
:
1002 case BGP_ENCAPV6_NODE
:
1004 case BGP_IPV6M_NODE
:
1005 vty
->node
= BGP_NODE
;
1007 case KEYCHAIN_KEY_NODE
:
1008 vty
->node
= KEYCHAIN_NODE
;
1010 case LINK_PARAMS_NODE
:
1011 vty
->node
= INTERFACE_NODE
;
1019 /* quit is alias of exit. */
1021 /* End of configuration. */
1025 "End current mode and change to enable mode.")
1031 case RESTRICTED_NODE
:
1032 /* Nothing to do. */
1035 case INTERFACE_NODE
:
1042 case BGP_ENCAP_NODE
:
1043 case BGP_ENCAPV6_NODE
:
1044 case BGP_VPNV4_NODE
:
1045 case BGP_VPNV6_NODE
:
1047 case BGP_IPV4M_NODE
:
1049 case BGP_IPV6M_NODE
:
1055 case KEYCHAIN_KEY_NODE
:
1059 case LINK_PARAMS_NODE
:
1060 vty_config_unlock (vty
);
1061 vty
->node
= ENABLE_NODE
;
1070 DEFUN (show_version
,
1074 "Displays zebra version\n")
1076 vty_out (vty
, "Quagga %s (%s).%s", QUAGGA_VERSION
, host
.name
?host
.name
:"",
1078 vty_out (vty
, "%s%s%s", QUAGGA_COPYRIGHT
, GIT_INFO
, VTY_NEWLINE
);
1079 vty_out (vty
, "configured with:%s %s%s", VTY_NEWLINE
,
1080 QUAGGA_CONFIG_ARGS
, VTY_NEWLINE
);
1085 /* Help display function for all node. */
1089 "Description of the interactive help system\n")
1092 "Quagga VTY provides advanced help feature. When you need help,%s\
1093 anytime at the command line please press '?'.%s\
1095 If nothing matches, the help list will be empty and you must backup%s\
1096 until entering a '?' shows the available options.%s\
1097 Two styles of help are provided:%s\
1098 1. Full help is available when you are ready to enter a%s\
1099 command argument (e.g. 'show ?') and describes each possible%s\
1101 2. Partial help is provided when an abbreviated argument is entered%s\
1102 and you want to know what arguments match the input%s\
1103 (e.g. 'show me?'.)%s%s", VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
1104 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
1105 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
1109 /* Help display function for all node. */
1113 "Print command list\n")
1116 struct cmd_node
*cnode
= vector_slot (cmdvec
, vty
->node
);
1117 struct cmd_element
*cmd
;
1119 for (i
= 0; i
< vector_active (cnode
->cmd_vector
); i
++)
1120 if ((cmd
= vector_slot (cnode
->cmd_vector
, i
)) != NULL
1121 && !(cmd
->attr
== CMD_ATTR_DEPRECATED
1122 || cmd
->attr
== CMD_ATTR_HIDDEN
))
1123 vty_out (vty
, " %s%s", cmd
->string
,
1128 /* Write current configuration into file. */
1130 * CHECK ME - The following ALIASes need to be implemented in this DEFUN
1131 * "copy running-config startup-config",
1132 * "Copy configuration\n"
1133 * "Copy running config to... \n"
1134 * "Copy running config to startup config (same as write file)\n"
1136 * "show running-config",
1138 * "running configuration\n"
1141 DEFUN (config_write
,
1143 "write [<file|memory|terminal>]",
1144 "Write running configuration to memory, network, or terminal\n"
1145 "Write to configuration file\n"
1146 "Write configuration currently in memory\n"
1147 "Write configuration to terminal\n")
1151 struct cmd_node
*node
;
1153 char *config_file_tmp
= NULL
;
1154 char *config_file_sav
= NULL
;
1155 int ret
= CMD_WARNING
;
1156 struct vty
*file_vty
;
1157 struct stat conf_stat
;
1159 // if command was 'write terminal' or 'show running-config'
1160 if (argc
== 2 && (!strcmp(argv
[1]->arg
, "terminal") ||
1161 !strcmp(argv
[1]->arg
, "running-config")))
1163 if (vty
->type
== VTY_SHELL_SERV
)
1165 for (i
= 0; i
< vector_active (cmdvec
); i
++)
1166 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
&& node
->vtysh
)
1168 if ((*node
->func
) (vty
))
1169 vty_out (vty
, "!%s", VTY_NEWLINE
);
1174 vty_out (vty
, "%sCurrent configuration:%s", VTY_NEWLINE
,
1176 vty_out (vty
, "!%s", VTY_NEWLINE
);
1178 for (i
= 0; i
< vector_active (cmdvec
); i
++)
1179 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
1181 if ((*node
->func
) (vty
))
1182 vty_out (vty
, "!%s", VTY_NEWLINE
);
1184 vty_out (vty
, "end%s",VTY_NEWLINE
);
1189 /* Check and see if we are operating under vtysh configuration */
1190 if (host
.config
== NULL
)
1192 vty_out (vty
, "Can't save to configuration file, using vtysh.%s",
1198 config_file
= host
.config
;
1201 XMALLOC (MTYPE_TMP
, strlen (config_file
) + strlen (CONF_BACKUP_EXT
) + 1);
1202 strcpy (config_file_sav
, config_file
);
1203 strcat (config_file_sav
, CONF_BACKUP_EXT
);
1206 config_file_tmp
= XMALLOC (MTYPE_TMP
, strlen (config_file
) + 8);
1207 sprintf (config_file_tmp
, "%s.XXXXXX", config_file
);
1209 /* Open file to configuration write. */
1210 fd
= mkstemp (config_file_tmp
);
1213 vty_out (vty
, "Can't open configuration file %s.%s", config_file_tmp
,
1218 /* Make vty for configuration file. */
1219 file_vty
= vty_new ();
1221 file_vty
->type
= VTY_FILE
;
1223 /* Config file header print. */
1224 vty_out (file_vty
, "!\n! Zebra configuration saved from vty\n! ");
1225 vty_time_print (file_vty
, 1);
1226 vty_out (file_vty
, "!\n");
1228 for (i
= 0; i
< vector_active (cmdvec
); i
++)
1229 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
1231 if ((*node
->func
) (file_vty
))
1232 vty_out (file_vty
, "!\n");
1234 vty_close (file_vty
);
1236 if (stat(config_file
, &conf_stat
) >= 0)
1238 if (unlink (config_file_sav
) != 0)
1239 if (errno
!= ENOENT
)
1241 vty_out (vty
, "Can't unlink backup configuration file %s.%s", config_file_sav
,
1245 if (link (config_file
, config_file_sav
) != 0)
1247 vty_out (vty
, "Can't backup old configuration file %s.%s", config_file_sav
,
1252 if (unlink (config_file
) != 0)
1254 vty_out (vty
, "Can't unlink configuration file %s.%s", config_file
,
1259 if (link (config_file_tmp
, config_file
) != 0)
1261 vty_out (vty
, "Can't save configuration file %s.%s", config_file
,
1267 if (chmod (config_file
, CONFIGFILE_MASK
) != 0)
1269 vty_out (vty
, "Can't chmod configuration file %s: %s (%d).%s",
1270 config_file
, safe_strerror(errno
), errno
, VTY_NEWLINE
);
1274 vty_out (vty
, "Configuration saved to %s%s", config_file
,
1279 unlink (config_file_tmp
);
1280 XFREE (MTYPE_TMP
, config_file_tmp
);
1281 XFREE (MTYPE_TMP
, config_file_sav
);
1286 /* Write current configuration into the terminal. */
1288 /* Write startup configuration into the terminal. */
1289 DEFUN (show_startup_config
,
1290 show_startup_config_cmd
,
1291 "show startup-config",
1293 "Contents of startup configuration\n")
1298 confp
= fopen (host
.config
, "r");
1301 vty_out (vty
, "Can't open configuration file [%s] due to '%s'%s",
1302 host
.config
, safe_strerror(errno
), VTY_NEWLINE
);
1306 while (fgets (buf
, BUFSIZ
, confp
))
1310 while (*cp
!= '\r' && *cp
!= '\n' && *cp
!= '\0')
1314 vty_out (vty
, "%s%s", buf
, VTY_NEWLINE
);
1322 /* Hostname configuration */
1323 DEFUN (config_hostname
,
1326 "Set system's network name\n"
1327 "This system's network name\n")
1329 struct cmd_token
*word
= argv
[1];
1331 if (!isalpha((int) word
->arg
[0]))
1333 vty_out (vty
, "Please specify string starting with alphabet%s", VTY_NEWLINE
);
1338 XFREE (MTYPE_HOST
, host
.name
);
1340 host
.name
= XSTRDUP (MTYPE_HOST
, word
->arg
);
1344 DEFUN (config_no_hostname
,
1346 "no hostname [HOSTNAME]",
1348 "Reset system's network name\n"
1349 "Host name of this router\n")
1352 XFREE (MTYPE_HOST
, host
.name
);
1357 /* VTY interface password set. */
1358 DEFUN (config_password
,
1360 "password [8] WORD",
1361 "Assign the terminal connection password\n"
1362 "Specifies a HIDDEN password will follow\n"
1363 "The password string\n")
1365 if (argc
== 3) // '8' was specified
1368 XFREE (MTYPE_HOST
, host
.password
);
1369 host
.password
= NULL
;
1370 if (host
.password_encrypt
)
1371 XFREE (MTYPE_HOST
, host
.password_encrypt
);
1372 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[2]->arg
);
1376 if (!isalnum (argv
[1]->arg
[0]))
1379 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
1384 XFREE (MTYPE_HOST
, host
.password
);
1385 host
.password
= NULL
;
1389 if (host
.password_encrypt
)
1390 XFREE (MTYPE_HOST
, host
.password_encrypt
);
1391 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[1]->arg
));
1394 host
.password
= XSTRDUP (MTYPE_HOST
, argv
[1]->arg
);
1399 /* VTY enable password set. */
1400 DEFUN (config_enable_password
,
1401 enable_password_cmd
,
1402 "enable password [8] WORD",
1403 "Modify enable password parameters\n"
1404 "Assign the privileged level password\n"
1405 "Specifies a HIDDEN password will follow\n"
1407 "The HIDDEN 'enable' password string\n")
1409 /* Crypt type is specified. */
1412 if (argv
[2]->arg
[0] == '8')
1415 XFREE (MTYPE_HOST
, host
.enable
);
1418 if (host
.enable_encrypt
)
1419 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
1420 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[3]->arg
);
1426 vty_out (vty
, "Unknown encryption type.%s", VTY_NEWLINE
);
1431 if (!isalnum (argv
[2]->arg
[0]))
1434 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
1439 XFREE (MTYPE_HOST
, host
.enable
);
1442 /* Plain password input. */
1445 if (host
.enable_encrypt
)
1446 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
1447 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[2]->arg
));
1450 host
.enable
= XSTRDUP (MTYPE_HOST
, argv
[2]->arg
);
1455 /* VTY enable password delete. */
1456 DEFUN (no_config_enable_password
,
1457 no_enable_password_cmd
,
1458 "no enable password",
1460 "Modify enable password parameters\n"
1461 "Assign the privileged level password\n")
1464 XFREE (MTYPE_HOST
, host
.enable
);
1467 if (host
.enable_encrypt
)
1468 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
1469 host
.enable_encrypt
= NULL
;
1474 DEFUN (service_password_encrypt
,
1475 service_password_encrypt_cmd
,
1476 "service password-encryption",
1477 "Set up miscellaneous service\n"
1478 "Enable encrypted passwords\n")
1487 if (host
.password_encrypt
)
1488 XFREE (MTYPE_HOST
, host
.password_encrypt
);
1489 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.password
));
1493 if (host
.enable_encrypt
)
1494 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
1495 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.enable
));
1501 DEFUN (no_service_password_encrypt
,
1502 no_service_password_encrypt_cmd
,
1503 "no service password-encryption",
1505 "Set up miscellaneous service\n"
1506 "Enable encrypted passwords\n")
1513 if (host
.password_encrypt
)
1514 XFREE (MTYPE_HOST
, host
.password_encrypt
);
1515 host
.password_encrypt
= NULL
;
1517 if (host
.enable_encrypt
)
1518 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
1519 host
.enable_encrypt
= NULL
;
1524 DEFUN (config_terminal_length
,
1525 config_terminal_length_cmd
,
1526 "terminal length (0-512)",
1527 "Set terminal line parameters\n"
1528 "Set number of lines on a screen\n"
1529 "Number of lines on screen (0 for no pausing)\n")
1532 char *endptr
= NULL
;
1534 lines
= strtol (argv
[2]->arg
, &endptr
, 10);
1535 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
1537 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
1545 DEFUN (config_terminal_no_length
,
1546 config_terminal_no_length_cmd
,
1547 "terminal no length",
1548 "Set terminal line parameters\n"
1550 "Set number of lines on a screen\n")
1556 DEFUN (service_terminal_length
,
1557 service_terminal_length_cmd
,
1558 "service terminal-length (0-512)",
1559 "Set up miscellaneous service\n"
1560 "System wide terminal length configuration\n"
1561 "Number of lines of VTY (0 means no line control)\n")
1564 char *endptr
= NULL
;
1566 lines
= strtol (argv
[2]->arg
, &endptr
, 10);
1567 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
1569 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
1577 DEFUN (no_service_terminal_length
,
1578 no_service_terminal_length_cmd
,
1579 "no service terminal-length [(0-512)]",
1581 "Set up miscellaneous service\n"
1582 "System wide terminal length configuration\n"
1583 "Number of lines of VTY (0 means no line control)\n")
1589 DEFUN_HIDDEN (do_echo
,
1592 "Echo a message back to the vty\n"
1593 "The message to echo\n")
1597 vty_out (vty
, "%s%s", ((message
= argv_concat (argv
, argc
, 0)) ? message
: ""),
1600 XFREE(MTYPE_TMP
, message
);
1604 DEFUN (config_logmsg
,
1606 "logmsg "LOG_LEVELS
" MESSAGE...",
1607 "Send a message to enabled logging destinations\n"
1609 "The message to send\n")
1614 if ((level
= level_match(argv
[1]->arg
)) == ZLOG_DISABLED
)
1615 return CMD_ERR_NO_MATCH
;
1617 zlog(NULL
, level
, "%s", ((message
= argv_concat(argv
, argc
, 1)) ? message
: ""));
1619 XFREE(MTYPE_TMP
, message
);
1623 DEFUN (show_logging
,
1627 "Show current logging configuration\n")
1629 struct zlog
*zl
= zlog_default
;
1631 vty_out (vty
, "Syslog logging: ");
1632 if (zl
->maxlvl
[ZLOG_DEST_SYSLOG
] == ZLOG_DISABLED
)
1633 vty_out (vty
, "disabled");
1635 vty_out (vty
, "level %s, facility %s, ident %s",
1636 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_SYSLOG
]],
1637 facility_name(zl
->facility
), zl
->ident
);
1638 vty_out (vty
, "%s", VTY_NEWLINE
);
1640 vty_out (vty
, "Stdout logging: ");
1641 if (zl
->maxlvl
[ZLOG_DEST_STDOUT
] == ZLOG_DISABLED
)
1642 vty_out (vty
, "disabled");
1644 vty_out (vty
, "level %s",
1645 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_STDOUT
]]);
1646 vty_out (vty
, "%s", VTY_NEWLINE
);
1648 vty_out (vty
, "Monitor logging: ");
1649 if (zl
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
1650 vty_out (vty
, "disabled");
1652 vty_out (vty
, "level %s",
1653 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_MONITOR
]]);
1654 vty_out (vty
, "%s", VTY_NEWLINE
);
1656 vty_out (vty
, "File logging: ");
1657 if ((zl
->maxlvl
[ZLOG_DEST_FILE
] == ZLOG_DISABLED
) ||
1659 vty_out (vty
, "disabled");
1661 vty_out (vty
, "level %s, filename %s",
1662 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_FILE
]],
1664 vty_out (vty
, "%s", VTY_NEWLINE
);
1666 vty_out (vty
, "Protocol name: %s%s",
1667 zlog_proto_names
[zl
->protocol
], VTY_NEWLINE
);
1668 vty_out (vty
, "Record priority: %s%s",
1669 (zl
->record_priority
? "enabled" : "disabled"), VTY_NEWLINE
);
1670 vty_out (vty
, "Timestamp precision: %d%s",
1671 zl
->timestamp_precision
, VTY_NEWLINE
);
1676 DEFUN (config_log_stdout
,
1677 config_log_stdout_cmd
,
1678 "log stdout ["LOG_LEVELS
"]",
1680 "Set stdout logging level\n"
1685 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, zlog_default
->default_lvl
);
1690 if ((level
= level_match(argv
[2]->arg
)) == ZLOG_DISABLED
)
1691 return CMD_ERR_NO_MATCH
;
1692 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, level
);
1696 DEFUN (no_config_log_stdout
,
1697 no_config_log_stdout_cmd
,
1698 "no log stdout ["LOG_LEVELS
"]",
1701 "Cancel logging to stdout\n"
1704 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, ZLOG_DISABLED
);
1708 DEFUN (config_log_monitor
,
1709 config_log_monitor_cmd
,
1710 "log monitor ["LOG_LEVELS
"]",
1712 "Set terminal line (monitor) logging level\n"
1717 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, zlog_default
->default_lvl
);
1722 if ((level
= level_match(argv
[2]->arg
)) == ZLOG_DISABLED
)
1723 return CMD_ERR_NO_MATCH
;
1724 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, level
);
1728 DEFUN (no_config_log_monitor
,
1729 no_config_log_monitor_cmd
,
1730 "no log monitor ["LOG_LEVELS
"]",
1733 "Disable terminal line (monitor) logging\n"
1736 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, ZLOG_DISABLED
);
1741 set_log_file(struct vty
*vty
, const char *fname
, int loglevel
)
1745 const char *fullpath
;
1747 /* Path detection. */
1748 if (! IS_DIRECTORY_SEP (*fname
))
1750 char cwd
[MAXPATHLEN
+1];
1751 cwd
[MAXPATHLEN
] = '\0';
1753 if (getcwd (cwd
, MAXPATHLEN
) == NULL
)
1755 zlog_err ("config_log_file: Unable to alloc mem!");
1759 if ( (p
= XMALLOC (MTYPE_TMP
, strlen (cwd
) + strlen (fname
) + 2))
1762 zlog_err ("config_log_file: Unable to alloc mem!");
1765 sprintf (p
, "%s/%s", cwd
, fname
);
1771 ret
= zlog_set_file (NULL
, fullpath
, loglevel
);
1774 XFREE (MTYPE_TMP
, p
);
1778 vty_out (vty
, "can't open logfile %s\n", fname
);
1783 XFREE (MTYPE_HOST
, host
.logfile
);
1785 host
.logfile
= XSTRDUP (MTYPE_HOST
, fname
);
1787 #if defined(HAVE_CUMULUS)
1788 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != ZLOG_DISABLED
)
1789 zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] = ZLOG_DISABLED
;
1794 DEFUN (config_log_file
,
1795 config_log_file_cmd
,
1796 "log file FILENAME [" LOG_LEVELS
"]",
1799 "Logging filename\n"
1805 if ((level
= level_match(argv
[3]->arg
)) == ZLOG_DISABLED
)
1806 return CMD_ERR_NO_MATCH
;
1807 return set_log_file(vty
, argv
[2]->arg
, level
);
1810 return set_log_file(vty
, argv
[2]->arg
, zlog_default
->default_lvl
);
1813 DEFUN (no_config_log_file
,
1814 no_config_log_file_cmd
,
1815 "no log file [FILENAME [LEVEL]]",
1818 "Cancel logging to file\n"
1819 "Logging file name\n"
1820 "Logging file name\n"
1823 zlog_reset_file (NULL
);
1826 XFREE (MTYPE_HOST
, host
.logfile
);
1828 host
.logfile
= NULL
;
1833 DEFUN (config_log_syslog
,
1834 config_log_syslog_cmd
,
1835 "log syslog [" LOG_LEVELS
"]",
1837 "Set syslog logging level\n"
1843 if ((level
= level_match (argv
[2]->arg
)) == ZLOG_DISABLED
)
1844 return CMD_ERR_NO_MATCH
;
1845 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, level
);
1850 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
1855 DEFUN_DEPRECATED (config_log_syslog_facility
,
1856 config_log_syslog_facility_cmd
,
1857 "log syslog facility "LOG_FACILITIES
,
1859 "Logging goes to syslog\n"
1860 "(Deprecated) Facility parameter for syslog messages\n"
1863 int facility
= facility_match(argv
[3]->arg
);
1865 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
1866 zlog_default
->facility
= facility
;
1870 DEFUN (no_config_log_syslog
,
1871 no_config_log_syslog_cmd
,
1872 "no log syslog [" LOG_FACILITIES
"] [" LOG_LEVELS
"]",
1875 "Cancel logging to syslog\n"
1879 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, ZLOG_DISABLED
);
1883 DEFUN (config_log_facility
,
1884 config_log_facility_cmd
,
1885 "log facility " LOG_FACILITIES
,
1887 "Facility parameter for syslog messages\n"
1890 int facility
= facility_match(argv
[2]->arg
);
1892 zlog_default
->facility
= facility
;
1896 DEFUN (no_config_log_facility
,
1897 no_config_log_facility_cmd
,
1898 "no log facility [" LOG_FACILITIES
"]",
1901 "Reset syslog facility to default (daemon)\n"
1904 zlog_default
->facility
= LOG_DAEMON
;
1908 DEFUN_DEPRECATED (config_log_trap
,
1909 config_log_trap_cmd
,
1910 "log trap " LOG_LEVELS
,
1912 "(Deprecated) Set logging level and default for all destinations\n"
1918 if ((new_level
= level_match(argv
[2]->arg
)) == ZLOG_DISABLED
)
1919 return CMD_ERR_NO_MATCH
;
1921 zlog_default
->default_lvl
= new_level
;
1922 for (i
= 0; i
< ZLOG_NUM_DESTS
; i
++)
1923 if (zlog_default
->maxlvl
[i
] != ZLOG_DISABLED
)
1924 zlog_default
->maxlvl
[i
] = new_level
;
1928 DEFUN_DEPRECATED (no_config_log_trap
,
1929 no_config_log_trap_cmd
,
1930 "no log trap [" LOG_LEVELS
"]",
1933 "Permit all logging information\n"
1936 zlog_default
->default_lvl
= LOG_DEBUG
;
1940 DEFUN (config_log_record_priority
,
1941 config_log_record_priority_cmd
,
1942 "log record-priority",
1944 "Log the priority of the message within the message\n")
1946 zlog_default
->record_priority
= 1 ;
1950 DEFUN (no_config_log_record_priority
,
1951 no_config_log_record_priority_cmd
,
1952 "no log record-priority",
1955 "Do not log the priority of the message within the message\n")
1957 zlog_default
->record_priority
= 0 ;
1961 DEFUN (config_log_timestamp_precision
,
1962 config_log_timestamp_precision_cmd
,
1963 "log timestamp precision (0-6)",
1965 "Timestamp configuration\n"
1966 "Set the timestamp precision\n"
1967 "Number of subsecond digits\n")
1969 VTY_GET_INTEGER_RANGE("Timestamp Precision",
1970 zlog_default
->timestamp_precision
, argv
[3]->arg
, 0, 6);
1974 DEFUN (no_config_log_timestamp_precision
,
1975 no_config_log_timestamp_precision_cmd
,
1976 "no log timestamp precision",
1979 "Timestamp configuration\n"
1980 "Reset the timestamp precision to the default value of 0\n")
1982 zlog_default
->timestamp_precision
= 0 ;
1987 cmd_banner_motd_file (const char *file
)
1989 int success
= CMD_SUCCESS
;
1994 rpath
= realpath (file
, p
);
1996 return CMD_ERR_NO_FILE
;
1997 in
= strstr (rpath
, SYSCONFDIR
);
2001 XFREE (MTYPE_HOST
, host
.motdfile
);
2002 host
.motdfile
= XSTRDUP (MTYPE_HOST
, file
);
2005 success
= CMD_WARNING
;
2010 DEFUN (banner_motd_file
,
2011 banner_motd_file_cmd
,
2012 "banner motd file FILE",
2015 "Banner from a file\n"
2018 const char *filename
= argv
[3]->arg
;
2019 int cmd
= cmd_banner_motd_file (filename
);
2021 if (cmd
== CMD_ERR_NO_FILE
)
2022 vty_out (vty
, "%s does not exist", filename
);
2023 else if (cmd
== CMD_WARNING
)
2024 vty_out (vty
, "%s must be in %s", filename
, SYSCONFDIR
);
2029 DEFUN (banner_motd_default
,
2030 banner_motd_default_cmd
,
2031 "banner motd default",
2032 "Set banner string\n"
2033 "Strings for motd\n"
2036 host
.motd
= default_motd
;
2040 DEFUN (no_banner_motd
,
2044 "Set banner string\n"
2045 "Strings for motd\n")
2049 XFREE (MTYPE_HOST
, host
.motdfile
);
2050 host
.motdfile
= NULL
;
2054 DEFUN (show_commandtree
,
2055 show_commandtree_cmd
,
2058 "Show command tree\n")
2064 vty_out (vty
, "Current node id: %d%s", vty
->node
, VTY_NEWLINE
);
2066 /* vector of all commands installed at this node */
2067 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
2069 /* loop over all commands at this node */
2070 for (i
= 0; i
< vector_active(cmd_vector
); ++i
)
2072 struct cmd_element
*cmd_element
;
2074 /* A cmd_element (seems to be) is an individual command */
2075 if ((cmd_element
= vector_slot (cmd_vector
, i
)) == NULL
)
2078 vty_out (vty
, " %s%s", cmd_element
->string
, VTY_NEWLINE
);
2081 vector_free (cmd_vector
);
2085 /* Set config filename. Called from vty.c */
2087 host_config_set (const char *filename
)
2090 XFREE (MTYPE_HOST
, host
.config
);
2091 host
.config
= XSTRDUP (MTYPE_HOST
, filename
);
2095 install_default (enum node_type node
)
2097 install_element (node
, &config_exit_cmd
);
2098 install_element (node
, &config_end_cmd
);
2099 install_element (node
, &config_help_cmd
);
2100 install_element (node
, &config_list_cmd
);
2102 install_element (node
, &config_write_cmd
);
2105 /* Initialize command interface. Install basic nodes and commands. */
2107 cmd_init (int terminal
)
2109 /* Allocate initial top vector of commands. */
2110 cmdvec
= vector_init (VECTOR_MIN_SIZE
);
2112 /* Default host value settings. */
2114 host
.password
= NULL
;
2116 host
.logfile
= NULL
;
2119 host
.motd
= default_motd
;
2120 host
.motdfile
= NULL
;
2122 /* Install top nodes. */
2123 install_node (&view_node
, NULL
);
2124 install_node (&enable_node
, NULL
);
2125 install_node (&auth_node
, NULL
);
2126 install_node (&auth_enable_node
, NULL
);
2127 install_node (&restricted_node
, NULL
);
2128 install_node (&config_node
, config_write_host
);
2130 /* Each node's basic commands. */
2131 install_element (VIEW_NODE
, &show_version_cmd
);
2134 install_element (VIEW_NODE
, &config_list_cmd
);
2135 install_element (VIEW_NODE
, &config_exit_cmd
);
2136 install_element (VIEW_NODE
, &config_help_cmd
);
2137 install_element (VIEW_NODE
, &config_enable_cmd
);
2138 install_element (VIEW_NODE
, &config_terminal_length_cmd
);
2139 install_element (VIEW_NODE
, &config_terminal_no_length_cmd
);
2140 install_element (VIEW_NODE
, &show_logging_cmd
);
2141 install_element (VIEW_NODE
, &show_commandtree_cmd
);
2142 install_element (VIEW_NODE
, &echo_cmd
);
2144 install_element (RESTRICTED_NODE
, &config_list_cmd
);
2145 install_element (RESTRICTED_NODE
, &config_exit_cmd
);
2146 install_element (RESTRICTED_NODE
, &config_help_cmd
);
2147 install_element (RESTRICTED_NODE
, &config_enable_cmd
);
2148 install_element (RESTRICTED_NODE
, &config_terminal_length_cmd
);
2149 install_element (RESTRICTED_NODE
, &config_terminal_no_length_cmd
);
2150 install_element (RESTRICTED_NODE
, &echo_cmd
);
2155 install_default (ENABLE_NODE
);
2156 install_element (ENABLE_NODE
, &config_disable_cmd
);
2157 install_element (ENABLE_NODE
, &config_terminal_cmd
);
2159 install_element (ENABLE_NODE
, &show_startup_config_cmd
);
2160 install_element (ENABLE_NODE
, &show_version_cmd
);
2161 install_element (ENABLE_NODE
, &show_commandtree_cmd
);
2165 install_element (ENABLE_NODE
, &config_terminal_length_cmd
);
2166 install_element (ENABLE_NODE
, &config_terminal_no_length_cmd
);
2167 install_element (ENABLE_NODE
, &show_logging_cmd
);
2168 install_element (ENABLE_NODE
, &echo_cmd
);
2169 install_element (ENABLE_NODE
, &config_logmsg_cmd
);
2171 install_default (CONFIG_NODE
);
2174 install_element (CONFIG_NODE
, &hostname_cmd
);
2175 install_element (CONFIG_NODE
, &no_hostname_cmd
);
2179 install_element (CONFIG_NODE
, &password_cmd
);
2180 install_element (CONFIG_NODE
, &enable_password_cmd
);
2181 install_element (CONFIG_NODE
, &no_enable_password_cmd
);
2183 install_element (CONFIG_NODE
, &config_log_stdout_cmd
);
2184 install_element (CONFIG_NODE
, &no_config_log_stdout_cmd
);
2185 install_element (CONFIG_NODE
, &config_log_monitor_cmd
);
2186 install_element (CONFIG_NODE
, &no_config_log_monitor_cmd
);
2187 install_element (CONFIG_NODE
, &config_log_file_cmd
);
2188 install_element (CONFIG_NODE
, &no_config_log_file_cmd
);
2189 install_element (CONFIG_NODE
, &config_log_syslog_cmd
);
2190 install_element (CONFIG_NODE
, &no_config_log_syslog_cmd
);
2191 install_element (CONFIG_NODE
, &config_log_facility_cmd
);
2192 install_element (CONFIG_NODE
, &no_config_log_facility_cmd
);
2193 install_element (CONFIG_NODE
, &config_log_trap_cmd
);
2194 install_element (CONFIG_NODE
, &no_config_log_trap_cmd
);
2195 install_element (CONFIG_NODE
, &config_log_record_priority_cmd
);
2196 install_element (CONFIG_NODE
, &no_config_log_record_priority_cmd
);
2197 install_element (CONFIG_NODE
, &config_log_timestamp_precision_cmd
);
2198 install_element (CONFIG_NODE
, &no_config_log_timestamp_precision_cmd
);
2199 install_element (CONFIG_NODE
, &service_password_encrypt_cmd
);
2200 install_element (CONFIG_NODE
, &no_service_password_encrypt_cmd
);
2201 install_element (CONFIG_NODE
, &banner_motd_default_cmd
);
2202 install_element (CONFIG_NODE
, &banner_motd_file_cmd
);
2203 install_element (CONFIG_NODE
, &no_banner_motd_cmd
);
2204 install_element (CONFIG_NODE
, &service_terminal_length_cmd
);
2205 install_element (CONFIG_NODE
, &no_service_terminal_length_cmd
);
2207 install_element (VIEW_NODE
, &show_thread_cpu_cmd
);
2208 install_element (ENABLE_NODE
, &show_thread_cpu_cmd
);
2209 install_element (RESTRICTED_NODE
, &show_thread_cpu_cmd
);
2211 install_element (ENABLE_NODE
, &clear_thread_cpu_cmd
);
2212 install_element (VIEW_NODE
, &show_work_queues_cmd
);
2213 install_element (ENABLE_NODE
, &show_work_queues_cmd
);
2215 vrf_install_commands ();
2217 srandom(time(NULL
));
2221 new_cmd_token (enum cmd_token_type type
, char *text
, char *desc
)
2223 struct cmd_token
*token
= XMALLOC (MTYPE_CMD_TOKENS
, sizeof (struct cmd_token
));
2233 del_cmd_token (struct cmd_token
*token
)
2248 copy_cmd_token (struct cmd_token
*token
)
2250 struct cmd_token
*copy
= new_cmd_token (token
->type
, NULL
, NULL
);
2251 copy
->max
= token
->max
;
2252 copy
->min
= token
->min
;
2253 copy
->text
= token
->text
? XSTRDUP (MTYPE_CMD_TOKENS
, token
->text
) : NULL
;
2254 copy
->desc
= token
->desc
? XSTRDUP (MTYPE_CMD_TOKENS
, token
->desc
) : NULL
;
2255 copy
->arg
= token
->arg
? XSTRDUP (MTYPE_CMD_TOKENS
, token
->arg
) : NULL
;
2261 del_cmd_element(struct cmd_element
*cmd
)
2264 free ((char *) cmd
->string
);
2265 free ((char *) cmd
->doc
);
2269 struct cmd_element
*
2270 copy_cmd_element(struct cmd_element
*cmd
)
2272 struct cmd_element
*el
= XMALLOC(MTYPE_CMD_TOKENS
, sizeof (struct cmd_element
));
2273 el
->string
= cmd
->string
? XSTRDUP(MTYPE_CMD_TOKENS
, cmd
->string
) : NULL
;
2274 el
->func
= cmd
->func
;
2275 el
->doc
= cmd
->doc
? XSTRDUP(MTYPE_CMD_TOKENS
, cmd
->doc
) : NULL
;
2276 el
->daemon
= cmd
->daemon
;
2277 el
->attr
= cmd
->attr
;
2284 struct cmd_node
*cmd_node
;
2288 for (unsigned int i
= 0; i
< vector_active (cmdvec
); i
++)
2289 if ((cmd_node
= vector_slot (cmdvec
, i
)) != NULL
)
2291 // deleting the graph delets the cmd_element as well
2292 graph_delete_graph (cmd_node
->cmdgraph
);
2293 vector_free (cmd_node
->cmd_vector
);
2296 vector_free (cmdvec
);
2301 XFREE (MTYPE_HOST
, host
.name
);
2303 XFREE (MTYPE_HOST
, host
.password
);
2304 if (host
.password_encrypt
)
2305 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2307 XFREE (MTYPE_HOST
, host
.enable
);
2308 if (host
.enable_encrypt
)
2309 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2311 XFREE (MTYPE_HOST
, host
.logfile
);
2313 XFREE (MTYPE_HOST
, host
.motdfile
);
2315 XFREE (MTYPE_HOST
, host
.config
);