4 Command interpreter routine for virtual terminal [aka TeletYpe]
5 Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
7 This file is part of GNU Zebra.
9 GNU Zebra is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 2, or (at your
12 option) any later version.
14 GNU Zebra is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Zebra; see the file COPYING. If not, write to the
21 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
29 #include <lib/version.h>
34 #include "workqueue.h"
36 /* Command vector which includes some level of command lists. Normally
37 each daemon maintains each own cmdvec. */
40 /* Host information structure. */
43 /* Standard command node structures. */
44 struct cmd_node auth_node
=
50 struct cmd_node view_node
=
56 struct cmd_node restricted_node
=
62 struct cmd_node auth_enable_node
=
68 struct cmd_node enable_node
=
74 struct cmd_node config_node
=
81 /* Default motd string. */
82 const char *default_motd
=
84 Hello, this is " QUAGGA_PROGNAME
" (version " QUAGGA_VERSION
").\r\n\
85 " QUAGGA_COPYRIGHT
"\r\n\
89 static struct facility_map
{
93 } syslog_facilities
[] =
95 { LOG_KERN
, "kern", 1 },
96 { LOG_USER
, "user", 2 },
97 { LOG_MAIL
, "mail", 1 },
98 { LOG_DAEMON
, "daemon", 1 },
99 { LOG_AUTH
, "auth", 1 },
100 { LOG_SYSLOG
, "syslog", 1 },
101 { LOG_LPR
, "lpr", 2 },
102 { LOG_NEWS
, "news", 1 },
103 { LOG_UUCP
, "uucp", 2 },
104 { LOG_CRON
, "cron", 1 },
106 { LOG_FTP
, "ftp", 1 },
108 { LOG_LOCAL0
, "local0", 6 },
109 { LOG_LOCAL1
, "local1", 6 },
110 { LOG_LOCAL2
, "local2", 6 },
111 { LOG_LOCAL3
, "local3", 6 },
112 { LOG_LOCAL4
, "local4", 6 },
113 { LOG_LOCAL5
, "local5", 6 },
114 { LOG_LOCAL6
, "local6", 6 },
115 { LOG_LOCAL7
, "local7", 6 },
120 facility_name(int facility
)
122 struct facility_map
*fm
;
124 for (fm
= syslog_facilities
; fm
->name
; fm
++)
125 if (fm
->facility
== facility
)
131 facility_match(const char *str
)
133 struct facility_map
*fm
;
135 for (fm
= syslog_facilities
; fm
->name
; fm
++)
136 if (!strncmp(str
,fm
->name
,fm
->match
))
142 level_match(const char *s
)
146 for ( level
= 0 ; zlog_priority
[level
] != NULL
; level
++ )
147 if (!strncmp (s
, zlog_priority
[level
], 2))
149 return ZLOG_DISABLED
;
152 /* This is called from main when a daemon is invoked with -v or --version. */
154 print_version (const char *progname
)
156 printf ("%s version %s\n", progname
, QUAGGA_VERSION
);
157 printf ("%s\n", QUAGGA_COPYRIGHT
);
161 /* Utility function to concatenate argv argument into a single string
162 with inserting ' ' character between each argument. */
164 argv_concat (const char **argv
, int argc
, int shift
)
172 for (i
= shift
; i
< argc
; i
++)
173 len
+= strlen(argv
[i
])+1;
176 p
= str
= XMALLOC(MTYPE_TMP
, len
);
177 for (i
= shift
; i
< argc
; i
++)
180 memcpy(p
, argv
[i
], (arglen
= strlen(argv
[i
])));
188 /* Install top node of command vector. */
190 install_node (struct cmd_node
*node
,
191 int (*func
) (struct vty
*))
193 vector_set_index (cmdvec
, node
->node
, node
);
195 node
->cmd_vector
= vector_init (VECTOR_MIN_SIZE
);
198 /* Compare two command's string. Used in sort_node (). */
200 cmp_node (const void *p
, const void *q
)
202 const struct cmd_element
*a
= *(struct cmd_element
**)p
;
203 const struct cmd_element
*b
= *(struct cmd_element
**)q
;
205 return strcmp (a
->string
, b
->string
);
209 cmp_desc (const void *p
, const void *q
)
211 const struct desc
*a
= *(struct desc
**)p
;
212 const struct desc
*b
= *(struct desc
**)q
;
214 return strcmp (a
->cmd
, b
->cmd
);
217 /* Sort each node's command element according to command string. */
222 struct cmd_node
*cnode
;
224 struct cmd_element
*cmd_element
;
226 for (i
= 0; i
< vector_active (cmdvec
); i
++)
227 if ((cnode
= vector_slot (cmdvec
, i
)) != NULL
)
229 vector cmd_vector
= cnode
->cmd_vector
;
230 qsort (cmd_vector
->index
, vector_active (cmd_vector
),
231 sizeof (void *), cmp_node
);
233 for (j
= 0; j
< vector_active (cmd_vector
); j
++)
234 if ((cmd_element
= vector_slot (cmd_vector
, j
)) != NULL
235 && vector_active (cmd_element
->strvec
))
237 descvec
= vector_slot (cmd_element
->strvec
,
238 vector_active (cmd_element
->strvec
) - 1);
239 qsort (descvec
->index
, vector_active (descvec
),
240 sizeof (void *), cmp_desc
);
245 /* Breaking up string into each command piece. I assume given
246 character is separated by a space character. Return value is a
247 vector which includes char ** data element. */
249 cmd_make_strvec (const char *string
)
251 const char *cp
, *start
;
261 /* Skip white spaces. */
262 while (isspace ((int) *cp
) && *cp
!= '\0')
265 /* Return if there is only white spaces */
269 if (*cp
== '!' || *cp
== '#')
272 /* Prepare return vector. */
273 strvec
= vector_init (VECTOR_MIN_SIZE
);
275 /* Copy each command piece and set into vector. */
279 while (!(isspace ((int) *cp
) || *cp
== '\r' || *cp
== '\n') &&
283 token
= XMALLOC (MTYPE_STRVEC
, strlen
+ 1);
284 memcpy (token
, start
, strlen
);
285 *(token
+ strlen
) = '\0';
286 vector_set (strvec
, token
);
288 while ((isspace ((int) *cp
) || *cp
== '\n' || *cp
== '\r') &&
297 /* Free allocated string vector. */
299 cmd_free_strvec (vector v
)
307 for (i
= 0; i
< vector_active (v
); i
++)
308 if ((cp
= vector_slot (v
, i
)) != NULL
)
309 XFREE (MTYPE_STRVEC
, cp
);
314 /* Fetch next description. Used in cmd_make_descvec(). */
316 cmd_desc_str (const char **string
)
318 const char *cp
, *start
;
327 /* Skip white spaces. */
328 while (isspace ((int) *cp
) && *cp
!= '\0')
331 /* Return if there is only white spaces */
337 while (!(*cp
== '\r' || *cp
== '\n') && *cp
!= '\0')
341 token
= XMALLOC (MTYPE_STRVEC
, strlen
+ 1);
342 memcpy (token
, start
, strlen
);
343 *(token
+ strlen
) = '\0';
350 /* New string vector. */
352 cmd_make_descvec (const char *string
, const char *descstr
)
361 vector strvec
= NULL
;
370 allvec
= vector_init (VECTOR_MIN_SIZE
);
374 while (isspace ((int) *cp
) && *cp
!= '\0')
391 fprintf (stderr
, "Command parse error!: %s\n", string
);
397 while (isspace ((int) *cp
) && *cp
!= '\0')
411 while (! (isspace ((int) *cp
) || *cp
== '\r' || *cp
== '\n' || *cp
== ')' || *cp
== '|') && *cp
!= '\0')
416 token
= XMALLOC (MTYPE_STRVEC
, len
+ 1);
417 memcpy (token
, sp
, len
);
418 *(token
+ len
) = '\0';
420 desc
= XCALLOC (MTYPE_DESC
, sizeof (struct desc
));
422 desc
->str
= cmd_desc_str (&dp
);
428 strvec
= vector_init (VECTOR_MIN_SIZE
);
429 vector_set (allvec
, strvec
);
435 strvec
= vector_init (VECTOR_MIN_SIZE
);
436 vector_set (allvec
, strvec
);
438 vector_set (strvec
, desc
);
442 /* Count mandantory string vector size. This is to determine inputed
443 command has enough command length. */
445 cmd_cmdsize (vector strvec
)
452 for (i
= 0; i
< vector_active (strvec
); i
++)
453 if ((descvec
= vector_slot (strvec
, i
)) != NULL
)
455 if ((vector_active (descvec
)) == 1
456 && (desc
= vector_slot (descvec
, 0)) != NULL
)
458 if (desc
->cmd
== NULL
|| CMD_OPTION (desc
->cmd
))
469 /* Return prompt character of specified node. */
471 cmd_prompt (enum node_type node
)
473 struct cmd_node
*cnode
;
475 cnode
= vector_slot (cmdvec
, node
);
476 return cnode
->prompt
;
479 /* Install a command into a node. */
481 install_element (enum node_type ntype
, struct cmd_element
*cmd
)
483 struct cmd_node
*cnode
;
485 /* cmd_init hasn't been called */
489 cnode
= vector_slot (cmdvec
, ntype
);
493 fprintf (stderr
, "Command node %d doesn't exist, please check it\n",
498 vector_set (cnode
->cmd_vector
, cmd
);
500 cmd
->strvec
= cmd_make_descvec (cmd
->string
, cmd
->doc
);
501 cmd
->cmdsize
= cmd_cmdsize (cmd
->strvec
);
504 static unsigned char itoa64
[] =
505 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
508 to64(char *s
, long v
, int n
)
512 *s
++ = itoa64
[v
&0x3f];
518 zencrypt (const char *passwd
)
522 char *crypt (const char *, const char *);
526 to64(&salt
[0], random(), 3);
527 to64(&salt
[3], tv
.tv_usec
, 3);
530 return crypt (passwd
, salt
);
533 /* This function write configuration of this host. */
535 config_write_host (struct vty
*vty
)
538 vty_out (vty
, "hostname %s%s", host
.name
, VTY_NEWLINE
);
542 if (host
.password_encrypt
)
543 vty_out (vty
, "password 8 %s%s", host
.password_encrypt
, VTY_NEWLINE
);
544 if (host
.enable_encrypt
)
545 vty_out (vty
, "enable password 8 %s%s", host
.enable_encrypt
, VTY_NEWLINE
);
550 vty_out (vty
, "password %s%s", host
.password
, VTY_NEWLINE
);
552 vty_out (vty
, "enable password %s%s", host
.enable
, VTY_NEWLINE
);
555 if (zlog_default
->default_lvl
!= LOG_DEBUG
)
557 vty_out (vty
, "! N.B. The 'log trap' command is deprecated.%s",
559 vty_out (vty
, "log trap %s%s",
560 zlog_priority
[zlog_default
->default_lvl
], VTY_NEWLINE
);
563 if (host
.logfile
&& (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != ZLOG_DISABLED
))
565 vty_out (vty
, "log file %s", host
.logfile
);
566 if (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != zlog_default
->default_lvl
)
568 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_FILE
]]);
569 vty_out (vty
, "%s", VTY_NEWLINE
);
572 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != ZLOG_DISABLED
)
574 vty_out (vty
, "log stdout");
575 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != zlog_default
->default_lvl
)
577 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
]]);
578 vty_out (vty
, "%s", VTY_NEWLINE
);
581 if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
582 vty_out(vty
,"no log monitor%s",VTY_NEWLINE
);
583 else if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] != zlog_default
->default_lvl
)
584 vty_out(vty
,"log monitor %s%s",
585 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
]],VTY_NEWLINE
);
587 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != ZLOG_DISABLED
)
589 vty_out (vty
, "log syslog");
590 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != zlog_default
->default_lvl
)
592 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
]]);
593 vty_out (vty
, "%s", VTY_NEWLINE
);
596 if (zlog_default
->facility
!= LOG_DAEMON
)
597 vty_out (vty
, "log facility %s%s",
598 facility_name(zlog_default
->facility
), VTY_NEWLINE
);
600 if (zlog_default
->record_priority
== 1)
601 vty_out (vty
, "log record-priority%s", VTY_NEWLINE
);
603 if (zlog_default
->timestamp_precision
> 0)
604 vty_out (vty
, "log timestamp precision %d%s",
605 zlog_default
->timestamp_precision
, VTY_NEWLINE
);
608 vty_out (vty
, "service advanced-vty%s", VTY_NEWLINE
);
611 vty_out (vty
, "service password-encryption%s", VTY_NEWLINE
);
614 vty_out (vty
, "service terminal-length %d%s", host
.lines
,
618 vty_out (vty
, "banner motd file %s%s", host
.motdfile
, VTY_NEWLINE
);
619 else if (! host
.motd
)
620 vty_out (vty
, "no banner motd%s", VTY_NEWLINE
);
625 /* Utility function for getting command vector. */
627 cmd_node_vector (vector v
, enum node_type ntype
)
629 struct cmd_node
*cnode
= vector_slot (v
, ntype
);
630 return cnode
->cmd_vector
;
634 /* Filter command vector by symbol. This function is not actually used;
635 * should it be deleted? */
637 cmd_filter_by_symbol (char *command
, char *symbol
)
641 if (strcmp (symbol
, "IPV4_ADDRESS") == 0)
644 lim
= strlen (command
);
647 if (! (isdigit ((int) command
[i
]) || command
[i
] == '.' || command
[i
] == '/'))
653 if (strcmp (symbol
, "STRING") == 0)
656 lim
= strlen (command
);
659 if (! (isalpha ((int) command
[i
]) || command
[i
] == '_' || command
[i
] == '-'))
665 if (strcmp (symbol
, "IFNAME") == 0)
668 lim
= strlen (command
);
671 if (! isalnum ((int) command
[i
]))
681 /* Completion match types. */
696 static enum match_type
697 cmd_ipv4_match (const char *str
)
700 int dots
= 0, nums
= 0;
708 memset (buf
, 0, sizeof (buf
));
717 if (*(str
+ 1) == '.')
720 if (*(str
+ 1) == '\0')
726 if (!isdigit ((int) *str
))
735 strncpy (buf
, sp
, str
- sp
);
736 if (atoi (buf
) > 255)
753 static enum match_type
754 cmd_ipv4_prefix_match (const char *str
)
765 memset (buf
, 0, sizeof (buf
));
767 while (*str
!= '\0' && *str
!= '/')
774 if (*(str
+ 1) == '.' || *(str
+ 1) == '/')
777 if (*(str
+ 1) == '\0')
784 if (!isdigit ((int) *str
))
793 strncpy (buf
, sp
, str
- sp
);
794 if (atoi (buf
) > 255)
801 if (*(str
+ 1) == '\0')
807 else if (*str
== '\0')
820 if (!isdigit ((int) *str
))
832 #define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
833 #define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
834 #define STATE_START 1
835 #define STATE_COLON 2
836 #define STATE_DOUBLE 3
839 #define STATE_SLASH 6
844 static enum match_type
845 cmd_ipv6_match (const char *str
)
847 int state
= STATE_START
;
848 int colons
= 0, nums
= 0, double_colon
= 0;
849 const char *sp
= NULL
;
850 struct sockaddr_in6 sin6_dummy
;
856 if (strspn (str
, IPV6_ADDR_STR
) != strlen (str
))
859 /* use inet_pton that has a better support,
860 * for example inet_pton can support the automatic addresses:
863 ret
= inet_pton(AF_INET6
, str
, &sin6_dummy
.sin6_addr
);
875 if (*(str
+ 1) != ':' && *(str
+ 1) != '\0')
889 if (*(str
+ 1) == ':')
890 state
= STATE_DOUBLE
;
901 if (*(str
+ 1) == ':')
905 if (*(str
+ 1) != '\0')
915 if (*(str
+ 1) == ':' || *(str
+ 1) == '\0')
923 if (*(str
+ 1) == '.')
950 static enum match_type
951 cmd_ipv6_prefix_match (const char *str
)
953 int state
= STATE_START
;
954 int colons
= 0, nums
= 0, double_colon
= 0;
956 const char *sp
= NULL
;
962 if (strspn (str
, IPV6_PREFIX_STR
) != strlen (str
))
965 while (*str
!= '\0' && state
!= STATE_MASK
)
972 if (*(str
+ 1) != ':' && *(str
+ 1) != '\0')
986 if (*(str
+ 1) == '/')
988 else if (*(str
+ 1) == ':')
989 state
= STATE_DOUBLE
;
1000 if (*(str
+ 1) == ':')
1004 if (*(str
+ 1) != '\0' && *(str
+ 1) != '/')
1008 if (*(str
+ 1) == '/')
1009 state
= STATE_SLASH
;
1018 if (*(str
+ 1) == ':' || *(str
+ 1) == '.'
1019 || *(str
+ 1) == '\0' || *(str
+ 1) == '/')
1024 for (; sp
<= str
; sp
++)
1030 if (*(str
+ 1) == ':')
1031 state
= STATE_COLON
;
1032 else if (*(str
+ 1) == '.')
1034 else if (*(str
+ 1) == '/')
1035 state
= STATE_SLASH
;
1042 if (*(str
+ 1) == '\0')
1043 return partly_match
;
1060 if (state
< STATE_MASK
)
1061 return partly_match
;
1063 mask
= strtol (str
, &endptr
, 10);
1064 if (*endptr
!= '\0')
1067 if (mask
< 0 || mask
> 128)
1070 /* I don't know why mask < 13 makes command match partly.
1071 Forgive me to make this comments. I Want to set static default route
1072 because of lack of function to originate default in ospf6d; sorry
1075 return partly_match;
1081 #endif /* HAVE_IPV6 */
1083 #define DECIMAL_STRLEN_MAX 10
1086 cmd_range_match (const char *range
, const char *str
)
1089 char buf
[DECIMAL_STRLEN_MAX
+ 1];
1090 char *endptr
= NULL
;
1091 unsigned long min
, max
, val
;
1096 val
= strtoul (str
, &endptr
, 10);
1097 if (*endptr
!= '\0')
1101 p
= strchr (range
, '-');
1104 if (p
- range
> DECIMAL_STRLEN_MAX
)
1106 strncpy (buf
, range
, p
- range
);
1107 buf
[p
- range
] = '\0';
1108 min
= strtoul (buf
, &endptr
, 10);
1109 if (*endptr
!= '\0')
1113 p
= strchr (range
, '>');
1116 if (p
- range
> DECIMAL_STRLEN_MAX
)
1118 strncpy (buf
, range
, p
- range
);
1119 buf
[p
- range
] = '\0';
1120 max
= strtoul (buf
, &endptr
, 10);
1121 if (*endptr
!= '\0')
1124 if (val
< min
|| val
> max
)
1130 /* Make completion match and return match type flag. */
1131 static enum match_type
1132 cmd_filter_by_completion (char *command
, vector v
, unsigned int index
)
1136 struct cmd_element
*cmd_element
;
1137 enum match_type match_type
;
1141 match_type
= no_match
;
1143 /* If command and cmd_element string does not match set NULL to vector */
1144 for (i
= 0; i
< vector_active (v
); i
++)
1145 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1147 if (index
>= vector_active (cmd_element
->strvec
))
1148 vector_slot (v
, i
) = NULL
;
1154 descvec
= vector_slot (cmd_element
->strvec
, index
);
1156 for (j
= 0; j
< vector_active (descvec
); j
++)
1157 if ((desc
= vector_slot (descvec
, j
)))
1161 if (CMD_VARARG (str
))
1163 if (match_type
< vararg_match
)
1164 match_type
= vararg_match
;
1167 else if (CMD_RANGE (str
))
1169 if (cmd_range_match (str
, command
))
1171 if (match_type
< range_match
)
1172 match_type
= range_match
;
1178 else if (CMD_IPV6 (str
))
1180 if (cmd_ipv6_match (command
))
1182 if (match_type
< ipv6_match
)
1183 match_type
= ipv6_match
;
1188 else if (CMD_IPV6_PREFIX (str
))
1190 if (cmd_ipv6_prefix_match (command
))
1192 if (match_type
< ipv6_prefix_match
)
1193 match_type
= ipv6_prefix_match
;
1198 #endif /* HAVE_IPV6 */
1199 else if (CMD_IPV4 (str
))
1201 if (cmd_ipv4_match (command
))
1203 if (match_type
< ipv4_match
)
1204 match_type
= ipv4_match
;
1209 else if (CMD_IPV4_PREFIX (str
))
1211 if (cmd_ipv4_prefix_match (command
))
1213 if (match_type
< ipv4_prefix_match
)
1214 match_type
= ipv4_prefix_match
;
1219 /* Check is this point's argument optional ? */
1220 if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1222 if (match_type
< extend_match
)
1223 match_type
= extend_match
;
1226 else if (strncmp (command
, str
, strlen (command
)) == 0)
1228 if (strcmp (command
, str
) == 0)
1229 match_type
= exact_match
;
1232 if (match_type
< partly_match
)
1233 match_type
= partly_match
;
1239 vector_slot (v
, i
) = NULL
;
1245 /* Filter vector by command character with index. */
1246 static enum match_type
1247 cmd_filter_by_string (char *command
, vector v
, unsigned int index
)
1251 struct cmd_element
*cmd_element
;
1252 enum match_type match_type
;
1256 match_type
= no_match
;
1258 /* If command and cmd_element string does not match set NULL to vector */
1259 for (i
= 0; i
< vector_active (v
); i
++)
1260 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1262 /* If given index is bigger than max string vector of command,
1264 if (index
>= vector_active (cmd_element
->strvec
))
1265 vector_slot (v
, i
) = NULL
;
1271 descvec
= vector_slot (cmd_element
->strvec
, index
);
1273 for (j
= 0; j
< vector_active (descvec
); j
++)
1274 if ((desc
= vector_slot (descvec
, j
)))
1278 if (CMD_VARARG (str
))
1280 if (match_type
< vararg_match
)
1281 match_type
= vararg_match
;
1284 else if (CMD_RANGE (str
))
1286 if (cmd_range_match (str
, command
))
1288 if (match_type
< range_match
)
1289 match_type
= range_match
;
1294 else if (CMD_IPV6 (str
))
1296 if (cmd_ipv6_match (command
) == exact_match
)
1298 if (match_type
< ipv6_match
)
1299 match_type
= ipv6_match
;
1303 else if (CMD_IPV6_PREFIX (str
))
1305 if (cmd_ipv6_prefix_match (command
) == exact_match
)
1307 if (match_type
< ipv6_prefix_match
)
1308 match_type
= ipv6_prefix_match
;
1312 #endif /* HAVE_IPV6 */
1313 else if (CMD_IPV4 (str
))
1315 if (cmd_ipv4_match (command
) == exact_match
)
1317 if (match_type
< ipv4_match
)
1318 match_type
= ipv4_match
;
1322 else if (CMD_IPV4_PREFIX (str
))
1324 if (cmd_ipv4_prefix_match (command
) == exact_match
)
1326 if (match_type
< ipv4_prefix_match
)
1327 match_type
= ipv4_prefix_match
;
1331 else if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1333 if (match_type
< extend_match
)
1334 match_type
= extend_match
;
1339 if (strcmp (command
, str
) == 0)
1341 match_type
= exact_match
;
1347 vector_slot (v
, i
) = NULL
;
1353 /* Check ambiguous match */
1355 is_cmd_ambiguous (char *command
, vector v
, int index
, enum match_type type
)
1359 const char *str
= NULL
;
1360 struct cmd_element
*cmd_element
;
1361 const char *matched
= NULL
;
1365 for (i
= 0; i
< vector_active (v
); i
++)
1366 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1370 descvec
= vector_slot (cmd_element
->strvec
, index
);
1372 for (j
= 0; j
< vector_active (descvec
); j
++)
1373 if ((desc
= vector_slot (descvec
, j
)))
1375 enum match_type ret
;
1382 if (!(CMD_OPTION (str
) || CMD_VARIABLE (str
))
1383 && strcmp (command
, str
) == 0)
1387 if (!(CMD_OPTION (str
) || CMD_VARIABLE (str
))
1388 && strncmp (command
, str
, strlen (command
)) == 0)
1390 if (matched
&& strcmp (matched
, str
) != 0)
1391 return 1; /* There is ambiguous match. */
1398 if (cmd_range_match (str
, command
))
1400 if (matched
&& strcmp (matched
, str
) != 0)
1412 case ipv6_prefix_match
:
1413 if ((ret
= cmd_ipv6_prefix_match (command
)) != no_match
)
1415 if (ret
== partly_match
)
1416 return 2; /* There is incomplete match. */
1421 #endif /* HAVE_IPV6 */
1426 case ipv4_prefix_match
:
1427 if ((ret
= cmd_ipv4_prefix_match (command
)) != no_match
)
1429 if (ret
== partly_match
)
1430 return 2; /* There is incomplete match. */
1436 if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1445 vector_slot (v
, i
) = NULL
;
1450 /* If src matches dst return dst string, otherwise return NULL */
1452 cmd_entry_function (const char *src
, const char *dst
)
1454 /* Skip variable arguments. */
1455 if (CMD_OPTION (dst
) || CMD_VARIABLE (dst
) || CMD_VARARG (dst
) ||
1456 CMD_IPV4 (dst
) || CMD_IPV4_PREFIX (dst
) || CMD_RANGE (dst
))
1459 /* In case of 'command \t', given src is NULL string. */
1463 /* Matched with input string. */
1464 if (strncmp (src
, dst
, strlen (src
)) == 0)
1470 /* If src matches dst return dst string, otherwise return NULL */
1471 /* This version will return the dst string always if it is
1472 CMD_VARIABLE for '?' key processing */
1474 cmd_entry_function_desc (const char *src
, const char *dst
)
1476 if (CMD_VARARG (dst
))
1479 if (CMD_RANGE (dst
))
1481 if (cmd_range_match (dst
, src
))
1490 if (cmd_ipv6_match (src
))
1496 if (CMD_IPV6_PREFIX (dst
))
1498 if (cmd_ipv6_prefix_match (src
))
1503 #endif /* HAVE_IPV6 */
1507 if (cmd_ipv4_match (src
))
1513 if (CMD_IPV4_PREFIX (dst
))
1515 if (cmd_ipv4_prefix_match (src
))
1521 /* Optional or variable commands always match on '?' */
1522 if (CMD_OPTION (dst
) || CMD_VARIABLE (dst
))
1525 /* In case of 'command \t', given src is NULL string. */
1529 if (strncmp (src
, dst
, strlen (src
)) == 0)
1535 /* Check same string element existence. If it isn't there return
1538 cmd_unique_string (vector v
, const char *str
)
1543 for (i
= 0; i
< vector_active (v
); i
++)
1544 if ((match
= vector_slot (v
, i
)) != NULL
)
1545 if (strcmp (match
, str
) == 0)
1550 /* Compare string to description vector. If there is same string
1551 return 1 else return 0. */
1553 desc_unique_string (vector v
, const char *str
)
1558 for (i
= 0; i
< vector_active (v
); i
++)
1559 if ((desc
= vector_slot (v
, i
)) != NULL
)
1560 if (strcmp (desc
->cmd
, str
) == 0)
1566 cmd_try_do_shortcut (enum node_type node
, char* first_word
) {
1567 if ( first_word
!= NULL
&&
1568 node
!= AUTH_NODE
&&
1569 node
!= VIEW_NODE
&&
1570 node
!= AUTH_ENABLE_NODE
&&
1571 node
!= ENABLE_NODE
&&
1572 node
!= RESTRICTED_NODE
&&
1573 0 == strcmp( "do", first_word
) )
1578 /* '?' describe command support. */
1580 cmd_describe_command_real (vector vline
, struct vty
*vty
, int *status
)
1584 #define INIT_MATCHVEC_SIZE 10
1586 struct cmd_element
*cmd_element
;
1589 enum match_type match
;
1591 static struct desc desc_cr
= { "<cr>", "" };
1594 if (vector_active (vline
) == 0)
1596 *status
= CMD_ERR_NO_MATCH
;
1600 index
= vector_active (vline
) - 1;
1602 /* Make copy vector of current node's command vector. */
1603 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
1605 /* Prepare match vector */
1606 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1608 /* Filter commands. */
1609 /* Only words precedes current word will be checked in this loop. */
1610 for (i
= 0; i
< index
; i
++)
1611 if ((command
= vector_slot (vline
, i
)))
1613 match
= cmd_filter_by_completion (command
, cmd_vector
, i
);
1615 if (match
== vararg_match
)
1617 struct cmd_element
*cmd_element
;
1621 for (j
= 0; j
< vector_active (cmd_vector
); j
++)
1622 if ((cmd_element
= vector_slot (cmd_vector
, j
)) != NULL
1623 && (vector_active (cmd_element
->strvec
)))
1625 descvec
= vector_slot (cmd_element
->strvec
,
1626 vector_active (cmd_element
->strvec
) - 1);
1627 for (k
= 0; k
< vector_active (descvec
); k
++)
1629 struct desc
*desc
= vector_slot (descvec
, k
);
1630 vector_set (matchvec
, desc
);
1634 vector_set (matchvec
, &desc_cr
);
1635 vector_free (cmd_vector
);
1640 if ((ret
= is_cmd_ambiguous (command
, cmd_vector
, i
, match
)) == 1)
1642 vector_free (cmd_vector
);
1643 vector_free (matchvec
);
1644 *status
= CMD_ERR_AMBIGUOUS
;
1649 vector_free (cmd_vector
);
1650 vector_free (matchvec
);
1651 *status
= CMD_ERR_NO_MATCH
;
1656 /* Prepare match vector */
1657 /* matchvec = vector_init (INIT_MATCHVEC_SIZE); */
1659 /* Make sure that cmd_vector is filtered based on current word */
1660 command
= vector_slot (vline
, index
);
1662 match
= cmd_filter_by_completion (command
, cmd_vector
, index
);
1664 /* Make description vector. */
1665 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
1666 if ((cmd_element
= vector_slot (cmd_vector
, i
)) != NULL
)
1668 const char *string
= NULL
;
1669 vector strvec
= cmd_element
->strvec
;
1671 /* if command is NULL, index may be equal to vector_active */
1672 if (command
&& index
>= vector_active (strvec
))
1673 vector_slot (cmd_vector
, i
) = NULL
;
1676 /* Check if command is completed. */
1677 if (command
== NULL
&& index
== vector_active (strvec
))
1680 if (!desc_unique_string (matchvec
, string
))
1681 vector_set (matchvec
, &desc_cr
);
1686 vector descvec
= vector_slot (strvec
, index
);
1689 for (j
= 0; j
< vector_active (descvec
); j
++)
1690 if ((desc
= vector_slot (descvec
, j
)))
1692 string
= cmd_entry_function_desc (command
, desc
->cmd
);
1695 /* Uniqueness check */
1696 if (!desc_unique_string (matchvec
, string
))
1697 vector_set (matchvec
, desc
);
1703 vector_free (cmd_vector
);
1705 if (vector_slot (matchvec
, 0) == NULL
)
1707 vector_free (matchvec
);
1708 *status
= CMD_ERR_NO_MATCH
;
1712 *status
= CMD_SUCCESS
;
1717 cmd_describe_command (vector vline
, struct vty
*vty
, int *status
)
1721 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
1723 enum node_type onode
;
1724 vector shifted_vline
;
1728 vty
->node
= ENABLE_NODE
;
1729 /* We can try it on enable node, cos' the vty is authenticated */
1731 shifted_vline
= vector_init (vector_count(vline
));
1733 for (index
= 1; index
< vector_active (vline
); index
++)
1735 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
1738 ret
= cmd_describe_command_real (shifted_vline
, vty
, status
);
1740 vector_free(shifted_vline
);
1746 return cmd_describe_command_real (vline
, vty
, status
);
1750 /* Check LCD of matched command. */
1752 cmd_lcd (char **matched
)
1760 if (matched
[0] == NULL
|| matched
[1] == NULL
)
1763 for (i
= 1; matched
[i
] != NULL
; i
++)
1765 s1
= matched
[i
- 1];
1768 for (j
= 0; (c1
= s1
[j
]) && (c2
= s2
[j
]); j
++)
1783 /* Command line completion support. */
1785 cmd_complete_command_real (vector vline
, struct vty
*vty
, int *status
)
1788 vector cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
1789 #define INIT_MATCHVEC_SIZE 10
1791 struct cmd_element
*cmd_element
;
1799 if (vector_active (vline
) == 0)
1801 vector_free (cmd_vector
);
1802 *status
= CMD_ERR_NO_MATCH
;
1806 index
= vector_active (vline
) - 1;
1808 /* First, filter by preceeding command string */
1809 for (i
= 0; i
< index
; i
++)
1810 if ((command
= vector_slot (vline
, i
)))
1812 enum match_type match
;
1815 /* First try completion match, if there is exactly match return 1 */
1816 match
= cmd_filter_by_completion (command
, cmd_vector
, i
);
1818 /* If there is exact match then filter ambiguous match else check
1820 if ((ret
= is_cmd_ambiguous (command
, cmd_vector
, i
, match
)) == 1)
1822 vector_free (cmd_vector
);
1823 *status
= CMD_ERR_AMBIGUOUS
;
1829 vector_free (cmd_vector);
1830 *status = CMD_ERR_NO_MATCH;
1836 /* Prepare match vector. */
1837 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1839 /* Now we got into completion */
1840 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
1841 if ((cmd_element
= vector_slot (cmd_vector
, i
)))
1844 vector strvec
= cmd_element
->strvec
;
1846 /* Check field length */
1847 if (index
>= vector_active (strvec
))
1848 vector_slot (cmd_vector
, i
) = NULL
;
1853 descvec
= vector_slot (strvec
, index
);
1854 for (j
= 0; j
< vector_active (descvec
); j
++)
1855 if ((desc
= vector_slot (descvec
, j
)))
1858 cmd_entry_function (vector_slot (vline
, index
),
1860 if (cmd_unique_string (matchvec
, string
))
1861 vector_set (matchvec
, XSTRDUP (MTYPE_TMP
, string
));
1866 /* We don't need cmd_vector any more. */
1867 vector_free (cmd_vector
);
1869 /* No matched command */
1870 if (vector_slot (matchvec
, 0) == NULL
)
1872 vector_free (matchvec
);
1874 /* In case of 'command \t' pattern. Do you need '?' command at
1875 the end of the line. */
1876 if (vector_slot (vline
, index
) == '\0')
1877 *status
= CMD_ERR_NOTHING_TODO
;
1879 *status
= CMD_ERR_NO_MATCH
;
1883 /* Only one matched */
1884 if (vector_slot (matchvec
, 1) == NULL
)
1886 match_str
= (char **) matchvec
->index
;
1887 vector_only_wrapper_free (matchvec
);
1888 *status
= CMD_COMPLETE_FULL_MATCH
;
1891 /* Make it sure last element is NULL. */
1892 vector_set (matchvec
, NULL
);
1894 /* Check LCD of matched strings. */
1895 if (vector_slot (vline
, index
) != NULL
)
1897 lcd
= cmd_lcd ((char **) matchvec
->index
);
1901 int len
= strlen (vector_slot (vline
, index
));
1907 lcdstr
= XMALLOC (MTYPE_STRVEC
, lcd
+ 1);
1908 memcpy (lcdstr
, matchvec
->index
[0], lcd
);
1911 /* match_str = (char **) &lcdstr; */
1913 /* Free matchvec. */
1914 for (i
= 0; i
< vector_active (matchvec
); i
++)
1916 if (vector_slot (matchvec
, i
))
1917 XFREE (MTYPE_STRVEC
, vector_slot (matchvec
, i
));
1919 vector_free (matchvec
);
1921 /* Make new matchvec. */
1922 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1923 vector_set (matchvec
, lcdstr
);
1924 match_str
= (char **) matchvec
->index
;
1925 vector_only_wrapper_free (matchvec
);
1927 *status
= CMD_COMPLETE_MATCH
;
1933 match_str
= (char **) matchvec
->index
;
1934 vector_only_wrapper_free (matchvec
);
1935 *status
= CMD_COMPLETE_LIST_MATCH
;
1940 cmd_complete_command (vector vline
, struct vty
*vty
, int *status
)
1944 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
1946 enum node_type onode
;
1947 vector shifted_vline
;
1951 vty
->node
= ENABLE_NODE
;
1952 /* We can try it on enable node, cos' the vty is authenticated */
1954 shifted_vline
= vector_init (vector_count(vline
));
1956 for (index
= 1; index
< vector_active (vline
); index
++)
1958 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
1961 ret
= cmd_complete_command_real (shifted_vline
, vty
, status
);
1963 vector_free(shifted_vline
);
1969 return cmd_complete_command_real (vline
, vty
, status
);
1972 /* return parent node */
1973 /* MUST eventually converge on CONFIG_NODE */
1975 node_parent ( enum node_type node
)
1979 assert (node
> CONFIG_NODE
);
1983 case BGP_VPNV4_NODE
:
1985 case BGP_IPV4M_NODE
:
1987 case BGP_IPV6M_NODE
:
1990 case KEYCHAIN_KEY_NODE
:
1991 ret
= KEYCHAIN_NODE
;
2000 /* Execute command by argument vline vector. */
2002 cmd_execute_command_real (vector vline
, struct vty
*vty
,
2003 struct cmd_element
**cmd
)
2008 struct cmd_element
*cmd_element
;
2009 struct cmd_element
*matched_element
;
2010 unsigned int matched_count
, incomplete_count
;
2012 const char *argv
[CMD_ARGC_MAX
];
2013 enum match_type match
= 0;
2017 /* Make copy of command elements. */
2018 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
2020 for (index
= 0; index
< vector_active (vline
); index
++)
2021 if ((command
= vector_slot (vline
, index
)))
2025 match
= cmd_filter_by_completion (command
, cmd_vector
, index
);
2027 if (match
== vararg_match
)
2030 ret
= is_cmd_ambiguous (command
, cmd_vector
, index
, match
);
2034 vector_free (cmd_vector
);
2035 return CMD_ERR_AMBIGUOUS
;
2039 vector_free (cmd_vector
);
2040 return CMD_ERR_NO_MATCH
;
2044 /* Check matched count. */
2045 matched_element
= NULL
;
2047 incomplete_count
= 0;
2049 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
2050 if ((cmd_element
= vector_slot (cmd_vector
, i
)))
2052 if (match
== vararg_match
|| index
>= cmd_element
->cmdsize
)
2054 matched_element
= cmd_element
;
2056 printf ("DEBUG: %s\n", cmd_element
->string
);
2066 /* Finish of using cmd_vector. */
2067 vector_free (cmd_vector
);
2069 /* To execute command, matched_count must be 1. */
2070 if (matched_count
== 0)
2072 if (incomplete_count
)
2073 return CMD_ERR_INCOMPLETE
;
2075 return CMD_ERR_NO_MATCH
;
2078 if (matched_count
> 1)
2079 return CMD_ERR_AMBIGUOUS
;
2081 /* Argument treatment */
2085 for (i
= 0; i
< vector_active (vline
); i
++)
2088 argv
[argc
++] = vector_slot (vline
, i
);
2091 vector descvec
= vector_slot (matched_element
->strvec
, i
);
2093 if (vector_active (descvec
) == 1)
2095 struct desc
*desc
= vector_slot (descvec
, 0);
2097 if (CMD_VARARG (desc
->cmd
))
2100 if (varflag
|| CMD_VARIABLE (desc
->cmd
) || CMD_OPTION (desc
->cmd
))
2101 argv
[argc
++] = vector_slot (vline
, i
);
2104 argv
[argc
++] = vector_slot (vline
, i
);
2107 if (argc
>= CMD_ARGC_MAX
)
2108 return CMD_ERR_EXEED_ARGC_MAX
;
2111 /* For vtysh execution. */
2113 *cmd
= matched_element
;
2115 if (matched_element
->daemon
)
2116 return CMD_SUCCESS_DAEMON
;
2118 /* Execute matched command. */
2119 return (*matched_element
->func
) (matched_element
, vty
, argc
, argv
);
2123 cmd_execute_command (vector vline
, struct vty
*vty
, struct cmd_element
**cmd
,
2125 int ret
, saved_ret
, tried
= 0;
2126 enum node_type onode
, try_node
;
2128 onode
= try_node
= vty
->node
;
2130 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
2132 vector shifted_vline
;
2135 vty
->node
= ENABLE_NODE
;
2136 /* We can try it on enable node, cos' the vty is authenticated */
2138 shifted_vline
= vector_init (vector_count(vline
));
2140 for (index
= 1; index
< vector_active (vline
); index
++)
2142 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
2145 ret
= cmd_execute_command_real (shifted_vline
, vty
, cmd
);
2147 vector_free(shifted_vline
);
2153 saved_ret
= ret
= cmd_execute_command_real (vline
, vty
, cmd
);
2158 /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
2159 while ( ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2160 && vty
->node
> CONFIG_NODE
)
2162 try_node
= node_parent(try_node
);
2163 vty
->node
= try_node
;
2164 ret
= cmd_execute_command_real (vline
, vty
, cmd
);
2166 if (ret
== CMD_SUCCESS
|| ret
== CMD_WARNING
)
2168 /* succesfull command, leave the node as is */
2172 /* no command succeeded, reset the vty to the original node and
2173 return the error for this node */
2179 /* Execute command by argument readline. */
2181 cmd_execute_command_strict (vector vline
, struct vty
*vty
,
2182 struct cmd_element
**cmd
)
2187 struct cmd_element
*cmd_element
;
2188 struct cmd_element
*matched_element
;
2189 unsigned int matched_count
, incomplete_count
;
2191 const char *argv
[CMD_ARGC_MAX
];
2193 enum match_type match
= 0;
2196 /* Make copy of command element */
2197 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
2199 for (index
= 0; index
< vector_active (vline
); index
++)
2200 if ((command
= vector_slot (vline
, index
)))
2204 match
= cmd_filter_by_string (vector_slot (vline
, index
),
2207 /* If command meets '.VARARG' then finish matching. */
2208 if (match
== vararg_match
)
2211 ret
= is_cmd_ambiguous (command
, cmd_vector
, index
, match
);
2214 vector_free (cmd_vector
);
2215 return CMD_ERR_AMBIGUOUS
;
2219 vector_free (cmd_vector
);
2220 return CMD_ERR_NO_MATCH
;
2224 /* Check matched count. */
2225 matched_element
= NULL
;
2227 incomplete_count
= 0;
2228 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
2229 if (vector_slot (cmd_vector
, i
) != NULL
)
2231 cmd_element
= vector_slot (cmd_vector
, i
);
2233 if (match
== vararg_match
|| index
>= cmd_element
->cmdsize
)
2235 matched_element
= cmd_element
;
2242 /* Finish of using cmd_vector. */
2243 vector_free (cmd_vector
);
2245 /* To execute command, matched_count must be 1. */
2246 if (matched_count
== 0)
2248 if (incomplete_count
)
2249 return CMD_ERR_INCOMPLETE
;
2251 return CMD_ERR_NO_MATCH
;
2254 if (matched_count
> 1)
2255 return CMD_ERR_AMBIGUOUS
;
2257 /* Argument treatment */
2261 for (i
= 0; i
< vector_active (vline
); i
++)
2264 argv
[argc
++] = vector_slot (vline
, i
);
2267 vector descvec
= vector_slot (matched_element
->strvec
, i
);
2269 if (vector_active (descvec
) == 1)
2271 struct desc
*desc
= vector_slot (descvec
, 0);
2273 if (CMD_VARARG (desc
->cmd
))
2276 if (varflag
|| CMD_VARIABLE (desc
->cmd
) || CMD_OPTION (desc
->cmd
))
2277 argv
[argc
++] = vector_slot (vline
, i
);
2280 argv
[argc
++] = vector_slot (vline
, i
);
2283 if (argc
>= CMD_ARGC_MAX
)
2284 return CMD_ERR_EXEED_ARGC_MAX
;
2287 /* For vtysh execution. */
2289 *cmd
= matched_element
;
2291 if (matched_element
->daemon
)
2292 return CMD_SUCCESS_DAEMON
;
2294 /* Now execute matched command */
2295 return (*matched_element
->func
) (matched_element
, vty
, argc
, argv
);
2298 /* Configration make from file. */
2300 config_from_file (struct vty
*vty
, FILE *fp
)
2305 while (fgets (vty
->buf
, VTY_BUFSIZ
, fp
))
2307 vline
= cmd_make_strvec (vty
->buf
);
2309 /* In case of comment line */
2312 /* Execute configuration command : this is strict match */
2313 ret
= cmd_execute_command_strict (vline
, vty
, NULL
);
2315 /* Try again with setting node to CONFIG_NODE */
2316 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2317 && ret
!= CMD_ERR_NOTHING_TODO
&& vty
->node
!= CONFIG_NODE
)
2319 vty
->node
= node_parent(vty
->node
);
2320 ret
= cmd_execute_command_strict (vline
, vty
, NULL
);
2323 cmd_free_strvec (vline
);
2325 if (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2326 && ret
!= CMD_ERR_NOTHING_TODO
)
2332 /* Configration from terminal */
2333 DEFUN (config_terminal
,
2334 config_terminal_cmd
,
2335 "configure terminal",
2336 "Configuration from vty interface\n"
2337 "Configuration terminal\n")
2339 if (vty_config_lock (vty
))
2340 vty
->node
= CONFIG_NODE
;
2343 vty_out (vty
, "VTY configuration is locked by other VTY%s", VTY_NEWLINE
);
2349 /* Enable command */
2353 "Turn on privileged mode command\n")
2355 /* If enable password is NULL, change to ENABLE_NODE */
2356 if ((host
.enable
== NULL
&& host
.enable_encrypt
== NULL
) ||
2357 vty
->type
== VTY_SHELL_SERV
)
2358 vty
->node
= ENABLE_NODE
;
2360 vty
->node
= AUTH_ENABLE_NODE
;
2365 /* Disable command */
2369 "Turn off privileged mode command\n")
2371 if (vty
->node
== ENABLE_NODE
)
2372 vty
->node
= VIEW_NODE
;
2376 /* Down vty node level. */
2380 "Exit current mode and down to previous mode\n")
2386 case RESTRICTED_NODE
:
2387 if (vty_shell (vty
))
2390 vty
->status
= VTY_CLOSE
;
2393 vty
->node
= ENABLE_NODE
;
2394 vty_config_unlock (vty
);
2396 case INTERFACE_NODE
:
2408 vty
->node
= CONFIG_NODE
;
2410 case BGP_VPNV4_NODE
:
2412 case BGP_IPV4M_NODE
:
2414 case BGP_IPV6M_NODE
:
2415 vty
->node
= BGP_NODE
;
2417 case KEYCHAIN_KEY_NODE
:
2418 vty
->node
= KEYCHAIN_NODE
;
2426 /* quit is alias of exit. */
2430 "Exit current mode and down to previous mode\n")
2432 /* End of configuration. */
2436 "End current mode and change to enable mode.")
2442 case RESTRICTED_NODE
:
2443 /* Nothing to do. */
2446 case INTERFACE_NODE
:
2451 case BGP_VPNV4_NODE
:
2453 case BGP_IPV4M_NODE
:
2455 case BGP_IPV6M_NODE
:
2461 case KEYCHAIN_KEY_NODE
:
2464 vty_config_unlock (vty
);
2465 vty
->node
= ENABLE_NODE
;
2474 DEFUN (show_version
,
2478 "Displays zebra version\n")
2480 vty_out (vty
, "Quagga %s (%s).%s", QUAGGA_VERSION
, host
.name
?host
.name
:"",
2482 vty_out (vty
, "%s%s", QUAGGA_COPYRIGHT
, VTY_NEWLINE
);
2487 /* Help display function for all node. */
2491 "Description of the interactive help system\n")
2494 "Quagga VTY provides advanced help feature. When you need help,%s\
2495 anytime at the command line please press '?'.%s\
2497 If nothing matches, the help list will be empty and you must backup%s\
2498 until entering a '?' shows the available options.%s\
2499 Two styles of help are provided:%s\
2500 1. Full help is available when you are ready to enter a%s\
2501 command argument (e.g. 'show ?') and describes each possible%s\
2503 2. Partial help is provided when an abbreviated argument is entered%s\
2504 and you want to know what arguments match the input%s\
2505 (e.g. 'show me?'.)%s%s", VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2506 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2507 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2511 /* Help display function for all node. */
2515 "Print command list\n")
2518 struct cmd_node
*cnode
= vector_slot (cmdvec
, vty
->node
);
2519 struct cmd_element
*cmd
;
2521 for (i
= 0; i
< vector_active (cnode
->cmd_vector
); i
++)
2522 if ((cmd
= vector_slot (cnode
->cmd_vector
, i
)) != NULL
2523 && !(cmd
->attr
== CMD_ATTR_DEPRECATED
2524 || cmd
->attr
== CMD_ATTR_HIDDEN
))
2525 vty_out (vty
, " %s%s", cmd
->string
,
2530 /* Write current configuration into file. */
2531 DEFUN (config_write_file
,
2532 config_write_file_cmd
,
2534 "Write running configuration to memory, network, or terminal\n"
2535 "Write to configuration file\n")
2539 struct cmd_node
*node
;
2541 char *config_file_tmp
= NULL
;
2542 char *config_file_sav
= NULL
;
2543 int ret
= CMD_WARNING
;
2544 struct vty
*file_vty
;
2546 /* Check and see if we are operating under vtysh configuration */
2547 if (host
.config
== NULL
)
2549 vty_out (vty
, "Can't save to configuration file, using vtysh.%s",
2555 config_file
= host
.config
;
2558 XMALLOC (MTYPE_TMP
, strlen (config_file
) + strlen (CONF_BACKUP_EXT
) + 1);
2559 strcpy (config_file_sav
, config_file
);
2560 strcat (config_file_sav
, CONF_BACKUP_EXT
);
2563 config_file_tmp
= XMALLOC (MTYPE_TMP
, strlen (config_file
) + 8);
2564 sprintf (config_file_tmp
, "%s.XXXXXX", config_file
);
2566 /* Open file to configuration write. */
2567 fd
= mkstemp (config_file_tmp
);
2570 vty_out (vty
, "Can't open configuration file %s.%s", config_file_tmp
,
2575 /* Make vty for configuration file. */
2576 file_vty
= vty_new ();
2578 file_vty
->type
= VTY_FILE
;
2580 /* Config file header print. */
2581 vty_out (file_vty
, "!\n! Zebra configuration saved from vty\n! ");
2582 vty_time_print (file_vty
, 1);
2583 vty_out (file_vty
, "!\n");
2585 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2586 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
2588 if ((*node
->func
) (file_vty
))
2589 vty_out (file_vty
, "!\n");
2591 vty_close (file_vty
);
2593 if (unlink (config_file_sav
) != 0)
2594 if (errno
!= ENOENT
)
2596 vty_out (vty
, "Can't unlink backup configuration file %s.%s", config_file_sav
,
2600 if (link (config_file
, config_file_sav
) != 0)
2602 vty_out (vty
, "Can't backup old configuration file %s.%s", config_file_sav
,
2607 if (unlink (config_file
) != 0)
2609 vty_out (vty
, "Can't unlink configuration file %s.%s", config_file
,
2613 if (link (config_file_tmp
, config_file
) != 0)
2615 vty_out (vty
, "Can't save configuration file %s.%s", config_file
,
2621 if (chmod (config_file
, CONFIGFILE_MASK
) != 0)
2623 vty_out (vty
, "Can't chmod configuration file %s: %s (%d).%s",
2624 config_file
, safe_strerror(errno
), errno
, VTY_NEWLINE
);
2628 vty_out (vty
, "Configuration saved to %s%s", config_file
,
2633 unlink (config_file_tmp
);
2634 XFREE (MTYPE_TMP
, config_file_tmp
);
2635 XFREE (MTYPE_TMP
, config_file_sav
);
2639 ALIAS (config_write_file
,
2642 "Write running configuration to memory, network, or terminal\n")
2644 ALIAS (config_write_file
,
2645 config_write_memory_cmd
,
2647 "Write running configuration to memory, network, or terminal\n"
2648 "Write configuration to the file (same as write file)\n")
2650 ALIAS (config_write_file
,
2651 copy_runningconfig_startupconfig_cmd
,
2652 "copy running-config startup-config",
2653 "Copy configuration\n"
2654 "Copy running config to... \n"
2655 "Copy running config to startup config (same as write file)\n")
2657 /* Write current configuration into the terminal. */
2658 DEFUN (config_write_terminal
,
2659 config_write_terminal_cmd
,
2661 "Write running configuration to memory, network, or terminal\n"
2662 "Write to terminal\n")
2665 struct cmd_node
*node
;
2667 if (vty
->type
== VTY_SHELL_SERV
)
2669 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2670 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
&& node
->vtysh
)
2672 if ((*node
->func
) (vty
))
2673 vty_out (vty
, "!%s", VTY_NEWLINE
);
2678 vty_out (vty
, "%sCurrent configuration:%s", VTY_NEWLINE
,
2680 vty_out (vty
, "!%s", VTY_NEWLINE
);
2682 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2683 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
2685 if ((*node
->func
) (vty
))
2686 vty_out (vty
, "!%s", VTY_NEWLINE
);
2688 vty_out (vty
, "end%s",VTY_NEWLINE
);
2693 /* Write current configuration into the terminal. */
2694 ALIAS (config_write_terminal
,
2695 show_running_config_cmd
,
2696 "show running-config",
2698 "running configuration\n")
2700 /* Write startup configuration into the terminal. */
2701 DEFUN (show_startup_config
,
2702 show_startup_config_cmd
,
2703 "show startup-config",
2705 "Contentes of startup configuration\n")
2710 confp
= fopen (host
.config
, "r");
2713 vty_out (vty
, "Can't open configuration file [%s]%s",
2714 host
.config
, VTY_NEWLINE
);
2718 while (fgets (buf
, BUFSIZ
, confp
))
2722 while (*cp
!= '\r' && *cp
!= '\n' && *cp
!= '\0')
2726 vty_out (vty
, "%s%s", buf
, VTY_NEWLINE
);
2734 /* Hostname configuration */
2735 DEFUN (config_hostname
,
2738 "Set system's network name\n"
2739 "This system's network name\n")
2741 if (!isalpha((int) *argv
[0]))
2743 vty_out (vty
, "Please specify string starting with alphabet%s", VTY_NEWLINE
);
2748 XFREE (MTYPE_HOST
, host
.name
);
2750 host
.name
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2754 DEFUN (config_no_hostname
,
2756 "no hostname [HOSTNAME]",
2758 "Reset system's network name\n"
2759 "Host name of this router\n")
2762 XFREE (MTYPE_HOST
, host
.name
);
2767 /* VTY interface password set. */
2768 DEFUN (config_password
, password_cmd
,
2769 "password (8|) WORD",
2770 "Assign the terminal connection password\n"
2771 "Specifies a HIDDEN password will follow\n"
2773 "The HIDDEN line password string\n")
2775 /* Argument check. */
2778 vty_out (vty
, "Please specify password.%s", VTY_NEWLINE
);
2784 if (*argv
[0] == '8')
2787 XFREE (MTYPE_HOST
, host
.password
);
2788 host
.password
= NULL
;
2789 if (host
.password_encrypt
)
2790 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2791 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[1]);
2796 vty_out (vty
, "Unknown encryption type.%s", VTY_NEWLINE
);
2801 if (!isalnum ((int) *argv
[0]))
2804 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
2809 XFREE (MTYPE_HOST
, host
.password
);
2810 host
.password
= NULL
;
2814 if (host
.password_encrypt
)
2815 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2816 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[0]));
2819 host
.password
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2824 ALIAS (config_password
, password_text_cmd
,
2826 "Assign the terminal connection password\n"
2827 "The UNENCRYPTED (cleartext) line password\n")
2829 /* VTY enable password set. */
2830 DEFUN (config_enable_password
, enable_password_cmd
,
2831 "enable password (8|) WORD",
2832 "Modify enable password parameters\n"
2833 "Assign the privileged level password\n"
2834 "Specifies a HIDDEN password will follow\n"
2836 "The HIDDEN 'enable' password string\n")
2838 /* Argument check. */
2841 vty_out (vty
, "Please specify password.%s", VTY_NEWLINE
);
2845 /* Crypt type is specified. */
2848 if (*argv
[0] == '8')
2851 XFREE (MTYPE_HOST
, host
.enable
);
2854 if (host
.enable_encrypt
)
2855 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2856 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[1]);
2862 vty_out (vty
, "Unknown encryption type.%s", VTY_NEWLINE
);
2867 if (!isalnum ((int) *argv
[0]))
2870 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
2875 XFREE (MTYPE_HOST
, host
.enable
);
2878 /* Plain password input. */
2881 if (host
.enable_encrypt
)
2882 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2883 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[0]));
2886 host
.enable
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2891 ALIAS (config_enable_password
,
2892 enable_password_text_cmd
,
2893 "enable password LINE",
2894 "Modify enable password parameters\n"
2895 "Assign the privileged level password\n"
2896 "The UNENCRYPTED (cleartext) 'enable' password\n")
2898 /* VTY enable password delete. */
2899 DEFUN (no_config_enable_password
, no_enable_password_cmd
,
2900 "no enable password",
2902 "Modify enable password parameters\n"
2903 "Assign the privileged level password\n")
2906 XFREE (MTYPE_HOST
, host
.enable
);
2909 if (host
.enable_encrypt
)
2910 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2911 host
.enable_encrypt
= NULL
;
2916 DEFUN (service_password_encrypt
,
2917 service_password_encrypt_cmd
,
2918 "service password-encryption",
2919 "Set up miscellaneous service\n"
2920 "Enable encrypted passwords\n")
2929 if (host
.password_encrypt
)
2930 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2931 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.password
));
2935 if (host
.enable_encrypt
)
2936 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2937 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.enable
));
2943 DEFUN (no_service_password_encrypt
,
2944 no_service_password_encrypt_cmd
,
2945 "no service password-encryption",
2947 "Set up miscellaneous service\n"
2948 "Enable encrypted passwords\n")
2955 if (host
.password_encrypt
)
2956 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2957 host
.password_encrypt
= NULL
;
2959 if (host
.enable_encrypt
)
2960 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2961 host
.enable_encrypt
= NULL
;
2966 DEFUN (config_terminal_length
, config_terminal_length_cmd
,
2967 "terminal length <0-512>",
2968 "Set terminal line parameters\n"
2969 "Set number of lines on a screen\n"
2970 "Number of lines on screen (0 for no pausing)\n")
2973 char *endptr
= NULL
;
2975 lines
= strtol (argv
[0], &endptr
, 10);
2976 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
2978 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
2986 DEFUN (config_terminal_no_length
, config_terminal_no_length_cmd
,
2987 "terminal no length",
2988 "Set terminal line parameters\n"
2990 "Set number of lines on a screen\n")
2996 DEFUN (service_terminal_length
, service_terminal_length_cmd
,
2997 "service terminal-length <0-512>",
2998 "Set up miscellaneous service\n"
2999 "System wide terminal length configuration\n"
3000 "Number of lines of VTY (0 means no line control)\n")
3003 char *endptr
= NULL
;
3005 lines
= strtol (argv
[0], &endptr
, 10);
3006 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
3008 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
3016 DEFUN (no_service_terminal_length
, no_service_terminal_length_cmd
,
3017 "no service terminal-length [<0-512>]",
3019 "Set up miscellaneous service\n"
3020 "System wide terminal length configuration\n"
3021 "Number of lines of VTY (0 means no line control)\n")
3027 DEFUN_HIDDEN (do_echo
,
3030 "Echo a message back to the vty\n"
3031 "The message to echo\n")
3035 vty_out (vty
, "%s%s", ((message
= argv_concat(argv
, argc
, 0)) ? message
: ""),
3038 XFREE(MTYPE_TMP
, message
);
3042 DEFUN (config_logmsg
,
3044 "logmsg "LOG_LEVELS
" .MESSAGE",
3045 "Send a message to enabled logging destinations\n"
3047 "The message to send\n")
3052 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3053 return CMD_ERR_NO_MATCH
;
3055 zlog(NULL
, level
, ((message
= argv_concat(argv
, argc
, 1)) ? message
: ""));
3057 XFREE(MTYPE_TMP
, message
);
3061 DEFUN (show_logging
,
3065 "Show current logging configuration\n")
3067 struct zlog
*zl
= zlog_default
;
3069 vty_out (vty
, "Syslog logging: ");
3070 if (zl
->maxlvl
[ZLOG_DEST_SYSLOG
] == ZLOG_DISABLED
)
3071 vty_out (vty
, "disabled");
3073 vty_out (vty
, "level %s, facility %s, ident %s",
3074 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_SYSLOG
]],
3075 facility_name(zl
->facility
), zl
->ident
);
3076 vty_out (vty
, "%s", VTY_NEWLINE
);
3078 vty_out (vty
, "Stdout logging: ");
3079 if (zl
->maxlvl
[ZLOG_DEST_STDOUT
] == ZLOG_DISABLED
)
3080 vty_out (vty
, "disabled");
3082 vty_out (vty
, "level %s",
3083 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_STDOUT
]]);
3084 vty_out (vty
, "%s", VTY_NEWLINE
);
3086 vty_out (vty
, "Monitor logging: ");
3087 if (zl
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
3088 vty_out (vty
, "disabled");
3090 vty_out (vty
, "level %s",
3091 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_MONITOR
]]);
3092 vty_out (vty
, "%s", VTY_NEWLINE
);
3094 vty_out (vty
, "File logging: ");
3095 if ((zl
->maxlvl
[ZLOG_DEST_FILE
] == ZLOG_DISABLED
) ||
3097 vty_out (vty
, "disabled");
3099 vty_out (vty
, "level %s, filename %s",
3100 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_FILE
]],
3102 vty_out (vty
, "%s", VTY_NEWLINE
);
3104 vty_out (vty
, "Protocol name: %s%s",
3105 zlog_proto_names
[zl
->protocol
], VTY_NEWLINE
);
3106 vty_out (vty
, "Record priority: %s%s",
3107 (zl
->record_priority
? "enabled" : "disabled"), VTY_NEWLINE
);
3108 vty_out (vty
, "Timestamp precision: %d%s",
3109 zl
->timestamp_precision
, VTY_NEWLINE
);
3114 DEFUN (config_log_stdout
,
3115 config_log_stdout_cmd
,
3118 "Set stdout logging level\n")
3120 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, zlog_default
->default_lvl
);
3124 DEFUN (config_log_stdout_level
,
3125 config_log_stdout_level_cmd
,
3126 "log stdout "LOG_LEVELS
,
3128 "Set stdout logging level\n"
3133 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3134 return CMD_ERR_NO_MATCH
;
3135 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, level
);
3139 DEFUN (no_config_log_stdout
,
3140 no_config_log_stdout_cmd
,
3141 "no log stdout [LEVEL]",
3144 "Cancel logging to stdout\n"
3147 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, ZLOG_DISABLED
);
3151 DEFUN (config_log_monitor
,
3152 config_log_monitor_cmd
,
3155 "Set terminal line (monitor) logging level\n")
3157 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, zlog_default
->default_lvl
);
3161 DEFUN (config_log_monitor_level
,
3162 config_log_monitor_level_cmd
,
3163 "log monitor "LOG_LEVELS
,
3165 "Set terminal line (monitor) logging level\n"
3170 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3171 return CMD_ERR_NO_MATCH
;
3172 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, level
);
3176 DEFUN (no_config_log_monitor
,
3177 no_config_log_monitor_cmd
,
3178 "no log monitor [LEVEL]",
3181 "Disable terminal line (monitor) logging\n"
3184 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, ZLOG_DISABLED
);
3189 set_log_file(struct vty
*vty
, const char *fname
, int loglevel
)
3193 const char *fullpath
;
3195 /* Path detection. */
3196 if (! IS_DIRECTORY_SEP (*fname
))
3198 char cwd
[MAXPATHLEN
+1];
3199 cwd
[MAXPATHLEN
] = '\0';
3201 if (getcwd (cwd
, MAXPATHLEN
) == NULL
)
3203 zlog_err ("config_log_file: Unable to alloc mem!");
3207 if ( (p
= XMALLOC (MTYPE_TMP
, strlen (cwd
) + strlen (fname
) + 2))
3210 zlog_err ("config_log_file: Unable to alloc mem!");
3213 sprintf (p
, "%s/%s", cwd
, fname
);
3219 ret
= zlog_set_file (NULL
, fullpath
, loglevel
);
3222 XFREE (MTYPE_TMP
, p
);
3226 vty_out (vty
, "can't open logfile %s\n", fname
);
3231 XFREE (MTYPE_HOST
, host
.logfile
);
3233 host
.logfile
= XSTRDUP (MTYPE_HOST
, fname
);
3238 DEFUN (config_log_file
,
3239 config_log_file_cmd
,
3240 "log file FILENAME",
3243 "Logging filename\n")
3245 return set_log_file(vty
, argv
[0], zlog_default
->default_lvl
);
3248 DEFUN (config_log_file_level
,
3249 config_log_file_level_cmd
,
3250 "log file FILENAME "LOG_LEVELS
,
3253 "Logging filename\n"
3258 if ((level
= level_match(argv
[1])) == ZLOG_DISABLED
)
3259 return CMD_ERR_NO_MATCH
;
3260 return set_log_file(vty
, argv
[0], level
);
3263 DEFUN (no_config_log_file
,
3264 no_config_log_file_cmd
,
3265 "no log file [FILENAME]",
3268 "Cancel logging to file\n"
3269 "Logging file name\n")
3271 zlog_reset_file (NULL
);
3274 XFREE (MTYPE_HOST
, host
.logfile
);
3276 host
.logfile
= NULL
;
3281 ALIAS (no_config_log_file
,
3282 no_config_log_file_level_cmd
,
3283 "no log file FILENAME LEVEL",
3286 "Cancel logging to file\n"
3287 "Logging file name\n"
3290 DEFUN (config_log_syslog
,
3291 config_log_syslog_cmd
,
3294 "Set syslog logging level\n")
3296 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
3300 DEFUN (config_log_syslog_level
,
3301 config_log_syslog_level_cmd
,
3302 "log syslog "LOG_LEVELS
,
3304 "Set syslog logging level\n"
3309 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3310 return CMD_ERR_NO_MATCH
;
3311 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, level
);
3315 DEFUN_DEPRECATED (config_log_syslog_facility
,
3316 config_log_syslog_facility_cmd
,
3317 "log syslog facility "LOG_FACILITIES
,
3319 "Logging goes to syslog\n"
3320 "(Deprecated) Facility parameter for syslog messages\n"
3325 if ((facility
= facility_match(argv
[0])) < 0)
3326 return CMD_ERR_NO_MATCH
;
3328 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
3329 zlog_default
->facility
= facility
;
3333 DEFUN (no_config_log_syslog
,
3334 no_config_log_syslog_cmd
,
3335 "no log syslog [LEVEL]",
3338 "Cancel logging to syslog\n"
3341 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, ZLOG_DISABLED
);
3345 ALIAS (no_config_log_syslog
,
3346 no_config_log_syslog_facility_cmd
,
3347 "no log syslog facility "LOG_FACILITIES
,
3350 "Logging goes to syslog\n"
3351 "Facility parameter for syslog messages\n"
3354 DEFUN (config_log_facility
,
3355 config_log_facility_cmd
,
3356 "log facility "LOG_FACILITIES
,
3358 "Facility parameter for syslog messages\n"
3363 if ((facility
= facility_match(argv
[0])) < 0)
3364 return CMD_ERR_NO_MATCH
;
3365 zlog_default
->facility
= facility
;
3369 DEFUN (no_config_log_facility
,
3370 no_config_log_facility_cmd
,
3371 "no log facility [FACILITY]",
3374 "Reset syslog facility to default (daemon)\n"
3375 "Syslog facility\n")
3377 zlog_default
->facility
= LOG_DAEMON
;
3381 DEFUN_DEPRECATED (config_log_trap
,
3382 config_log_trap_cmd
,
3383 "log trap "LOG_LEVELS
,
3385 "(Deprecated) Set logging level and default for all destinations\n"
3391 if ((new_level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3392 return CMD_ERR_NO_MATCH
;
3394 zlog_default
->default_lvl
= new_level
;
3395 for (i
= 0; i
< ZLOG_NUM_DESTS
; i
++)
3396 if (zlog_default
->maxlvl
[i
] != ZLOG_DISABLED
)
3397 zlog_default
->maxlvl
[i
] = new_level
;
3401 DEFUN_DEPRECATED (no_config_log_trap
,
3402 no_config_log_trap_cmd
,
3403 "no log trap [LEVEL]",
3406 "Permit all logging information\n"
3409 zlog_default
->default_lvl
= LOG_DEBUG
;
3413 DEFUN (config_log_record_priority
,
3414 config_log_record_priority_cmd
,
3415 "log record-priority",
3417 "Log the priority of the message within the message\n")
3419 zlog_default
->record_priority
= 1 ;
3423 DEFUN (no_config_log_record_priority
,
3424 no_config_log_record_priority_cmd
,
3425 "no log record-priority",
3428 "Do not log the priority of the message within the message\n")
3430 zlog_default
->record_priority
= 0 ;
3434 DEFUN (config_log_timestamp_precision
,
3435 config_log_timestamp_precision_cmd
,
3436 "log timestamp precision <0-6>",
3438 "Timestamp configuration\n"
3439 "Set the timestamp precision\n"
3440 "Number of subsecond digits\n")
3444 vty_out (vty
, "Insufficient arguments%s", VTY_NEWLINE
);
3448 VTY_GET_INTEGER_RANGE("Timestamp Precision",
3449 zlog_default
->timestamp_precision
, argv
[0], 0, 6);
3453 DEFUN (no_config_log_timestamp_precision
,
3454 no_config_log_timestamp_precision_cmd
,
3455 "no log timestamp precision",
3458 "Timestamp configuration\n"
3459 "Reset the timestamp precision to the default value of 0\n")
3461 zlog_default
->timestamp_precision
= 0 ;
3465 DEFUN (banner_motd_file
,
3466 banner_motd_file_cmd
,
3467 "banner motd file [FILE]",
3470 "Banner from a file\n"
3474 XFREE (MTYPE_HOST
, host
.motdfile
);
3475 host
.motdfile
= XSTRDUP (MTYPE_HOST
, argv
[0]);
3480 DEFUN (banner_motd_default
,
3481 banner_motd_default_cmd
,
3482 "banner motd default",
3483 "Set banner string\n"
3484 "Strings for motd\n"
3487 host
.motd
= default_motd
;
3491 DEFUN (no_banner_motd
,
3495 "Set banner string\n"
3496 "Strings for motd\n")
3500 XFREE (MTYPE_HOST
, host
.motdfile
);
3501 host
.motdfile
= NULL
;
3505 /* Set config filename. Called from vty.c */
3507 host_config_set (char *filename
)
3509 host
.config
= XSTRDUP (MTYPE_HOST
, filename
);
3513 install_default (enum node_type node
)
3515 install_element (node
, &config_exit_cmd
);
3516 install_element (node
, &config_quit_cmd
);
3517 install_element (node
, &config_end_cmd
);
3518 install_element (node
, &config_help_cmd
);
3519 install_element (node
, &config_list_cmd
);
3521 install_element (node
, &config_write_terminal_cmd
);
3522 install_element (node
, &config_write_file_cmd
);
3523 install_element (node
, &config_write_memory_cmd
);
3524 install_element (node
, &config_write_cmd
);
3525 install_element (node
, &show_running_config_cmd
);
3528 /* Initialize command interface. Install basic nodes and commands. */
3530 cmd_init (int terminal
)
3532 /* Allocate initial top vector of commands. */
3533 cmdvec
= vector_init (VECTOR_MIN_SIZE
);
3535 /* Default host value settings. */
3537 host
.password
= NULL
;
3539 host
.logfile
= NULL
;
3542 host
.motd
= default_motd
;
3543 host
.motdfile
= NULL
;
3545 /* Install top nodes. */
3546 install_node (&view_node
, NULL
);
3547 install_node (&enable_node
, NULL
);
3548 install_node (&auth_node
, NULL
);
3549 install_node (&auth_enable_node
, NULL
);
3550 install_node (&restricted_node
, NULL
);
3551 install_node (&config_node
, config_write_host
);
3553 /* Each node's basic commands. */
3554 install_element (VIEW_NODE
, &show_version_cmd
);
3557 install_element (VIEW_NODE
, &config_list_cmd
);
3558 install_element (VIEW_NODE
, &config_exit_cmd
);
3559 install_element (VIEW_NODE
, &config_quit_cmd
);
3560 install_element (VIEW_NODE
, &config_help_cmd
);
3561 install_element (VIEW_NODE
, &config_enable_cmd
);
3562 install_element (VIEW_NODE
, &config_terminal_length_cmd
);
3563 install_element (VIEW_NODE
, &config_terminal_no_length_cmd
);
3564 install_element (VIEW_NODE
, &show_logging_cmd
);
3565 install_element (VIEW_NODE
, &echo_cmd
);
3567 install_element (RESTRICTED_NODE
, &config_list_cmd
);
3568 install_element (RESTRICTED_NODE
, &config_exit_cmd
);
3569 install_element (RESTRICTED_NODE
, &config_quit_cmd
);
3570 install_element (RESTRICTED_NODE
, &config_help_cmd
);
3571 install_element (RESTRICTED_NODE
, &config_enable_cmd
);
3572 install_element (RESTRICTED_NODE
, &config_terminal_length_cmd
);
3573 install_element (RESTRICTED_NODE
, &config_terminal_no_length_cmd
);
3574 install_element (RESTRICTED_NODE
, &echo_cmd
);
3579 install_default (ENABLE_NODE
);
3580 install_element (ENABLE_NODE
, &config_disable_cmd
);
3581 install_element (ENABLE_NODE
, &config_terminal_cmd
);
3582 install_element (ENABLE_NODE
, ©_runningconfig_startupconfig_cmd
);
3584 install_element (ENABLE_NODE
, &show_startup_config_cmd
);
3585 install_element (ENABLE_NODE
, &show_version_cmd
);
3589 install_element (ENABLE_NODE
, &config_terminal_length_cmd
);
3590 install_element (ENABLE_NODE
, &config_terminal_no_length_cmd
);
3591 install_element (ENABLE_NODE
, &show_logging_cmd
);
3592 install_element (ENABLE_NODE
, &echo_cmd
);
3593 install_element (ENABLE_NODE
, &config_logmsg_cmd
);
3595 install_default (CONFIG_NODE
);
3598 install_element (CONFIG_NODE
, &hostname_cmd
);
3599 install_element (CONFIG_NODE
, &no_hostname_cmd
);
3603 install_element (CONFIG_NODE
, &password_cmd
);
3604 install_element (CONFIG_NODE
, &password_text_cmd
);
3605 install_element (CONFIG_NODE
, &enable_password_cmd
);
3606 install_element (CONFIG_NODE
, &enable_password_text_cmd
);
3607 install_element (CONFIG_NODE
, &no_enable_password_cmd
);
3609 install_element (CONFIG_NODE
, &config_log_stdout_cmd
);
3610 install_element (CONFIG_NODE
, &config_log_stdout_level_cmd
);
3611 install_element (CONFIG_NODE
, &no_config_log_stdout_cmd
);
3612 install_element (CONFIG_NODE
, &config_log_monitor_cmd
);
3613 install_element (CONFIG_NODE
, &config_log_monitor_level_cmd
);
3614 install_element (CONFIG_NODE
, &no_config_log_monitor_cmd
);
3615 install_element (CONFIG_NODE
, &config_log_file_cmd
);
3616 install_element (CONFIG_NODE
, &config_log_file_level_cmd
);
3617 install_element (CONFIG_NODE
, &no_config_log_file_cmd
);
3618 install_element (CONFIG_NODE
, &no_config_log_file_level_cmd
);
3619 install_element (CONFIG_NODE
, &config_log_syslog_cmd
);
3620 install_element (CONFIG_NODE
, &config_log_syslog_level_cmd
);
3621 install_element (CONFIG_NODE
, &config_log_syslog_facility_cmd
);
3622 install_element (CONFIG_NODE
, &no_config_log_syslog_cmd
);
3623 install_element (CONFIG_NODE
, &no_config_log_syslog_facility_cmd
);
3624 install_element (CONFIG_NODE
, &config_log_facility_cmd
);
3625 install_element (CONFIG_NODE
, &no_config_log_facility_cmd
);
3626 install_element (CONFIG_NODE
, &config_log_trap_cmd
);
3627 install_element (CONFIG_NODE
, &no_config_log_trap_cmd
);
3628 install_element (CONFIG_NODE
, &config_log_record_priority_cmd
);
3629 install_element (CONFIG_NODE
, &no_config_log_record_priority_cmd
);
3630 install_element (CONFIG_NODE
, &config_log_timestamp_precision_cmd
);
3631 install_element (CONFIG_NODE
, &no_config_log_timestamp_precision_cmd
);
3632 install_element (CONFIG_NODE
, &service_password_encrypt_cmd
);
3633 install_element (CONFIG_NODE
, &no_service_password_encrypt_cmd
);
3634 install_element (CONFIG_NODE
, &banner_motd_default_cmd
);
3635 install_element (CONFIG_NODE
, &banner_motd_file_cmd
);
3636 install_element (CONFIG_NODE
, &no_banner_motd_cmd
);
3637 install_element (CONFIG_NODE
, &service_terminal_length_cmd
);
3638 install_element (CONFIG_NODE
, &no_service_terminal_length_cmd
);
3640 install_element (VIEW_NODE
, &show_thread_cpu_cmd
);
3641 install_element (ENABLE_NODE
, &show_thread_cpu_cmd
);
3642 install_element (RESTRICTED_NODE
, &show_thread_cpu_cmd
);
3643 install_element (VIEW_NODE
, &show_work_queues_cmd
);
3644 install_element (ENABLE_NODE
, &show_work_queues_cmd
);