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. */
41 char *command_cr
= NULL
;
43 /* Host information structure. */
46 /* Standard command node structures. */
47 static struct cmd_node auth_node
=
53 static struct cmd_node view_node
=
59 static struct cmd_node restricted_node
=
65 static struct cmd_node auth_enable_node
=
71 static struct cmd_node enable_node
=
77 static struct cmd_node config_node
=
84 /* Default motd string. */
85 const char *default_motd
=
87 Hello, this is " QUAGGA_PROGNAME
" (version " QUAGGA_VERSION
").\r\n\
88 " QUAGGA_COPYRIGHT
"\r\n\
92 static struct facility_map
{
96 } syslog_facilities
[] =
98 { LOG_KERN
, "kern", 1 },
99 { LOG_USER
, "user", 2 },
100 { LOG_MAIL
, "mail", 1 },
101 { LOG_DAEMON
, "daemon", 1 },
102 { LOG_AUTH
, "auth", 1 },
103 { LOG_SYSLOG
, "syslog", 1 },
104 { LOG_LPR
, "lpr", 2 },
105 { LOG_NEWS
, "news", 1 },
106 { LOG_UUCP
, "uucp", 2 },
107 { LOG_CRON
, "cron", 1 },
109 { LOG_FTP
, "ftp", 1 },
111 { LOG_LOCAL0
, "local0", 6 },
112 { LOG_LOCAL1
, "local1", 6 },
113 { LOG_LOCAL2
, "local2", 6 },
114 { LOG_LOCAL3
, "local3", 6 },
115 { LOG_LOCAL4
, "local4", 6 },
116 { LOG_LOCAL5
, "local5", 6 },
117 { LOG_LOCAL6
, "local6", 6 },
118 { LOG_LOCAL7
, "local7", 6 },
123 facility_name(int facility
)
125 struct facility_map
*fm
;
127 for (fm
= syslog_facilities
; fm
->name
; fm
++)
128 if (fm
->facility
== facility
)
134 facility_match(const char *str
)
136 struct facility_map
*fm
;
138 for (fm
= syslog_facilities
; fm
->name
; fm
++)
139 if (!strncmp(str
,fm
->name
,fm
->match
))
145 level_match(const char *s
)
149 for ( level
= 0 ; zlog_priority
[level
] != NULL
; level
++ )
150 if (!strncmp (s
, zlog_priority
[level
], 2))
152 return ZLOG_DISABLED
;
155 /* This is called from main when a daemon is invoked with -v or --version. */
157 print_version (const char *progname
)
159 printf ("%s version %s\n", progname
, QUAGGA_VERSION
);
160 printf ("%s\n", QUAGGA_COPYRIGHT
);
164 /* Utility function to concatenate argv argument into a single string
165 with inserting ' ' character between each argument. */
167 argv_concat (const char **argv
, int argc
, int shift
)
175 for (i
= shift
; i
< argc
; i
++)
176 len
+= strlen(argv
[i
])+1;
179 p
= str
= XMALLOC(MTYPE_TMP
, len
);
180 for (i
= shift
; i
< argc
; i
++)
183 memcpy(p
, argv
[i
], (arglen
= strlen(argv
[i
])));
191 /* Install top node of command vector. */
193 install_node (struct cmd_node
*node
,
194 int (*func
) (struct vty
*))
196 vector_set_index (cmdvec
, node
->node
, node
);
198 node
->cmd_vector
= vector_init (VECTOR_MIN_SIZE
);
201 /* Compare two command's string. Used in sort_node (). */
203 cmp_node (const void *p
, const void *q
)
205 const struct cmd_element
*a
= *(struct cmd_element
* const *)p
;
206 const struct cmd_element
*b
= *(struct cmd_element
* const *)q
;
208 return strcmp (a
->string
, b
->string
);
212 cmp_desc (const void *p
, const void *q
)
214 const struct desc
*a
= *(struct desc
* const *)p
;
215 const struct desc
*b
= *(struct desc
* const *)q
;
217 return strcmp (a
->cmd
, b
->cmd
);
220 /* Sort each node's command element according to command string. */
225 struct cmd_node
*cnode
;
227 struct cmd_element
*cmd_element
;
229 for (i
= 0; i
< vector_active (cmdvec
); i
++)
230 if ((cnode
= vector_slot (cmdvec
, i
)) != NULL
)
232 vector cmd_vector
= cnode
->cmd_vector
;
233 qsort (cmd_vector
->index
, vector_active (cmd_vector
),
234 sizeof (void *), cmp_node
);
236 for (j
= 0; j
< vector_active (cmd_vector
); j
++)
237 if ((cmd_element
= vector_slot (cmd_vector
, j
)) != NULL
238 && vector_active (cmd_element
->strvec
))
240 descvec
= vector_slot (cmd_element
->strvec
,
241 vector_active (cmd_element
->strvec
) - 1);
242 qsort (descvec
->index
, vector_active (descvec
),
243 sizeof (void *), cmp_desc
);
248 /* Breaking up string into each command piece. I assume given
249 character is separated by a space character. Return value is a
250 vector which includes char ** data element. */
252 cmd_make_strvec (const char *string
)
254 const char *cp
, *start
;
264 /* Skip white spaces. */
265 while (isspace ((int) *cp
) && *cp
!= '\0')
268 /* Return if there is only white spaces */
272 if (*cp
== '!' || *cp
== '#')
275 /* Prepare return vector. */
276 strvec
= vector_init (VECTOR_MIN_SIZE
);
278 /* Copy each command piece and set into vector. */
282 while (!(isspace ((int) *cp
) || *cp
== '\r' || *cp
== '\n') &&
286 token
= XMALLOC (MTYPE_STRVEC
, strlen
+ 1);
287 memcpy (token
, start
, strlen
);
288 *(token
+ strlen
) = '\0';
289 vector_set (strvec
, token
);
291 while ((isspace ((int) *cp
) || *cp
== '\n' || *cp
== '\r') &&
300 /* Free allocated string vector. */
302 cmd_free_strvec (vector v
)
310 for (i
= 0; i
< vector_active (v
); i
++)
311 if ((cp
= vector_slot (v
, i
)) != NULL
)
312 XFREE (MTYPE_STRVEC
, cp
);
317 /* Fetch next description. Used in cmd_make_descvec(). */
319 cmd_desc_str (const char **string
)
321 const char *cp
, *start
;
330 /* Skip white spaces. */
331 while (isspace ((int) *cp
) && *cp
!= '\0')
334 /* Return if there is only white spaces */
340 while (!(*cp
== '\r' || *cp
== '\n') && *cp
!= '\0')
344 token
= XMALLOC (MTYPE_STRVEC
, strlen
+ 1);
345 memcpy (token
, start
, strlen
);
346 *(token
+ strlen
) = '\0';
353 /* New string vector. */
355 cmd_make_descvec (const char *string
, const char *descstr
)
364 vector strvec
= NULL
;
373 allvec
= vector_init (VECTOR_MIN_SIZE
);
377 while (isspace ((int) *cp
) && *cp
!= '\0')
394 fprintf (stderr
, "Command parse error!: %s\n", string
);
400 while (isspace ((int) *cp
) && *cp
!= '\0')
414 while (! (isspace ((int) *cp
) || *cp
== '\r' || *cp
== '\n' || *cp
== ')' || *cp
== '|') && *cp
!= '\0')
419 token
= XMALLOC (MTYPE_STRVEC
, len
+ 1);
420 memcpy (token
, sp
, len
);
421 *(token
+ len
) = '\0';
423 desc
= XCALLOC (MTYPE_DESC
, sizeof (struct desc
));
425 desc
->str
= cmd_desc_str (&dp
);
431 strvec
= vector_init (VECTOR_MIN_SIZE
);
432 vector_set (allvec
, strvec
);
438 strvec
= vector_init (VECTOR_MIN_SIZE
);
439 vector_set (allvec
, strvec
);
441 vector_set (strvec
, desc
);
445 /* Count mandantory string vector size. This is to determine inputed
446 command has enough command length. */
448 cmd_cmdsize (vector strvec
)
455 for (i
= 0; i
< vector_active (strvec
); i
++)
456 if ((descvec
= vector_slot (strvec
, i
)) != NULL
)
458 if ((vector_active (descvec
)) == 1
459 && (desc
= vector_slot (descvec
, 0)) != NULL
)
461 if (desc
->cmd
== NULL
|| CMD_OPTION (desc
->cmd
))
472 /* Return prompt character of specified node. */
474 cmd_prompt (enum node_type node
)
476 struct cmd_node
*cnode
;
478 cnode
= vector_slot (cmdvec
, node
);
479 return cnode
->prompt
;
482 /* Install a command into a node. */
484 install_element (enum node_type ntype
, struct cmd_element
*cmd
)
486 struct cmd_node
*cnode
;
488 /* cmd_init hasn't been called */
492 cnode
= vector_slot (cmdvec
, ntype
);
496 fprintf (stderr
, "Command node %d doesn't exist, please check it\n",
501 vector_set (cnode
->cmd_vector
, cmd
);
503 if (cmd
->strvec
== NULL
)
504 cmd
->strvec
= cmd_make_descvec (cmd
->string
, cmd
->doc
);
506 cmd
->cmdsize
= cmd_cmdsize (cmd
->strvec
);
509 static unsigned char itoa64
[] =
510 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
513 to64(char *s
, long v
, int n
)
517 *s
++ = itoa64
[v
&0x3f];
523 zencrypt (const char *passwd
)
527 char *crypt (const char *, const char *);
531 to64(&salt
[0], random(), 3);
532 to64(&salt
[3], tv
.tv_usec
, 3);
535 return crypt (passwd
, salt
);
538 /* This function write configuration of this host. */
540 config_write_host (struct vty
*vty
)
543 vty_out (vty
, "hostname %s%s", host
.name
, VTY_NEWLINE
);
547 if (host
.password_encrypt
)
548 vty_out (vty
, "password 8 %s%s", host
.password_encrypt
, VTY_NEWLINE
);
549 if (host
.enable_encrypt
)
550 vty_out (vty
, "enable password 8 %s%s", host
.enable_encrypt
, VTY_NEWLINE
);
555 vty_out (vty
, "password %s%s", host
.password
, VTY_NEWLINE
);
557 vty_out (vty
, "enable password %s%s", host
.enable
, VTY_NEWLINE
);
560 if (zlog_default
->default_lvl
!= LOG_DEBUG
)
562 vty_out (vty
, "! N.B. The 'log trap' command is deprecated.%s",
564 vty_out (vty
, "log trap %s%s",
565 zlog_priority
[zlog_default
->default_lvl
], VTY_NEWLINE
);
568 if (host
.logfile
&& (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != ZLOG_DISABLED
))
570 vty_out (vty
, "log file %s", host
.logfile
);
571 if (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != zlog_default
->default_lvl
)
573 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_FILE
]]);
574 vty_out (vty
, "%s", VTY_NEWLINE
);
577 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != ZLOG_DISABLED
)
579 vty_out (vty
, "log stdout");
580 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != zlog_default
->default_lvl
)
582 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
]]);
583 vty_out (vty
, "%s", VTY_NEWLINE
);
586 if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
587 vty_out(vty
,"no log monitor%s",VTY_NEWLINE
);
588 else if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] != zlog_default
->default_lvl
)
589 vty_out(vty
,"log monitor %s%s",
590 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
]],VTY_NEWLINE
);
592 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != ZLOG_DISABLED
)
594 vty_out (vty
, "log syslog");
595 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != zlog_default
->default_lvl
)
597 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
]]);
598 vty_out (vty
, "%s", VTY_NEWLINE
);
601 if (zlog_default
->facility
!= LOG_DAEMON
)
602 vty_out (vty
, "log facility %s%s",
603 facility_name(zlog_default
->facility
), VTY_NEWLINE
);
605 if (zlog_default
->record_priority
== 1)
606 vty_out (vty
, "log record-priority%s", VTY_NEWLINE
);
608 if (zlog_default
->timestamp_precision
> 0)
609 vty_out (vty
, "log timestamp precision %d%s",
610 zlog_default
->timestamp_precision
, VTY_NEWLINE
);
613 vty_out (vty
, "service advanced-vty%s", VTY_NEWLINE
);
616 vty_out (vty
, "service password-encryption%s", VTY_NEWLINE
);
619 vty_out (vty
, "service terminal-length %d%s", host
.lines
,
623 vty_out (vty
, "banner motd file %s%s", host
.motdfile
, VTY_NEWLINE
);
624 else if (! host
.motd
)
625 vty_out (vty
, "no banner motd%s", VTY_NEWLINE
);
630 /* Utility function for getting command vector. */
632 cmd_node_vector (vector v
, enum node_type ntype
)
634 struct cmd_node
*cnode
= vector_slot (v
, ntype
);
635 return cnode
->cmd_vector
;
639 /* Filter command vector by symbol. This function is not actually used;
640 * should it be deleted? */
642 cmd_filter_by_symbol (char *command
, char *symbol
)
646 if (strcmp (symbol
, "IPV4_ADDRESS") == 0)
649 lim
= strlen (command
);
652 if (! (isdigit ((int) command
[i
]) || command
[i
] == '.' || command
[i
] == '/'))
658 if (strcmp (symbol
, "STRING") == 0)
661 lim
= strlen (command
);
664 if (! (isalpha ((int) command
[i
]) || command
[i
] == '_' || command
[i
] == '-'))
670 if (strcmp (symbol
, "IFNAME") == 0)
673 lim
= strlen (command
);
676 if (! isalnum ((int) command
[i
]))
686 /* Completion match types. */
701 static enum match_type
702 cmd_ipv4_match (const char *str
)
705 int dots
= 0, nums
= 0;
713 memset (buf
, 0, sizeof (buf
));
722 if (*(str
+ 1) == '.')
725 if (*(str
+ 1) == '\0')
731 if (!isdigit ((int) *str
))
740 strncpy (buf
, sp
, str
- sp
);
741 if (atoi (buf
) > 255)
758 static enum match_type
759 cmd_ipv4_prefix_match (const char *str
)
770 memset (buf
, 0, sizeof (buf
));
772 while (*str
!= '\0' && *str
!= '/')
779 if (*(str
+ 1) == '.' || *(str
+ 1) == '/')
782 if (*(str
+ 1) == '\0')
789 if (!isdigit ((int) *str
))
798 strncpy (buf
, sp
, str
- sp
);
799 if (atoi (buf
) > 255)
806 if (*(str
+ 1) == '\0')
812 else if (*str
== '\0')
825 if (!isdigit ((int) *str
))
837 #define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
838 #define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
839 #define STATE_START 1
840 #define STATE_COLON 2
841 #define STATE_DOUBLE 3
844 #define STATE_SLASH 6
849 static enum match_type
850 cmd_ipv6_match (const char *str
)
852 int state
= STATE_START
;
853 int colons
= 0, nums
= 0, double_colon
= 0;
854 const char *sp
= NULL
;
855 struct sockaddr_in6 sin6_dummy
;
861 if (strspn (str
, IPV6_ADDR_STR
) != strlen (str
))
864 /* use inet_pton that has a better support,
865 * for example inet_pton can support the automatic addresses:
868 ret
= inet_pton(AF_INET6
, str
, &sin6_dummy
.sin6_addr
);
880 if (*(str
+ 1) != ':' && *(str
+ 1) != '\0')
894 if (*(str
+ 1) == ':')
895 state
= STATE_DOUBLE
;
906 if (*(str
+ 1) == ':')
910 if (*(str
+ 1) != '\0')
920 if (*(str
+ 1) == ':' || *(str
+ 1) == '\0')
928 if (*(str
+ 1) == '.')
955 static enum match_type
956 cmd_ipv6_prefix_match (const char *str
)
958 int state
= STATE_START
;
959 int colons
= 0, nums
= 0, double_colon
= 0;
961 const char *sp
= NULL
;
967 if (strspn (str
, IPV6_PREFIX_STR
) != strlen (str
))
970 while (*str
!= '\0' && state
!= STATE_MASK
)
977 if (*(str
+ 1) != ':' && *(str
+ 1) != '\0')
991 if (*(str
+ 1) == '/')
993 else if (*(str
+ 1) == ':')
994 state
= STATE_DOUBLE
;
1005 if (*(str
+ 1) == ':')
1009 if (*(str
+ 1) != '\0' && *(str
+ 1) != '/')
1013 if (*(str
+ 1) == '/')
1014 state
= STATE_SLASH
;
1023 if (*(str
+ 1) == ':' || *(str
+ 1) == '.'
1024 || *(str
+ 1) == '\0' || *(str
+ 1) == '/')
1029 for (; sp
<= str
; sp
++)
1035 if (*(str
+ 1) == ':')
1036 state
= STATE_COLON
;
1037 else if (*(str
+ 1) == '.')
1039 else if (*(str
+ 1) == '/')
1040 state
= STATE_SLASH
;
1047 if (*(str
+ 1) == '\0')
1048 return partly_match
;
1065 if (state
< STATE_MASK
)
1066 return partly_match
;
1068 mask
= strtol (str
, &endptr
, 10);
1069 if (*endptr
!= '\0')
1072 if (mask
< 0 || mask
> 128)
1075 /* I don't know why mask < 13 makes command match partly.
1076 Forgive me to make this comments. I Want to set static default route
1077 because of lack of function to originate default in ospf6d; sorry
1080 return partly_match;
1086 #endif /* HAVE_IPV6 */
1088 #define DECIMAL_STRLEN_MAX 10
1091 cmd_range_match (const char *range
, const char *str
)
1094 char buf
[DECIMAL_STRLEN_MAX
+ 1];
1095 char *endptr
= NULL
;
1096 unsigned long min
, max
, val
;
1101 val
= strtoul (str
, &endptr
, 10);
1102 if (*endptr
!= '\0')
1106 p
= strchr (range
, '-');
1109 if (p
- range
> DECIMAL_STRLEN_MAX
)
1111 strncpy (buf
, range
, p
- range
);
1112 buf
[p
- range
] = '\0';
1113 min
= strtoul (buf
, &endptr
, 10);
1114 if (*endptr
!= '\0')
1118 p
= strchr (range
, '>');
1121 if (p
- range
> DECIMAL_STRLEN_MAX
)
1123 strncpy (buf
, range
, p
- range
);
1124 buf
[p
- range
] = '\0';
1125 max
= strtoul (buf
, &endptr
, 10);
1126 if (*endptr
!= '\0')
1129 if (val
< min
|| val
> max
)
1135 /* Make completion match and return match type flag. */
1136 static enum match_type
1137 cmd_filter_by_completion (char *command
, vector v
, unsigned int index
)
1141 struct cmd_element
*cmd_element
;
1142 enum match_type match_type
;
1146 match_type
= no_match
;
1148 /* If command and cmd_element string does not match set NULL to vector */
1149 for (i
= 0; i
< vector_active (v
); i
++)
1150 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1152 if (index
>= vector_active (cmd_element
->strvec
))
1153 vector_slot (v
, i
) = NULL
;
1159 descvec
= vector_slot (cmd_element
->strvec
, index
);
1161 for (j
= 0; j
< vector_active (descvec
); j
++)
1162 if ((desc
= vector_slot (descvec
, j
)))
1166 if (CMD_VARARG (str
))
1168 if (match_type
< vararg_match
)
1169 match_type
= vararg_match
;
1172 else if (CMD_RANGE (str
))
1174 if (cmd_range_match (str
, command
))
1176 if (match_type
< range_match
)
1177 match_type
= range_match
;
1183 else if (CMD_IPV6 (str
))
1185 if (cmd_ipv6_match (command
))
1187 if (match_type
< ipv6_match
)
1188 match_type
= ipv6_match
;
1193 else if (CMD_IPV6_PREFIX (str
))
1195 if (cmd_ipv6_prefix_match (command
))
1197 if (match_type
< ipv6_prefix_match
)
1198 match_type
= ipv6_prefix_match
;
1203 #endif /* HAVE_IPV6 */
1204 else if (CMD_IPV4 (str
))
1206 if (cmd_ipv4_match (command
))
1208 if (match_type
< ipv4_match
)
1209 match_type
= ipv4_match
;
1214 else if (CMD_IPV4_PREFIX (str
))
1216 if (cmd_ipv4_prefix_match (command
))
1218 if (match_type
< ipv4_prefix_match
)
1219 match_type
= ipv4_prefix_match
;
1224 /* Check is this point's argument optional ? */
1225 if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1227 if (match_type
< extend_match
)
1228 match_type
= extend_match
;
1231 else if (strncmp (command
, str
, strlen (command
)) == 0)
1233 if (strcmp (command
, str
) == 0)
1234 match_type
= exact_match
;
1237 if (match_type
< partly_match
)
1238 match_type
= partly_match
;
1244 vector_slot (v
, i
) = NULL
;
1250 /* Filter vector by command character with index. */
1251 static enum match_type
1252 cmd_filter_by_string (char *command
, vector v
, unsigned int index
)
1256 struct cmd_element
*cmd_element
;
1257 enum match_type match_type
;
1261 match_type
= no_match
;
1263 /* If command and cmd_element string does not match set NULL to vector */
1264 for (i
= 0; i
< vector_active (v
); i
++)
1265 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1267 /* If given index is bigger than max string vector of command,
1269 if (index
>= vector_active (cmd_element
->strvec
))
1270 vector_slot (v
, i
) = NULL
;
1276 descvec
= vector_slot (cmd_element
->strvec
, index
);
1278 for (j
= 0; j
< vector_active (descvec
); j
++)
1279 if ((desc
= vector_slot (descvec
, j
)))
1283 if (CMD_VARARG (str
))
1285 if (match_type
< vararg_match
)
1286 match_type
= vararg_match
;
1289 else if (CMD_RANGE (str
))
1291 if (cmd_range_match (str
, command
))
1293 if (match_type
< range_match
)
1294 match_type
= range_match
;
1299 else if (CMD_IPV6 (str
))
1301 if (cmd_ipv6_match (command
) == exact_match
)
1303 if (match_type
< ipv6_match
)
1304 match_type
= ipv6_match
;
1308 else if (CMD_IPV6_PREFIX (str
))
1310 if (cmd_ipv6_prefix_match (command
) == exact_match
)
1312 if (match_type
< ipv6_prefix_match
)
1313 match_type
= ipv6_prefix_match
;
1317 #endif /* HAVE_IPV6 */
1318 else if (CMD_IPV4 (str
))
1320 if (cmd_ipv4_match (command
) == exact_match
)
1322 if (match_type
< ipv4_match
)
1323 match_type
= ipv4_match
;
1327 else if (CMD_IPV4_PREFIX (str
))
1329 if (cmd_ipv4_prefix_match (command
) == exact_match
)
1331 if (match_type
< ipv4_prefix_match
)
1332 match_type
= ipv4_prefix_match
;
1336 else if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1338 if (match_type
< extend_match
)
1339 match_type
= extend_match
;
1344 if (strcmp (command
, str
) == 0)
1346 match_type
= exact_match
;
1352 vector_slot (v
, i
) = NULL
;
1358 /* Check ambiguous match */
1360 is_cmd_ambiguous (char *command
, vector v
, int index
, enum match_type type
)
1364 const char *str
= NULL
;
1365 struct cmd_element
*cmd_element
;
1366 const char *matched
= NULL
;
1370 for (i
= 0; i
< vector_active (v
); i
++)
1371 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1375 descvec
= vector_slot (cmd_element
->strvec
, index
);
1377 for (j
= 0; j
< vector_active (descvec
); j
++)
1378 if ((desc
= vector_slot (descvec
, j
)))
1380 enum match_type ret
;
1387 if (!(CMD_OPTION (str
) || CMD_VARIABLE (str
))
1388 && strcmp (command
, str
) == 0)
1392 if (!(CMD_OPTION (str
) || CMD_VARIABLE (str
))
1393 && strncmp (command
, str
, strlen (command
)) == 0)
1395 if (matched
&& strcmp (matched
, str
) != 0)
1396 return 1; /* There is ambiguous match. */
1403 if (cmd_range_match (str
, command
))
1405 if (matched
&& strcmp (matched
, str
) != 0)
1417 case ipv6_prefix_match
:
1418 if ((ret
= cmd_ipv6_prefix_match (command
)) != no_match
)
1420 if (ret
== partly_match
)
1421 return 2; /* There is incomplete match. */
1426 #endif /* HAVE_IPV6 */
1431 case ipv4_prefix_match
:
1432 if ((ret
= cmd_ipv4_prefix_match (command
)) != no_match
)
1434 if (ret
== partly_match
)
1435 return 2; /* There is incomplete match. */
1441 if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1450 vector_slot (v
, i
) = NULL
;
1455 /* If src matches dst return dst string, otherwise return NULL */
1457 cmd_entry_function (const char *src
, const char *dst
)
1459 /* Skip variable arguments. */
1460 if (CMD_OPTION (dst
) || CMD_VARIABLE (dst
) || CMD_VARARG (dst
) ||
1461 CMD_IPV4 (dst
) || CMD_IPV4_PREFIX (dst
) || CMD_RANGE (dst
))
1464 /* In case of 'command \t', given src is NULL string. */
1468 /* Matched with input string. */
1469 if (strncmp (src
, dst
, strlen (src
)) == 0)
1475 /* If src matches dst return dst string, otherwise return NULL */
1476 /* This version will return the dst string always if it is
1477 CMD_VARIABLE for '?' key processing */
1479 cmd_entry_function_desc (const char *src
, const char *dst
)
1481 if (CMD_VARARG (dst
))
1484 if (CMD_RANGE (dst
))
1486 if (cmd_range_match (dst
, src
))
1495 if (cmd_ipv6_match (src
))
1501 if (CMD_IPV6_PREFIX (dst
))
1503 if (cmd_ipv6_prefix_match (src
))
1508 #endif /* HAVE_IPV6 */
1512 if (cmd_ipv4_match (src
))
1518 if (CMD_IPV4_PREFIX (dst
))
1520 if (cmd_ipv4_prefix_match (src
))
1526 /* Optional or variable commands always match on '?' */
1527 if (CMD_OPTION (dst
) || CMD_VARIABLE (dst
))
1530 /* In case of 'command \t', given src is NULL string. */
1534 if (strncmp (src
, dst
, strlen (src
)) == 0)
1540 /* Check same string element existence. If it isn't there return
1543 cmd_unique_string (vector v
, const char *str
)
1548 for (i
= 0; i
< vector_active (v
); i
++)
1549 if ((match
= vector_slot (v
, i
)) != NULL
)
1550 if (strcmp (match
, str
) == 0)
1555 /* Compare string to description vector. If there is same string
1556 return 1 else return 0. */
1558 desc_unique_string (vector v
, const char *str
)
1563 for (i
= 0; i
< vector_active (v
); i
++)
1564 if ((desc
= vector_slot (v
, i
)) != NULL
)
1565 if (strcmp (desc
->cmd
, str
) == 0)
1571 cmd_try_do_shortcut (enum node_type node
, char* first_word
) {
1572 if ( first_word
!= NULL
&&
1573 node
!= AUTH_NODE
&&
1574 node
!= VIEW_NODE
&&
1575 node
!= AUTH_ENABLE_NODE
&&
1576 node
!= ENABLE_NODE
&&
1577 node
!= RESTRICTED_NODE
&&
1578 0 == strcmp( "do", first_word
) )
1583 /* '?' describe command support. */
1585 cmd_describe_command_real (vector vline
, struct vty
*vty
, int *status
)
1589 #define INIT_MATCHVEC_SIZE 10
1591 struct cmd_element
*cmd_element
;
1594 enum match_type match
;
1598 if (vector_active (vline
) == 0)
1600 *status
= CMD_ERR_NO_MATCH
;
1604 index
= vector_active (vline
) - 1;
1606 /* Make copy vector of current node's command vector. */
1607 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
1609 /* Prepare match vector */
1610 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1612 /* Filter commands. */
1613 /* Only words precedes current word will be checked in this loop. */
1614 for (i
= 0; i
< index
; i
++)
1615 if ((command
= vector_slot (vline
, i
)))
1617 match
= cmd_filter_by_completion (command
, cmd_vector
, i
);
1619 if (match
== vararg_match
)
1621 struct cmd_element
*cmd_element
;
1625 for (j
= 0; j
< vector_active (cmd_vector
); j
++)
1626 if ((cmd_element
= vector_slot (cmd_vector
, j
)) != NULL
1627 && (vector_active (cmd_element
->strvec
)))
1629 descvec
= vector_slot (cmd_element
->strvec
,
1630 vector_active (cmd_element
->strvec
) - 1);
1631 for (k
= 0; k
< vector_active (descvec
); k
++)
1633 struct desc
*desc
= vector_slot (descvec
, k
);
1634 vector_set (matchvec
, desc
);
1638 vector_set (matchvec
, &desc_cr
);
1639 vector_free (cmd_vector
);
1644 if ((ret
= is_cmd_ambiguous (command
, cmd_vector
, i
, match
)) == 1)
1646 vector_free (cmd_vector
);
1647 vector_free (matchvec
);
1648 *status
= CMD_ERR_AMBIGUOUS
;
1653 vector_free (cmd_vector
);
1654 vector_free (matchvec
);
1655 *status
= CMD_ERR_NO_MATCH
;
1660 /* Prepare match vector */
1661 /* matchvec = vector_init (INIT_MATCHVEC_SIZE); */
1663 /* Make sure that cmd_vector is filtered based on current word */
1664 command
= vector_slot (vline
, index
);
1666 match
= cmd_filter_by_completion (command
, cmd_vector
, index
);
1668 /* Make description vector. */
1669 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
1670 if ((cmd_element
= vector_slot (cmd_vector
, i
)) != NULL
)
1672 vector strvec
= cmd_element
->strvec
;
1674 /* if command is NULL, index may be equal to vector_active */
1675 if (command
&& index
>= vector_active (strvec
))
1676 vector_slot (cmd_vector
, i
) = NULL
;
1679 /* Check if command is completed. */
1680 if (command
== NULL
&& index
== vector_active (strvec
))
1682 if (!desc_unique_string (matchvec
, command_cr
))
1683 vector_set (matchvec
, &desc_cr
);
1688 vector descvec
= vector_slot (strvec
, index
);
1691 for (j
= 0; j
< vector_active (descvec
); j
++)
1692 if ((desc
= vector_slot (descvec
, j
)))
1696 string
= cmd_entry_function_desc (command
, desc
->cmd
);
1699 /* Uniqueness check */
1700 if (!desc_unique_string (matchvec
, string
))
1701 vector_set (matchvec
, desc
);
1707 vector_free (cmd_vector
);
1709 if (vector_slot (matchvec
, 0) == NULL
)
1711 vector_free (matchvec
);
1712 *status
= CMD_ERR_NO_MATCH
;
1716 *status
= CMD_SUCCESS
;
1721 cmd_describe_command (vector vline
, struct vty
*vty
, int *status
)
1725 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
1727 enum node_type onode
;
1728 vector shifted_vline
;
1732 vty
->node
= ENABLE_NODE
;
1733 /* We can try it on enable node, cos' the vty is authenticated */
1735 shifted_vline
= vector_init (vector_count(vline
));
1737 for (index
= 1; index
< vector_active (vline
); index
++)
1739 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
1742 ret
= cmd_describe_command_real (shifted_vline
, vty
, status
);
1744 vector_free(shifted_vline
);
1750 return cmd_describe_command_real (vline
, vty
, status
);
1754 /* Check LCD of matched command. */
1756 cmd_lcd (char **matched
)
1764 if (matched
[0] == NULL
|| matched
[1] == NULL
)
1767 for (i
= 1; matched
[i
] != NULL
; i
++)
1769 s1
= matched
[i
- 1];
1772 for (j
= 0; (c1
= s1
[j
]) && (c2
= s2
[j
]); j
++)
1787 /* Command line completion support. */
1789 cmd_complete_command_real (vector vline
, struct vty
*vty
, int *status
)
1792 vector cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
1793 #define INIT_MATCHVEC_SIZE 10
1795 struct cmd_element
*cmd_element
;
1803 if (vector_active (vline
) == 0)
1805 vector_free (cmd_vector
);
1806 *status
= CMD_ERR_NO_MATCH
;
1810 index
= vector_active (vline
) - 1;
1812 /* First, filter by preceeding command string */
1813 for (i
= 0; i
< index
; i
++)
1814 if ((command
= vector_slot (vline
, i
)))
1816 enum match_type match
;
1819 /* First try completion match, if there is exactly match return 1 */
1820 match
= cmd_filter_by_completion (command
, cmd_vector
, i
);
1822 /* If there is exact match then filter ambiguous match else check
1824 if ((ret
= is_cmd_ambiguous (command
, cmd_vector
, i
, match
)) == 1)
1826 vector_free (cmd_vector
);
1827 *status
= CMD_ERR_AMBIGUOUS
;
1833 vector_free (cmd_vector);
1834 *status = CMD_ERR_NO_MATCH;
1840 /* Prepare match vector. */
1841 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1843 /* Now we got into completion */
1844 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
1845 if ((cmd_element
= vector_slot (cmd_vector
, i
)))
1848 vector strvec
= cmd_element
->strvec
;
1850 /* Check field length */
1851 if (index
>= vector_active (strvec
))
1852 vector_slot (cmd_vector
, i
) = NULL
;
1857 descvec
= vector_slot (strvec
, index
);
1858 for (j
= 0; j
< vector_active (descvec
); j
++)
1859 if ((desc
= vector_slot (descvec
, j
)))
1862 cmd_entry_function (vector_slot (vline
, index
),
1864 if (cmd_unique_string (matchvec
, string
))
1865 vector_set (matchvec
, XSTRDUP (MTYPE_TMP
, string
));
1870 /* We don't need cmd_vector any more. */
1871 vector_free (cmd_vector
);
1873 /* No matched command */
1874 if (vector_slot (matchvec
, 0) == NULL
)
1876 vector_free (matchvec
);
1878 /* In case of 'command \t' pattern. Do you need '?' command at
1879 the end of the line. */
1880 if (vector_slot (vline
, index
) == '\0')
1881 *status
= CMD_ERR_NOTHING_TODO
;
1883 *status
= CMD_ERR_NO_MATCH
;
1887 /* Only one matched */
1888 if (vector_slot (matchvec
, 1) == NULL
)
1890 match_str
= (char **) matchvec
->index
;
1891 vector_only_wrapper_free (matchvec
);
1892 *status
= CMD_COMPLETE_FULL_MATCH
;
1895 /* Make it sure last element is NULL. */
1896 vector_set (matchvec
, NULL
);
1898 /* Check LCD of matched strings. */
1899 if (vector_slot (vline
, index
) != NULL
)
1901 lcd
= cmd_lcd ((char **) matchvec
->index
);
1905 int len
= strlen (vector_slot (vline
, index
));
1911 lcdstr
= XMALLOC (MTYPE_STRVEC
, lcd
+ 1);
1912 memcpy (lcdstr
, matchvec
->index
[0], lcd
);
1915 /* match_str = (char **) &lcdstr; */
1917 /* Free matchvec. */
1918 for (i
= 0; i
< vector_active (matchvec
); i
++)
1920 if (vector_slot (matchvec
, i
))
1921 XFREE (MTYPE_STRVEC
, vector_slot (matchvec
, i
));
1923 vector_free (matchvec
);
1925 /* Make new matchvec. */
1926 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1927 vector_set (matchvec
, lcdstr
);
1928 match_str
= (char **) matchvec
->index
;
1929 vector_only_wrapper_free (matchvec
);
1931 *status
= CMD_COMPLETE_MATCH
;
1937 match_str
= (char **) matchvec
->index
;
1938 vector_only_wrapper_free (matchvec
);
1939 *status
= CMD_COMPLETE_LIST_MATCH
;
1944 cmd_complete_command (vector vline
, struct vty
*vty
, int *status
)
1948 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
1950 enum node_type onode
;
1951 vector shifted_vline
;
1955 vty
->node
= ENABLE_NODE
;
1956 /* We can try it on enable node, cos' the vty is authenticated */
1958 shifted_vline
= vector_init (vector_count(vline
));
1960 for (index
= 1; index
< vector_active (vline
); index
++)
1962 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
1965 ret
= cmd_complete_command_real (shifted_vline
, vty
, status
);
1967 vector_free(shifted_vline
);
1973 return cmd_complete_command_real (vline
, vty
, status
);
1976 /* return parent node */
1977 /* MUST eventually converge on CONFIG_NODE */
1979 node_parent ( enum node_type node
)
1983 assert (node
> CONFIG_NODE
);
1987 case BGP_VPNV4_NODE
:
1989 case BGP_IPV4M_NODE
:
1991 case BGP_IPV6M_NODE
:
1994 case KEYCHAIN_KEY_NODE
:
1995 ret
= KEYCHAIN_NODE
;
2004 /* Execute command by argument vline vector. */
2006 cmd_execute_command_real (vector vline
, struct vty
*vty
,
2007 struct cmd_element
**cmd
)
2012 struct cmd_element
*cmd_element
;
2013 struct cmd_element
*matched_element
;
2014 unsigned int matched_count
, incomplete_count
;
2016 const char *argv
[CMD_ARGC_MAX
];
2017 enum match_type match
= 0;
2021 /* Make copy of command elements. */
2022 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
2024 for (index
= 0; index
< vector_active (vline
); index
++)
2025 if ((command
= vector_slot (vline
, index
)))
2029 match
= cmd_filter_by_completion (command
, cmd_vector
, index
);
2031 if (match
== vararg_match
)
2034 ret
= is_cmd_ambiguous (command
, cmd_vector
, index
, match
);
2038 vector_free (cmd_vector
);
2039 return CMD_ERR_AMBIGUOUS
;
2043 vector_free (cmd_vector
);
2044 return CMD_ERR_NO_MATCH
;
2048 /* Check matched count. */
2049 matched_element
= NULL
;
2051 incomplete_count
= 0;
2053 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
2054 if ((cmd_element
= vector_slot (cmd_vector
, i
)))
2056 if (match
== vararg_match
|| index
>= cmd_element
->cmdsize
)
2058 matched_element
= cmd_element
;
2060 printf ("DEBUG: %s\n", cmd_element
->string
);
2070 /* Finish of using cmd_vector. */
2071 vector_free (cmd_vector
);
2073 /* To execute command, matched_count must be 1. */
2074 if (matched_count
== 0)
2076 if (incomplete_count
)
2077 return CMD_ERR_INCOMPLETE
;
2079 return CMD_ERR_NO_MATCH
;
2082 if (matched_count
> 1)
2083 return CMD_ERR_AMBIGUOUS
;
2085 /* Argument treatment */
2089 for (i
= 0; i
< vector_active (vline
); i
++)
2092 argv
[argc
++] = vector_slot (vline
, i
);
2095 vector descvec
= vector_slot (matched_element
->strvec
, i
);
2097 if (vector_active (descvec
) == 1)
2099 struct desc
*desc
= vector_slot (descvec
, 0);
2101 if (CMD_VARARG (desc
->cmd
))
2104 if (varflag
|| CMD_VARIABLE (desc
->cmd
) || CMD_OPTION (desc
->cmd
))
2105 argv
[argc
++] = vector_slot (vline
, i
);
2108 argv
[argc
++] = vector_slot (vline
, i
);
2111 if (argc
>= CMD_ARGC_MAX
)
2112 return CMD_ERR_EXEED_ARGC_MAX
;
2115 /* For vtysh execution. */
2117 *cmd
= matched_element
;
2119 if (matched_element
->daemon
)
2120 return CMD_SUCCESS_DAEMON
;
2122 /* Execute matched command. */
2123 return (*matched_element
->func
) (matched_element
, vty
, argc
, argv
);
2127 cmd_execute_command (vector vline
, struct vty
*vty
, struct cmd_element
**cmd
,
2129 int ret
, saved_ret
, tried
= 0;
2130 enum node_type onode
, try_node
;
2132 onode
= try_node
= vty
->node
;
2134 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
2136 vector shifted_vline
;
2139 vty
->node
= ENABLE_NODE
;
2140 /* We can try it on enable node, cos' the vty is authenticated */
2142 shifted_vline
= vector_init (vector_count(vline
));
2144 for (index
= 1; index
< vector_active (vline
); index
++)
2146 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
2149 ret
= cmd_execute_command_real (shifted_vline
, vty
, cmd
);
2151 vector_free(shifted_vline
);
2157 saved_ret
= ret
= cmd_execute_command_real (vline
, vty
, cmd
);
2162 /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
2163 while ( ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2164 && vty
->node
> CONFIG_NODE
)
2166 try_node
= node_parent(try_node
);
2167 vty
->node
= try_node
;
2168 ret
= cmd_execute_command_real (vline
, vty
, cmd
);
2170 if (ret
== CMD_SUCCESS
|| ret
== CMD_WARNING
)
2172 /* succesfull command, leave the node as is */
2176 /* no command succeeded, reset the vty to the original node and
2177 return the error for this node */
2183 /* Execute command by argument readline. */
2185 cmd_execute_command_strict (vector vline
, struct vty
*vty
,
2186 struct cmd_element
**cmd
)
2191 struct cmd_element
*cmd_element
;
2192 struct cmd_element
*matched_element
;
2193 unsigned int matched_count
, incomplete_count
;
2195 const char *argv
[CMD_ARGC_MAX
];
2197 enum match_type match
= 0;
2200 /* Make copy of command element */
2201 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
2203 for (index
= 0; index
< vector_active (vline
); index
++)
2204 if ((command
= vector_slot (vline
, index
)))
2208 match
= cmd_filter_by_string (vector_slot (vline
, index
),
2211 /* If command meets '.VARARG' then finish matching. */
2212 if (match
== vararg_match
)
2215 ret
= is_cmd_ambiguous (command
, cmd_vector
, index
, match
);
2218 vector_free (cmd_vector
);
2219 return CMD_ERR_AMBIGUOUS
;
2223 vector_free (cmd_vector
);
2224 return CMD_ERR_NO_MATCH
;
2228 /* Check matched count. */
2229 matched_element
= NULL
;
2231 incomplete_count
= 0;
2232 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
2233 if (vector_slot (cmd_vector
, i
) != NULL
)
2235 cmd_element
= vector_slot (cmd_vector
, i
);
2237 if (match
== vararg_match
|| index
>= cmd_element
->cmdsize
)
2239 matched_element
= cmd_element
;
2246 /* Finish of using cmd_vector. */
2247 vector_free (cmd_vector
);
2249 /* To execute command, matched_count must be 1. */
2250 if (matched_count
== 0)
2252 if (incomplete_count
)
2253 return CMD_ERR_INCOMPLETE
;
2255 return CMD_ERR_NO_MATCH
;
2258 if (matched_count
> 1)
2259 return CMD_ERR_AMBIGUOUS
;
2261 /* Argument treatment */
2265 for (i
= 0; i
< vector_active (vline
); i
++)
2268 argv
[argc
++] = vector_slot (vline
, i
);
2271 vector descvec
= vector_slot (matched_element
->strvec
, i
);
2273 if (vector_active (descvec
) == 1)
2275 struct desc
*desc
= vector_slot (descvec
, 0);
2277 if (CMD_VARARG (desc
->cmd
))
2280 if (varflag
|| CMD_VARIABLE (desc
->cmd
) || CMD_OPTION (desc
->cmd
))
2281 argv
[argc
++] = vector_slot (vline
, i
);
2284 argv
[argc
++] = vector_slot (vline
, i
);
2287 if (argc
>= CMD_ARGC_MAX
)
2288 return CMD_ERR_EXEED_ARGC_MAX
;
2291 /* For vtysh execution. */
2293 *cmd
= matched_element
;
2295 if (matched_element
->daemon
)
2296 return CMD_SUCCESS_DAEMON
;
2298 /* Now execute matched command */
2299 return (*matched_element
->func
) (matched_element
, vty
, argc
, argv
);
2302 /* Configration make from file. */
2304 config_from_file (struct vty
*vty
, FILE *fp
)
2309 while (fgets (vty
->buf
, VTY_BUFSIZ
, fp
))
2311 vline
= cmd_make_strvec (vty
->buf
);
2313 /* In case of comment line */
2316 /* Execute configuration command : this is strict match */
2317 ret
= cmd_execute_command_strict (vline
, vty
, NULL
);
2319 /* Try again with setting node to CONFIG_NODE */
2320 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2321 && ret
!= CMD_ERR_NOTHING_TODO
&& vty
->node
!= CONFIG_NODE
)
2323 vty
->node
= node_parent(vty
->node
);
2324 ret
= cmd_execute_command_strict (vline
, vty
, NULL
);
2327 cmd_free_strvec (vline
);
2329 if (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2330 && ret
!= CMD_ERR_NOTHING_TODO
)
2336 /* Configration from terminal */
2337 DEFUN (config_terminal
,
2338 config_terminal_cmd
,
2339 "configure terminal",
2340 "Configuration from vty interface\n"
2341 "Configuration terminal\n")
2343 if (vty_config_lock (vty
))
2344 vty
->node
= CONFIG_NODE
;
2347 vty_out (vty
, "VTY configuration is locked by other VTY%s", VTY_NEWLINE
);
2353 /* Enable command */
2357 "Turn on privileged mode command\n")
2359 /* If enable password is NULL, change to ENABLE_NODE */
2360 if ((host
.enable
== NULL
&& host
.enable_encrypt
== NULL
) ||
2361 vty
->type
== VTY_SHELL_SERV
)
2362 vty
->node
= ENABLE_NODE
;
2364 vty
->node
= AUTH_ENABLE_NODE
;
2369 /* Disable command */
2373 "Turn off privileged mode command\n")
2375 if (vty
->node
== ENABLE_NODE
)
2376 vty
->node
= VIEW_NODE
;
2380 /* Down vty node level. */
2384 "Exit current mode and down to previous mode\n")
2390 case RESTRICTED_NODE
:
2391 if (vty_shell (vty
))
2394 vty
->status
= VTY_CLOSE
;
2397 vty
->node
= ENABLE_NODE
;
2398 vty_config_unlock (vty
);
2400 case INTERFACE_NODE
:
2412 vty
->node
= CONFIG_NODE
;
2414 case BGP_VPNV4_NODE
:
2416 case BGP_IPV4M_NODE
:
2418 case BGP_IPV6M_NODE
:
2419 vty
->node
= BGP_NODE
;
2421 case KEYCHAIN_KEY_NODE
:
2422 vty
->node
= KEYCHAIN_NODE
;
2430 /* quit is alias of exit. */
2434 "Exit current mode and down to previous mode\n")
2436 /* End of configuration. */
2440 "End current mode and change to enable mode.")
2446 case RESTRICTED_NODE
:
2447 /* Nothing to do. */
2450 case INTERFACE_NODE
:
2455 case BGP_VPNV4_NODE
:
2457 case BGP_IPV4M_NODE
:
2459 case BGP_IPV6M_NODE
:
2465 case KEYCHAIN_KEY_NODE
:
2468 vty_config_unlock (vty
);
2469 vty
->node
= ENABLE_NODE
;
2478 DEFUN (show_version
,
2482 "Displays zebra version\n")
2484 vty_out (vty
, "Quagga %s (%s).%s", QUAGGA_VERSION
, host
.name
?host
.name
:"",
2486 vty_out (vty
, "%s%s", QUAGGA_COPYRIGHT
, VTY_NEWLINE
);
2491 /* Help display function for all node. */
2495 "Description of the interactive help system\n")
2498 "Quagga VTY provides advanced help feature. When you need help,%s\
2499 anytime at the command line please press '?'.%s\
2501 If nothing matches, the help list will be empty and you must backup%s\
2502 until entering a '?' shows the available options.%s\
2503 Two styles of help are provided:%s\
2504 1. Full help is available when you are ready to enter a%s\
2505 command argument (e.g. 'show ?') and describes each possible%s\
2507 2. Partial help is provided when an abbreviated argument is entered%s\
2508 and you want to know what arguments match the input%s\
2509 (e.g. 'show me?'.)%s%s", VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2510 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2511 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2515 /* Help display function for all node. */
2519 "Print command list\n")
2522 struct cmd_node
*cnode
= vector_slot (cmdvec
, vty
->node
);
2523 struct cmd_element
*cmd
;
2525 for (i
= 0; i
< vector_active (cnode
->cmd_vector
); i
++)
2526 if ((cmd
= vector_slot (cnode
->cmd_vector
, i
)) != NULL
2527 && !(cmd
->attr
== CMD_ATTR_DEPRECATED
2528 || cmd
->attr
== CMD_ATTR_HIDDEN
))
2529 vty_out (vty
, " %s%s", cmd
->string
,
2534 /* Write current configuration into file. */
2535 DEFUN (config_write_file
,
2536 config_write_file_cmd
,
2538 "Write running configuration to memory, network, or terminal\n"
2539 "Write to configuration file\n")
2543 struct cmd_node
*node
;
2545 char *config_file_tmp
= NULL
;
2546 char *config_file_sav
= NULL
;
2547 int ret
= CMD_WARNING
;
2548 struct vty
*file_vty
;
2550 /* Check and see if we are operating under vtysh configuration */
2551 if (host
.config
== NULL
)
2553 vty_out (vty
, "Can't save to configuration file, using vtysh.%s",
2559 config_file
= host
.config
;
2562 XMALLOC (MTYPE_TMP
, strlen (config_file
) + strlen (CONF_BACKUP_EXT
) + 1);
2563 strcpy (config_file_sav
, config_file
);
2564 strcat (config_file_sav
, CONF_BACKUP_EXT
);
2567 config_file_tmp
= XMALLOC (MTYPE_TMP
, strlen (config_file
) + 8);
2568 sprintf (config_file_tmp
, "%s.XXXXXX", config_file
);
2570 /* Open file to configuration write. */
2571 fd
= mkstemp (config_file_tmp
);
2574 vty_out (vty
, "Can't open configuration file %s.%s", config_file_tmp
,
2579 /* Make vty for configuration file. */
2580 file_vty
= vty_new ();
2582 file_vty
->type
= VTY_FILE
;
2584 /* Config file header print. */
2585 vty_out (file_vty
, "!\n! Zebra configuration saved from vty\n! ");
2586 vty_time_print (file_vty
, 1);
2587 vty_out (file_vty
, "!\n");
2589 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2590 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
2592 if ((*node
->func
) (file_vty
))
2593 vty_out (file_vty
, "!\n");
2595 vty_close (file_vty
);
2597 if (unlink (config_file_sav
) != 0)
2598 if (errno
!= ENOENT
)
2600 vty_out (vty
, "Can't unlink backup configuration file %s.%s", config_file_sav
,
2604 if (link (config_file
, config_file_sav
) != 0)
2606 vty_out (vty
, "Can't backup old configuration file %s.%s", config_file_sav
,
2611 if (unlink (config_file
) != 0)
2613 vty_out (vty
, "Can't unlink configuration file %s.%s", config_file
,
2617 if (link (config_file_tmp
, config_file
) != 0)
2619 vty_out (vty
, "Can't save configuration file %s.%s", config_file
,
2625 if (chmod (config_file
, CONFIGFILE_MASK
) != 0)
2627 vty_out (vty
, "Can't chmod configuration file %s: %s (%d).%s",
2628 config_file
, safe_strerror(errno
), errno
, VTY_NEWLINE
);
2632 vty_out (vty
, "Configuration saved to %s%s", config_file
,
2637 unlink (config_file_tmp
);
2638 XFREE (MTYPE_TMP
, config_file_tmp
);
2639 XFREE (MTYPE_TMP
, config_file_sav
);
2643 ALIAS (config_write_file
,
2646 "Write running configuration to memory, network, or terminal\n")
2648 ALIAS (config_write_file
,
2649 config_write_memory_cmd
,
2651 "Write running configuration to memory, network, or terminal\n"
2652 "Write configuration to the file (same as write file)\n")
2654 ALIAS (config_write_file
,
2655 copy_runningconfig_startupconfig_cmd
,
2656 "copy running-config startup-config",
2657 "Copy configuration\n"
2658 "Copy running config to... \n"
2659 "Copy running config to startup config (same as write file)\n")
2661 /* Write current configuration into the terminal. */
2662 DEFUN (config_write_terminal
,
2663 config_write_terminal_cmd
,
2665 "Write running configuration to memory, network, or terminal\n"
2666 "Write to terminal\n")
2669 struct cmd_node
*node
;
2671 if (vty
->type
== VTY_SHELL_SERV
)
2673 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2674 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
&& node
->vtysh
)
2676 if ((*node
->func
) (vty
))
2677 vty_out (vty
, "!%s", VTY_NEWLINE
);
2682 vty_out (vty
, "%sCurrent configuration:%s", VTY_NEWLINE
,
2684 vty_out (vty
, "!%s", VTY_NEWLINE
);
2686 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2687 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
2689 if ((*node
->func
) (vty
))
2690 vty_out (vty
, "!%s", VTY_NEWLINE
);
2692 vty_out (vty
, "end%s",VTY_NEWLINE
);
2697 /* Write current configuration into the terminal. */
2698 ALIAS (config_write_terminal
,
2699 show_running_config_cmd
,
2700 "show running-config",
2702 "running configuration\n")
2704 /* Write startup configuration into the terminal. */
2705 DEFUN (show_startup_config
,
2706 show_startup_config_cmd
,
2707 "show startup-config",
2709 "Contentes of startup configuration\n")
2714 confp
= fopen (host
.config
, "r");
2717 vty_out (vty
, "Can't open configuration file [%s]%s",
2718 host
.config
, VTY_NEWLINE
);
2722 while (fgets (buf
, BUFSIZ
, confp
))
2726 while (*cp
!= '\r' && *cp
!= '\n' && *cp
!= '\0')
2730 vty_out (vty
, "%s%s", buf
, VTY_NEWLINE
);
2738 /* Hostname configuration */
2739 DEFUN (config_hostname
,
2742 "Set system's network name\n"
2743 "This system's network name\n")
2745 if (!isalpha((int) *argv
[0]))
2747 vty_out (vty
, "Please specify string starting with alphabet%s", VTY_NEWLINE
);
2752 XFREE (MTYPE_HOST
, host
.name
);
2754 host
.name
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2758 DEFUN (config_no_hostname
,
2760 "no hostname [HOSTNAME]",
2762 "Reset system's network name\n"
2763 "Host name of this router\n")
2766 XFREE (MTYPE_HOST
, host
.name
);
2771 /* VTY interface password set. */
2772 DEFUN (config_password
, password_cmd
,
2773 "password (8|) WORD",
2774 "Assign the terminal connection password\n"
2775 "Specifies a HIDDEN password will follow\n"
2777 "The HIDDEN line password string\n")
2779 /* Argument check. */
2782 vty_out (vty
, "Please specify password.%s", VTY_NEWLINE
);
2788 if (*argv
[0] == '8')
2791 XFREE (MTYPE_HOST
, host
.password
);
2792 host
.password
= NULL
;
2793 if (host
.password_encrypt
)
2794 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2795 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[1]);
2800 vty_out (vty
, "Unknown encryption type.%s", VTY_NEWLINE
);
2805 if (!isalnum ((int) *argv
[0]))
2808 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
2813 XFREE (MTYPE_HOST
, host
.password
);
2814 host
.password
= NULL
;
2818 if (host
.password_encrypt
)
2819 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2820 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[0]));
2823 host
.password
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2828 ALIAS (config_password
, password_text_cmd
,
2830 "Assign the terminal connection password\n"
2831 "The UNENCRYPTED (cleartext) line password\n")
2833 /* VTY enable password set. */
2834 DEFUN (config_enable_password
, enable_password_cmd
,
2835 "enable password (8|) WORD",
2836 "Modify enable password parameters\n"
2837 "Assign the privileged level password\n"
2838 "Specifies a HIDDEN password will follow\n"
2840 "The HIDDEN 'enable' password string\n")
2842 /* Argument check. */
2845 vty_out (vty
, "Please specify password.%s", VTY_NEWLINE
);
2849 /* Crypt type is specified. */
2852 if (*argv
[0] == '8')
2855 XFREE (MTYPE_HOST
, host
.enable
);
2858 if (host
.enable_encrypt
)
2859 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2860 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[1]);
2866 vty_out (vty
, "Unknown encryption type.%s", VTY_NEWLINE
);
2871 if (!isalnum ((int) *argv
[0]))
2874 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
2879 XFREE (MTYPE_HOST
, host
.enable
);
2882 /* Plain password input. */
2885 if (host
.enable_encrypt
)
2886 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2887 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[0]));
2890 host
.enable
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2895 ALIAS (config_enable_password
,
2896 enable_password_text_cmd
,
2897 "enable password LINE",
2898 "Modify enable password parameters\n"
2899 "Assign the privileged level password\n"
2900 "The UNENCRYPTED (cleartext) 'enable' password\n")
2902 /* VTY enable password delete. */
2903 DEFUN (no_config_enable_password
, no_enable_password_cmd
,
2904 "no enable password",
2906 "Modify enable password parameters\n"
2907 "Assign the privileged level password\n")
2910 XFREE (MTYPE_HOST
, host
.enable
);
2913 if (host
.enable_encrypt
)
2914 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2915 host
.enable_encrypt
= NULL
;
2920 DEFUN (service_password_encrypt
,
2921 service_password_encrypt_cmd
,
2922 "service password-encryption",
2923 "Set up miscellaneous service\n"
2924 "Enable encrypted passwords\n")
2933 if (host
.password_encrypt
)
2934 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2935 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.password
));
2939 if (host
.enable_encrypt
)
2940 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2941 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.enable
));
2947 DEFUN (no_service_password_encrypt
,
2948 no_service_password_encrypt_cmd
,
2949 "no service password-encryption",
2951 "Set up miscellaneous service\n"
2952 "Enable encrypted passwords\n")
2959 if (host
.password_encrypt
)
2960 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2961 host
.password_encrypt
= NULL
;
2963 if (host
.enable_encrypt
)
2964 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2965 host
.enable_encrypt
= NULL
;
2970 DEFUN (config_terminal_length
, config_terminal_length_cmd
,
2971 "terminal length <0-512>",
2972 "Set terminal line parameters\n"
2973 "Set number of lines on a screen\n"
2974 "Number of lines on screen (0 for no pausing)\n")
2977 char *endptr
= NULL
;
2979 lines
= strtol (argv
[0], &endptr
, 10);
2980 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
2982 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
2990 DEFUN (config_terminal_no_length
, config_terminal_no_length_cmd
,
2991 "terminal no length",
2992 "Set terminal line parameters\n"
2994 "Set number of lines on a screen\n")
3000 DEFUN (service_terminal_length
, service_terminal_length_cmd
,
3001 "service terminal-length <0-512>",
3002 "Set up miscellaneous service\n"
3003 "System wide terminal length configuration\n"
3004 "Number of lines of VTY (0 means no line control)\n")
3007 char *endptr
= NULL
;
3009 lines
= strtol (argv
[0], &endptr
, 10);
3010 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
3012 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
3020 DEFUN (no_service_terminal_length
, no_service_terminal_length_cmd
,
3021 "no service terminal-length [<0-512>]",
3023 "Set up miscellaneous service\n"
3024 "System wide terminal length configuration\n"
3025 "Number of lines of VTY (0 means no line control)\n")
3031 DEFUN_HIDDEN (do_echo
,
3034 "Echo a message back to the vty\n"
3035 "The message to echo\n")
3039 vty_out (vty
, "%s%s", ((message
= argv_concat(argv
, argc
, 0)) ? message
: ""),
3042 XFREE(MTYPE_TMP
, message
);
3046 DEFUN (config_logmsg
,
3048 "logmsg "LOG_LEVELS
" .MESSAGE",
3049 "Send a message to enabled logging destinations\n"
3051 "The message to send\n")
3056 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3057 return CMD_ERR_NO_MATCH
;
3059 zlog(NULL
, level
, ((message
= argv_concat(argv
, argc
, 1)) ? message
: ""));
3061 XFREE(MTYPE_TMP
, message
);
3065 DEFUN (show_logging
,
3069 "Show current logging configuration\n")
3071 struct zlog
*zl
= zlog_default
;
3073 vty_out (vty
, "Syslog logging: ");
3074 if (zl
->maxlvl
[ZLOG_DEST_SYSLOG
] == ZLOG_DISABLED
)
3075 vty_out (vty
, "disabled");
3077 vty_out (vty
, "level %s, facility %s, ident %s",
3078 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_SYSLOG
]],
3079 facility_name(zl
->facility
), zl
->ident
);
3080 vty_out (vty
, "%s", VTY_NEWLINE
);
3082 vty_out (vty
, "Stdout logging: ");
3083 if (zl
->maxlvl
[ZLOG_DEST_STDOUT
] == ZLOG_DISABLED
)
3084 vty_out (vty
, "disabled");
3086 vty_out (vty
, "level %s",
3087 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_STDOUT
]]);
3088 vty_out (vty
, "%s", VTY_NEWLINE
);
3090 vty_out (vty
, "Monitor logging: ");
3091 if (zl
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
3092 vty_out (vty
, "disabled");
3094 vty_out (vty
, "level %s",
3095 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_MONITOR
]]);
3096 vty_out (vty
, "%s", VTY_NEWLINE
);
3098 vty_out (vty
, "File logging: ");
3099 if ((zl
->maxlvl
[ZLOG_DEST_FILE
] == ZLOG_DISABLED
) ||
3101 vty_out (vty
, "disabled");
3103 vty_out (vty
, "level %s, filename %s",
3104 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_FILE
]],
3106 vty_out (vty
, "%s", VTY_NEWLINE
);
3108 vty_out (vty
, "Protocol name: %s%s",
3109 zlog_proto_names
[zl
->protocol
], VTY_NEWLINE
);
3110 vty_out (vty
, "Record priority: %s%s",
3111 (zl
->record_priority
? "enabled" : "disabled"), VTY_NEWLINE
);
3112 vty_out (vty
, "Timestamp precision: %d%s",
3113 zl
->timestamp_precision
, VTY_NEWLINE
);
3118 DEFUN (config_log_stdout
,
3119 config_log_stdout_cmd
,
3122 "Set stdout logging level\n")
3124 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, zlog_default
->default_lvl
);
3128 DEFUN (config_log_stdout_level
,
3129 config_log_stdout_level_cmd
,
3130 "log stdout "LOG_LEVELS
,
3132 "Set stdout logging level\n"
3137 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3138 return CMD_ERR_NO_MATCH
;
3139 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, level
);
3143 DEFUN (no_config_log_stdout
,
3144 no_config_log_stdout_cmd
,
3145 "no log stdout [LEVEL]",
3148 "Cancel logging to stdout\n"
3151 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, ZLOG_DISABLED
);
3155 DEFUN (config_log_monitor
,
3156 config_log_monitor_cmd
,
3159 "Set terminal line (monitor) logging level\n")
3161 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, zlog_default
->default_lvl
);
3165 DEFUN (config_log_monitor_level
,
3166 config_log_monitor_level_cmd
,
3167 "log monitor "LOG_LEVELS
,
3169 "Set terminal line (monitor) logging level\n"
3174 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3175 return CMD_ERR_NO_MATCH
;
3176 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, level
);
3180 DEFUN (no_config_log_monitor
,
3181 no_config_log_monitor_cmd
,
3182 "no log monitor [LEVEL]",
3185 "Disable terminal line (monitor) logging\n"
3188 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, ZLOG_DISABLED
);
3193 set_log_file(struct vty
*vty
, const char *fname
, int loglevel
)
3197 const char *fullpath
;
3199 /* Path detection. */
3200 if (! IS_DIRECTORY_SEP (*fname
))
3202 char cwd
[MAXPATHLEN
+1];
3203 cwd
[MAXPATHLEN
] = '\0';
3205 if (getcwd (cwd
, MAXPATHLEN
) == NULL
)
3207 zlog_err ("config_log_file: Unable to alloc mem!");
3211 if ( (p
= XMALLOC (MTYPE_TMP
, strlen (cwd
) + strlen (fname
) + 2))
3214 zlog_err ("config_log_file: Unable to alloc mem!");
3217 sprintf (p
, "%s/%s", cwd
, fname
);
3223 ret
= zlog_set_file (NULL
, fullpath
, loglevel
);
3226 XFREE (MTYPE_TMP
, p
);
3230 vty_out (vty
, "can't open logfile %s\n", fname
);
3235 XFREE (MTYPE_HOST
, host
.logfile
);
3237 host
.logfile
= XSTRDUP (MTYPE_HOST
, fname
);
3242 DEFUN (config_log_file
,
3243 config_log_file_cmd
,
3244 "log file FILENAME",
3247 "Logging filename\n")
3249 return set_log_file(vty
, argv
[0], zlog_default
->default_lvl
);
3252 DEFUN (config_log_file_level
,
3253 config_log_file_level_cmd
,
3254 "log file FILENAME "LOG_LEVELS
,
3257 "Logging filename\n"
3262 if ((level
= level_match(argv
[1])) == ZLOG_DISABLED
)
3263 return CMD_ERR_NO_MATCH
;
3264 return set_log_file(vty
, argv
[0], level
);
3267 DEFUN (no_config_log_file
,
3268 no_config_log_file_cmd
,
3269 "no log file [FILENAME]",
3272 "Cancel logging to file\n"
3273 "Logging file name\n")
3275 zlog_reset_file (NULL
);
3278 XFREE (MTYPE_HOST
, host
.logfile
);
3280 host
.logfile
= NULL
;
3285 ALIAS (no_config_log_file
,
3286 no_config_log_file_level_cmd
,
3287 "no log file FILENAME LEVEL",
3290 "Cancel logging to file\n"
3291 "Logging file name\n"
3294 DEFUN (config_log_syslog
,
3295 config_log_syslog_cmd
,
3298 "Set syslog logging level\n")
3300 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
3304 DEFUN (config_log_syslog_level
,
3305 config_log_syslog_level_cmd
,
3306 "log syslog "LOG_LEVELS
,
3308 "Set syslog logging level\n"
3313 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3314 return CMD_ERR_NO_MATCH
;
3315 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, level
);
3319 DEFUN_DEPRECATED (config_log_syslog_facility
,
3320 config_log_syslog_facility_cmd
,
3321 "log syslog facility "LOG_FACILITIES
,
3323 "Logging goes to syslog\n"
3324 "(Deprecated) Facility parameter for syslog messages\n"
3329 if ((facility
= facility_match(argv
[0])) < 0)
3330 return CMD_ERR_NO_MATCH
;
3332 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
3333 zlog_default
->facility
= facility
;
3337 DEFUN (no_config_log_syslog
,
3338 no_config_log_syslog_cmd
,
3339 "no log syslog [LEVEL]",
3342 "Cancel logging to syslog\n"
3345 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, ZLOG_DISABLED
);
3349 ALIAS (no_config_log_syslog
,
3350 no_config_log_syslog_facility_cmd
,
3351 "no log syslog facility "LOG_FACILITIES
,
3354 "Logging goes to syslog\n"
3355 "Facility parameter for syslog messages\n"
3358 DEFUN (config_log_facility
,
3359 config_log_facility_cmd
,
3360 "log facility "LOG_FACILITIES
,
3362 "Facility parameter for syslog messages\n"
3367 if ((facility
= facility_match(argv
[0])) < 0)
3368 return CMD_ERR_NO_MATCH
;
3369 zlog_default
->facility
= facility
;
3373 DEFUN (no_config_log_facility
,
3374 no_config_log_facility_cmd
,
3375 "no log facility [FACILITY]",
3378 "Reset syslog facility to default (daemon)\n"
3379 "Syslog facility\n")
3381 zlog_default
->facility
= LOG_DAEMON
;
3385 DEFUN_DEPRECATED (config_log_trap
,
3386 config_log_trap_cmd
,
3387 "log trap "LOG_LEVELS
,
3389 "(Deprecated) Set logging level and default for all destinations\n"
3395 if ((new_level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3396 return CMD_ERR_NO_MATCH
;
3398 zlog_default
->default_lvl
= new_level
;
3399 for (i
= 0; i
< ZLOG_NUM_DESTS
; i
++)
3400 if (zlog_default
->maxlvl
[i
] != ZLOG_DISABLED
)
3401 zlog_default
->maxlvl
[i
] = new_level
;
3405 DEFUN_DEPRECATED (no_config_log_trap
,
3406 no_config_log_trap_cmd
,
3407 "no log trap [LEVEL]",
3410 "Permit all logging information\n"
3413 zlog_default
->default_lvl
= LOG_DEBUG
;
3417 DEFUN (config_log_record_priority
,
3418 config_log_record_priority_cmd
,
3419 "log record-priority",
3421 "Log the priority of the message within the message\n")
3423 zlog_default
->record_priority
= 1 ;
3427 DEFUN (no_config_log_record_priority
,
3428 no_config_log_record_priority_cmd
,
3429 "no log record-priority",
3432 "Do not log the priority of the message within the message\n")
3434 zlog_default
->record_priority
= 0 ;
3438 DEFUN (config_log_timestamp_precision
,
3439 config_log_timestamp_precision_cmd
,
3440 "log timestamp precision <0-6>",
3442 "Timestamp configuration\n"
3443 "Set the timestamp precision\n"
3444 "Number of subsecond digits\n")
3448 vty_out (vty
, "Insufficient arguments%s", VTY_NEWLINE
);
3452 VTY_GET_INTEGER_RANGE("Timestamp Precision",
3453 zlog_default
->timestamp_precision
, argv
[0], 0, 6);
3457 DEFUN (no_config_log_timestamp_precision
,
3458 no_config_log_timestamp_precision_cmd
,
3459 "no log timestamp precision",
3462 "Timestamp configuration\n"
3463 "Reset the timestamp precision to the default value of 0\n")
3465 zlog_default
->timestamp_precision
= 0 ;
3469 DEFUN (banner_motd_file
,
3470 banner_motd_file_cmd
,
3471 "banner motd file [FILE]",
3474 "Banner from a file\n"
3478 XFREE (MTYPE_HOST
, host
.motdfile
);
3479 host
.motdfile
= XSTRDUP (MTYPE_HOST
, argv
[0]);
3484 DEFUN (banner_motd_default
,
3485 banner_motd_default_cmd
,
3486 "banner motd default",
3487 "Set banner string\n"
3488 "Strings for motd\n"
3491 host
.motd
= default_motd
;
3495 DEFUN (no_banner_motd
,
3499 "Set banner string\n"
3500 "Strings for motd\n")
3504 XFREE (MTYPE_HOST
, host
.motdfile
);
3505 host
.motdfile
= NULL
;
3509 /* Set config filename. Called from vty.c */
3511 host_config_set (char *filename
)
3514 XFREE (MTYPE_HOST
, host
.config
);
3515 host
.config
= XSTRDUP (MTYPE_HOST
, filename
);
3519 install_default (enum node_type node
)
3521 install_element (node
, &config_exit_cmd
);
3522 install_element (node
, &config_quit_cmd
);
3523 install_element (node
, &config_end_cmd
);
3524 install_element (node
, &config_help_cmd
);
3525 install_element (node
, &config_list_cmd
);
3527 install_element (node
, &config_write_terminal_cmd
);
3528 install_element (node
, &config_write_file_cmd
);
3529 install_element (node
, &config_write_memory_cmd
);
3530 install_element (node
, &config_write_cmd
);
3531 install_element (node
, &show_running_config_cmd
);
3534 /* Initialize command interface. Install basic nodes and commands. */
3536 cmd_init (int terminal
)
3538 command_cr
= XSTRDUP(MTYPE_STRVEC
, "<cr>");
3539 desc_cr
.cmd
= command_cr
;
3540 desc_cr
.str
= XSTRDUP(MTYPE_STRVEC
, "");
3542 /* Allocate initial top vector of commands. */
3543 cmdvec
= vector_init (VECTOR_MIN_SIZE
);
3545 /* Default host value settings. */
3547 host
.password
= NULL
;
3549 host
.logfile
= NULL
;
3552 host
.motd
= default_motd
;
3553 host
.motdfile
= NULL
;
3555 /* Install top nodes. */
3556 install_node (&view_node
, NULL
);
3557 install_node (&enable_node
, NULL
);
3558 install_node (&auth_node
, NULL
);
3559 install_node (&auth_enable_node
, NULL
);
3560 install_node (&restricted_node
, NULL
);
3561 install_node (&config_node
, config_write_host
);
3563 /* Each node's basic commands. */
3564 install_element (VIEW_NODE
, &show_version_cmd
);
3567 install_element (VIEW_NODE
, &config_list_cmd
);
3568 install_element (VIEW_NODE
, &config_exit_cmd
);
3569 install_element (VIEW_NODE
, &config_quit_cmd
);
3570 install_element (VIEW_NODE
, &config_help_cmd
);
3571 install_element (VIEW_NODE
, &config_enable_cmd
);
3572 install_element (VIEW_NODE
, &config_terminal_length_cmd
);
3573 install_element (VIEW_NODE
, &config_terminal_no_length_cmd
);
3574 install_element (VIEW_NODE
, &show_logging_cmd
);
3575 install_element (VIEW_NODE
, &echo_cmd
);
3577 install_element (RESTRICTED_NODE
, &config_list_cmd
);
3578 install_element (RESTRICTED_NODE
, &config_exit_cmd
);
3579 install_element (RESTRICTED_NODE
, &config_quit_cmd
);
3580 install_element (RESTRICTED_NODE
, &config_help_cmd
);
3581 install_element (RESTRICTED_NODE
, &config_enable_cmd
);
3582 install_element (RESTRICTED_NODE
, &config_terminal_length_cmd
);
3583 install_element (RESTRICTED_NODE
, &config_terminal_no_length_cmd
);
3584 install_element (RESTRICTED_NODE
, &echo_cmd
);
3589 install_default (ENABLE_NODE
);
3590 install_element (ENABLE_NODE
, &config_disable_cmd
);
3591 install_element (ENABLE_NODE
, &config_terminal_cmd
);
3592 install_element (ENABLE_NODE
, ©_runningconfig_startupconfig_cmd
);
3594 install_element (ENABLE_NODE
, &show_startup_config_cmd
);
3595 install_element (ENABLE_NODE
, &show_version_cmd
);
3599 install_element (ENABLE_NODE
, &config_terminal_length_cmd
);
3600 install_element (ENABLE_NODE
, &config_terminal_no_length_cmd
);
3601 install_element (ENABLE_NODE
, &show_logging_cmd
);
3602 install_element (ENABLE_NODE
, &echo_cmd
);
3603 install_element (ENABLE_NODE
, &config_logmsg_cmd
);
3605 install_default (CONFIG_NODE
);
3608 install_element (CONFIG_NODE
, &hostname_cmd
);
3609 install_element (CONFIG_NODE
, &no_hostname_cmd
);
3613 install_element (CONFIG_NODE
, &password_cmd
);
3614 install_element (CONFIG_NODE
, &password_text_cmd
);
3615 install_element (CONFIG_NODE
, &enable_password_cmd
);
3616 install_element (CONFIG_NODE
, &enable_password_text_cmd
);
3617 install_element (CONFIG_NODE
, &no_enable_password_cmd
);
3619 install_element (CONFIG_NODE
, &config_log_stdout_cmd
);
3620 install_element (CONFIG_NODE
, &config_log_stdout_level_cmd
);
3621 install_element (CONFIG_NODE
, &no_config_log_stdout_cmd
);
3622 install_element (CONFIG_NODE
, &config_log_monitor_cmd
);
3623 install_element (CONFIG_NODE
, &config_log_monitor_level_cmd
);
3624 install_element (CONFIG_NODE
, &no_config_log_monitor_cmd
);
3625 install_element (CONFIG_NODE
, &config_log_file_cmd
);
3626 install_element (CONFIG_NODE
, &config_log_file_level_cmd
);
3627 install_element (CONFIG_NODE
, &no_config_log_file_cmd
);
3628 install_element (CONFIG_NODE
, &no_config_log_file_level_cmd
);
3629 install_element (CONFIG_NODE
, &config_log_syslog_cmd
);
3630 install_element (CONFIG_NODE
, &config_log_syslog_level_cmd
);
3631 install_element (CONFIG_NODE
, &config_log_syslog_facility_cmd
);
3632 install_element (CONFIG_NODE
, &no_config_log_syslog_cmd
);
3633 install_element (CONFIG_NODE
, &no_config_log_syslog_facility_cmd
);
3634 install_element (CONFIG_NODE
, &config_log_facility_cmd
);
3635 install_element (CONFIG_NODE
, &no_config_log_facility_cmd
);
3636 install_element (CONFIG_NODE
, &config_log_trap_cmd
);
3637 install_element (CONFIG_NODE
, &no_config_log_trap_cmd
);
3638 install_element (CONFIG_NODE
, &config_log_record_priority_cmd
);
3639 install_element (CONFIG_NODE
, &no_config_log_record_priority_cmd
);
3640 install_element (CONFIG_NODE
, &config_log_timestamp_precision_cmd
);
3641 install_element (CONFIG_NODE
, &no_config_log_timestamp_precision_cmd
);
3642 install_element (CONFIG_NODE
, &service_password_encrypt_cmd
);
3643 install_element (CONFIG_NODE
, &no_service_password_encrypt_cmd
);
3644 install_element (CONFIG_NODE
, &banner_motd_default_cmd
);
3645 install_element (CONFIG_NODE
, &banner_motd_file_cmd
);
3646 install_element (CONFIG_NODE
, &no_banner_motd_cmd
);
3647 install_element (CONFIG_NODE
, &service_terminal_length_cmd
);
3648 install_element (CONFIG_NODE
, &no_service_terminal_length_cmd
);
3650 install_element (VIEW_NODE
, &show_thread_cpu_cmd
);
3651 install_element (ENABLE_NODE
, &show_thread_cpu_cmd
);
3652 install_element (RESTRICTED_NODE
, &show_thread_cpu_cmd
);
3653 install_element (VIEW_NODE
, &show_work_queues_cmd
);
3654 install_element (ENABLE_NODE
, &show_work_queues_cmd
);
3662 unsigned int i
, j
, k
, l
;
3663 struct cmd_node
*cmd_node
;
3664 struct cmd_element
*cmd_element
;
3666 vector cmd_node_v
, cmd_element_v
, desc_v
;
3670 for (i
= 0; i
< vector_active (cmdvec
); i
++)
3671 if ((cmd_node
= vector_slot (cmdvec
, i
)) != NULL
)
3673 cmd_node_v
= cmd_node
->cmd_vector
;
3675 for (j
= 0; j
< vector_active (cmd_node_v
); j
++)
3676 if ((cmd_element
= vector_slot (cmd_node_v
, j
)) != NULL
&&
3677 cmd_element
->strvec
!= NULL
)
3679 cmd_element_v
= cmd_element
->strvec
;
3681 for (k
= 0; k
< vector_active (cmd_element_v
); k
++)
3682 if ((desc_v
= vector_slot (cmd_element_v
, k
)) != NULL
)
3684 for (l
= 0; l
< vector_active (desc_v
); l
++)
3685 if ((desc
= vector_slot (desc_v
, l
)) != NULL
)
3688 XFREE (MTYPE_STRVEC
, desc
->cmd
);
3690 XFREE (MTYPE_STRVEC
, desc
->str
);
3692 XFREE (MTYPE_DESC
, desc
);
3694 vector_free (desc_v
);
3697 cmd_element
->strvec
= NULL
;
3698 vector_free (cmd_element_v
);
3701 vector_free (cmd_node_v
);
3704 vector_free (cmdvec
);
3709 XFREE(MTYPE_STRVEC
, command_cr
);
3711 XFREE(MTYPE_STRVEC
, desc_cr
.str
);
3713 XFREE (MTYPE_HOST
, host
.name
);
3715 XFREE (MTYPE_HOST
, host
.password
);
3716 if (host
.password_encrypt
)
3717 XFREE (MTYPE_HOST
, host
.password_encrypt
);
3719 XFREE (MTYPE_HOST
, host
.enable
);
3720 if (host
.enable_encrypt
)
3721 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
3723 XFREE (MTYPE_HOST
, host
.logfile
);
3725 XFREE (MTYPE_HOST
, host
.motdfile
);
3727 XFREE (MTYPE_HOST
, host
.config
);