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 auth_enable_node
=
62 struct cmd_node enable_node
=
68 struct cmd_node config_node
=
75 /* Default motd string. */
76 const char *default_motd
=
78 Hello, this is " QUAGGA_PROGNAME
" (version " QUAGGA_VERSION
").\r\n\
79 " QUAGGA_COPYRIGHT
"\r\n\
83 static struct facility_map
{
87 } syslog_facilities
[] =
89 { LOG_KERN
, "kern", 1 },
90 { LOG_USER
, "user", 2 },
91 { LOG_MAIL
, "mail", 1 },
92 { LOG_DAEMON
, "daemon", 1 },
93 { LOG_AUTH
, "auth", 1 },
94 { LOG_SYSLOG
, "syslog", 1 },
95 { LOG_LPR
, "lpr", 2 },
96 { LOG_NEWS
, "news", 1 },
97 { LOG_UUCP
, "uucp", 2 },
98 { LOG_CRON
, "cron", 1 },
100 { LOG_FTP
, "ftp", 1 },
102 { LOG_LOCAL0
, "local0", 6 },
103 { LOG_LOCAL1
, "local1", 6 },
104 { LOG_LOCAL2
, "local2", 6 },
105 { LOG_LOCAL3
, "local3", 6 },
106 { LOG_LOCAL4
, "local4", 6 },
107 { LOG_LOCAL5
, "local5", 6 },
108 { LOG_LOCAL6
, "local6", 6 },
109 { LOG_LOCAL7
, "local7", 6 },
114 facility_name(int facility
)
116 struct facility_map
*fm
;
118 for (fm
= syslog_facilities
; fm
->name
; fm
++)
119 if (fm
->facility
== facility
)
125 facility_match(const char *str
)
127 struct facility_map
*fm
;
129 for (fm
= syslog_facilities
; fm
->name
; fm
++)
130 if (!strncmp(str
,fm
->name
,fm
->match
))
136 level_match(const char *s
)
140 for ( level
= 0 ; zlog_priority
[level
] != NULL
; level
++ )
141 if (!strncmp (s
, zlog_priority
[level
], 2))
143 return ZLOG_DISABLED
;
146 /* This is called from main when a daemon is invoked with -v or --version. */
148 print_version (const char *progname
)
150 printf ("%s version %s\n", progname
, QUAGGA_VERSION
);
151 printf ("%s\n", QUAGGA_COPYRIGHT
);
155 /* Utility function to concatenate argv argument into a single string
156 with inserting ' ' character between each argument. */
158 argv_concat (const char **argv
, int argc
, int shift
)
166 for (i
= shift
; i
< argc
; i
++)
167 len
+= strlen(argv
[i
])+1;
170 p
= str
= XMALLOC(MTYPE_TMP
, len
);
171 for (i
= shift
; i
< argc
; i
++)
174 memcpy(p
, argv
[i
], (arglen
= strlen(argv
[i
])));
182 /* Install top node of command vector. */
184 install_node (struct cmd_node
*node
,
185 int (*func
) (struct vty
*))
187 vector_set_index (cmdvec
, node
->node
, node
);
189 node
->cmd_vector
= vector_init (VECTOR_MIN_SIZE
);
192 /* Compare two command's string. Used in sort_node (). */
194 cmp_node (const void *p
, const void *q
)
196 const struct cmd_element
*a
= *(struct cmd_element
**)p
;
197 const struct cmd_element
*b
= *(struct cmd_element
**)q
;
199 return strcmp (a
->string
, b
->string
);
203 cmp_desc (const void *p
, const void *q
)
205 const struct desc
*a
= *(struct desc
**)p
;
206 const struct desc
*b
= *(struct desc
**)q
;
208 return strcmp (a
->cmd
, b
->cmd
);
211 /* Sort each node's command element according to command string. */
216 struct cmd_node
*cnode
;
218 struct cmd_element
*cmd_element
;
220 for (i
= 0; i
< vector_active (cmdvec
); i
++)
221 if ((cnode
= vector_slot (cmdvec
, i
)) != NULL
)
223 vector cmd_vector
= cnode
->cmd_vector
;
224 qsort (cmd_vector
->index
, vector_active (cmd_vector
),
225 sizeof (void *), cmp_node
);
227 for (j
= 0; j
< vector_active (cmd_vector
); j
++)
228 if ((cmd_element
= vector_slot (cmd_vector
, j
)) != NULL
229 && vector_active (cmd_element
->strvec
))
231 descvec
= vector_slot (cmd_element
->strvec
,
232 vector_active (cmd_element
->strvec
) - 1);
233 qsort (descvec
->index
, vector_active (descvec
),
234 sizeof (void *), cmp_desc
);
239 /* Breaking up string into each command piece. I assume given
240 character is separated by a space character. Return value is a
241 vector which includes char ** data element. */
243 cmd_make_strvec (const char *string
)
245 const char *cp
, *start
;
255 /* Skip white spaces. */
256 while (isspace ((int) *cp
) && *cp
!= '\0')
259 /* Return if there is only white spaces */
263 if (*cp
== '!' || *cp
== '#')
266 /* Prepare return vector. */
267 strvec
= vector_init (VECTOR_MIN_SIZE
);
269 /* Copy each command piece and set into vector. */
273 while (!(isspace ((int) *cp
) || *cp
== '\r' || *cp
== '\n') &&
277 token
= XMALLOC (MTYPE_STRVEC
, strlen
+ 1);
278 memcpy (token
, start
, strlen
);
279 *(token
+ strlen
) = '\0';
280 vector_set (strvec
, token
);
282 while ((isspace ((int) *cp
) || *cp
== '\n' || *cp
== '\r') &&
291 /* Free allocated string vector. */
293 cmd_free_strvec (vector v
)
301 for (i
= 0; i
< vector_active (v
); i
++)
302 if ((cp
= vector_slot (v
, i
)) != NULL
)
303 XFREE (MTYPE_STRVEC
, cp
);
308 /* Fetch next description. Used in cmd_make_descvec(). */
310 cmd_desc_str (const char **string
)
312 const char *cp
, *start
;
321 /* Skip white spaces. */
322 while (isspace ((int) *cp
) && *cp
!= '\0')
325 /* Return if there is only white spaces */
331 while (!(*cp
== '\r' || *cp
== '\n') && *cp
!= '\0')
335 token
= XMALLOC (MTYPE_STRVEC
, strlen
+ 1);
336 memcpy (token
, start
, strlen
);
337 *(token
+ strlen
) = '\0';
344 /* New string vector. */
346 cmd_make_descvec (const char *string
, const char *descstr
)
355 vector strvec
= NULL
;
364 allvec
= vector_init (VECTOR_MIN_SIZE
);
368 while (isspace ((int) *cp
) && *cp
!= '\0')
385 fprintf (stderr
, "Command parse error!: %s\n", string
);
391 while (isspace ((int) *cp
) && *cp
!= '\0')
405 while (! (isspace ((int) *cp
) || *cp
== '\r' || *cp
== '\n' || *cp
== ')' || *cp
== '|') && *cp
!= '\0')
410 token
= XMALLOC (MTYPE_STRVEC
, len
+ 1);
411 memcpy (token
, sp
, len
);
412 *(token
+ len
) = '\0';
414 desc
= XCALLOC (MTYPE_DESC
, sizeof (struct desc
));
416 desc
->str
= cmd_desc_str (&dp
);
422 strvec
= vector_init (VECTOR_MIN_SIZE
);
423 vector_set (allvec
, strvec
);
429 strvec
= vector_init (VECTOR_MIN_SIZE
);
430 vector_set (allvec
, strvec
);
432 vector_set (strvec
, desc
);
436 /* Count mandantory string vector size. This is to determine inputed
437 command has enough command length. */
439 cmd_cmdsize (vector strvec
)
446 for (i
= 0; i
< vector_active (strvec
); i
++)
447 if ((descvec
= vector_slot (strvec
, i
)) != NULL
)
449 if ((vector_active (descvec
)) == 1
450 && (desc
= vector_slot (descvec
, 0)) != NULL
)
452 if (desc
->cmd
== NULL
|| CMD_OPTION (desc
->cmd
))
463 /* Return prompt character of specified node. */
465 cmd_prompt (enum node_type node
)
467 struct cmd_node
*cnode
;
469 cnode
= vector_slot (cmdvec
, node
);
470 return cnode
->prompt
;
473 /* Install a command into a node. */
475 install_element (enum node_type ntype
, struct cmd_element
*cmd
)
477 struct cmd_node
*cnode
;
479 /* cmd_init hasn't been called */
483 cnode
= vector_slot (cmdvec
, ntype
);
487 fprintf (stderr
, "Command node %d doesn't exist, please check it\n",
492 vector_set (cnode
->cmd_vector
, cmd
);
494 cmd
->strvec
= cmd_make_descvec (cmd
->string
, cmd
->doc
);
495 cmd
->cmdsize
= cmd_cmdsize (cmd
->strvec
);
498 static unsigned char itoa64
[] =
499 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
502 to64(char *s
, long v
, int n
)
506 *s
++ = itoa64
[v
&0x3f];
512 zencrypt (const char *passwd
)
516 char *crypt (const char *, const char *);
520 to64(&salt
[0], random(), 3);
521 to64(&salt
[3], tv
.tv_usec
, 3);
524 return crypt (passwd
, salt
);
527 /* This function write configuration of this host. */
529 config_write_host (struct vty
*vty
)
532 vty_out (vty
, "hostname %s%s", host
.name
, VTY_NEWLINE
);
536 if (host
.password_encrypt
)
537 vty_out (vty
, "password 8 %s%s", host
.password_encrypt
, VTY_NEWLINE
);
538 if (host
.enable_encrypt
)
539 vty_out (vty
, "enable password 8 %s%s", host
.enable_encrypt
, VTY_NEWLINE
);
544 vty_out (vty
, "password %s%s", host
.password
, VTY_NEWLINE
);
546 vty_out (vty
, "enable password %s%s", host
.enable
, VTY_NEWLINE
);
549 if (zlog_default
->default_lvl
!= LOG_DEBUG
)
551 vty_out (vty
, "! N.B. The 'log trap' command is deprecated.%s",
553 vty_out (vty
, "log trap %s%s",
554 zlog_priority
[zlog_default
->default_lvl
], VTY_NEWLINE
);
557 if (host
.logfile
&& (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != ZLOG_DISABLED
))
559 vty_out (vty
, "log file %s", host
.logfile
);
560 if (zlog_default
->maxlvl
[ZLOG_DEST_FILE
] != zlog_default
->default_lvl
)
562 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_FILE
]]);
563 vty_out (vty
, "%s", VTY_NEWLINE
);
566 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != ZLOG_DISABLED
)
568 vty_out (vty
, "log stdout");
569 if (zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
] != zlog_default
->default_lvl
)
571 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_STDOUT
]]);
572 vty_out (vty
, "%s", VTY_NEWLINE
);
575 if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
576 vty_out(vty
,"no log monitor%s",VTY_NEWLINE
);
577 else if (zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
] != zlog_default
->default_lvl
)
578 vty_out(vty
,"log monitor %s%s",
579 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_MONITOR
]],VTY_NEWLINE
);
581 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != ZLOG_DISABLED
)
583 vty_out (vty
, "log syslog");
584 if (zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
] != zlog_default
->default_lvl
)
586 zlog_priority
[zlog_default
->maxlvl
[ZLOG_DEST_SYSLOG
]]);
587 vty_out (vty
, "%s", VTY_NEWLINE
);
590 if (zlog_default
->facility
!= LOG_DAEMON
)
591 vty_out (vty
, "log facility %s%s",
592 facility_name(zlog_default
->facility
), VTY_NEWLINE
);
594 if (zlog_default
->record_priority
== 1)
595 vty_out (vty
, "log record-priority%s", VTY_NEWLINE
);
597 if (zlog_default
->timestamp_precision
> 0)
598 vty_out (vty
, "log timestamp precision %d%s",
599 zlog_default
->timestamp_precision
, VTY_NEWLINE
);
602 vty_out (vty
, "service advanced-vty%s", VTY_NEWLINE
);
605 vty_out (vty
, "service password-encryption%s", VTY_NEWLINE
);
608 vty_out (vty
, "service terminal-length %d%s", host
.lines
,
612 vty_out (vty
, "banner motd file %s%s", host
.motdfile
, VTY_NEWLINE
);
613 else if (! host
.motd
)
614 vty_out (vty
, "no banner motd%s", VTY_NEWLINE
);
619 /* Utility function for getting command vector. */
621 cmd_node_vector (vector v
, enum node_type ntype
)
623 struct cmd_node
*cnode
= vector_slot (v
, ntype
);
624 return cnode
->cmd_vector
;
628 /* Filter command vector by symbol. This function is not actually used;
629 * should it be deleted? */
631 cmd_filter_by_symbol (char *command
, char *symbol
)
635 if (strcmp (symbol
, "IPV4_ADDRESS") == 0)
638 lim
= strlen (command
);
641 if (! (isdigit ((int) command
[i
]) || command
[i
] == '.' || command
[i
] == '/'))
647 if (strcmp (symbol
, "STRING") == 0)
650 lim
= strlen (command
);
653 if (! (isalpha ((int) command
[i
]) || command
[i
] == '_' || command
[i
] == '-'))
659 if (strcmp (symbol
, "IFNAME") == 0)
662 lim
= strlen (command
);
665 if (! isalnum ((int) command
[i
]))
675 /* Completion match types. */
690 static enum match_type
691 cmd_ipv4_match (const char *str
)
694 int dots
= 0, nums
= 0;
702 memset (buf
, 0, sizeof (buf
));
711 if (*(str
+ 1) == '.')
714 if (*(str
+ 1) == '\0')
720 if (!isdigit ((int) *str
))
729 strncpy (buf
, sp
, str
- sp
);
730 if (atoi (buf
) > 255)
747 static enum match_type
748 cmd_ipv4_prefix_match (const char *str
)
759 memset (buf
, 0, sizeof (buf
));
761 while (*str
!= '\0' && *str
!= '/')
768 if (*(str
+ 1) == '.' || *(str
+ 1) == '/')
771 if (*(str
+ 1) == '\0')
778 if (!isdigit ((int) *str
))
787 strncpy (buf
, sp
, str
- sp
);
788 if (atoi (buf
) > 255)
795 if (*(str
+ 1) == '\0')
801 else if (*str
== '\0')
814 if (!isdigit ((int) *str
))
826 #define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
827 #define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
828 #define STATE_START 1
829 #define STATE_COLON 2
830 #define STATE_DOUBLE 3
833 #define STATE_SLASH 6
838 static enum match_type
839 cmd_ipv6_match (const char *str
)
841 int state
= STATE_START
;
842 int colons
= 0, nums
= 0, double_colon
= 0;
843 const char *sp
= NULL
;
844 struct sockaddr_in6 sin6_dummy
;
850 if (strspn (str
, IPV6_ADDR_STR
) != strlen (str
))
853 /* use inet_pton that has a better support,
854 * for example inet_pton can support the automatic addresses:
857 ret
= inet_pton(AF_INET6
, str
, &sin6_dummy
.sin6_addr
);
869 if (*(str
+ 1) != ':' && *(str
+ 1) != '\0')
883 if (*(str
+ 1) == ':')
884 state
= STATE_DOUBLE
;
895 if (*(str
+ 1) == ':')
899 if (*(str
+ 1) != '\0')
909 if (*(str
+ 1) == ':' || *(str
+ 1) == '\0')
917 if (*(str
+ 1) == '.')
944 static enum match_type
945 cmd_ipv6_prefix_match (const char *str
)
947 int state
= STATE_START
;
948 int colons
= 0, nums
= 0, double_colon
= 0;
950 const char *sp
= NULL
;
956 if (strspn (str
, IPV6_PREFIX_STR
) != strlen (str
))
959 while (*str
!= '\0' && state
!= STATE_MASK
)
966 if (*(str
+ 1) != ':' && *(str
+ 1) != '\0')
980 if (*(str
+ 1) == '/')
982 else if (*(str
+ 1) == ':')
983 state
= STATE_DOUBLE
;
994 if (*(str
+ 1) == ':')
998 if (*(str
+ 1) != '\0' && *(str
+ 1) != '/')
1002 if (*(str
+ 1) == '/')
1003 state
= STATE_SLASH
;
1012 if (*(str
+ 1) == ':' || *(str
+ 1) == '.'
1013 || *(str
+ 1) == '\0' || *(str
+ 1) == '/')
1018 for (; sp
<= str
; sp
++)
1024 if (*(str
+ 1) == ':')
1025 state
= STATE_COLON
;
1026 else if (*(str
+ 1) == '.')
1028 else if (*(str
+ 1) == '/')
1029 state
= STATE_SLASH
;
1036 if (*(str
+ 1) == '\0')
1037 return partly_match
;
1054 if (state
< STATE_MASK
)
1055 return partly_match
;
1057 mask
= strtol (str
, &endptr
, 10);
1058 if (*endptr
!= '\0')
1061 if (mask
< 0 || mask
> 128)
1064 /* I don't know why mask < 13 makes command match partly.
1065 Forgive me to make this comments. I Want to set static default route
1066 because of lack of function to originate default in ospf6d; sorry
1069 return partly_match;
1075 #endif /* HAVE_IPV6 */
1077 #define DECIMAL_STRLEN_MAX 10
1080 cmd_range_match (const char *range
, const char *str
)
1083 char buf
[DECIMAL_STRLEN_MAX
+ 1];
1084 char *endptr
= NULL
;
1085 unsigned long min
, max
, val
;
1090 val
= strtoul (str
, &endptr
, 10);
1091 if (*endptr
!= '\0')
1095 p
= strchr (range
, '-');
1098 if (p
- range
> DECIMAL_STRLEN_MAX
)
1100 strncpy (buf
, range
, p
- range
);
1101 buf
[p
- range
] = '\0';
1102 min
= strtoul (buf
, &endptr
, 10);
1103 if (*endptr
!= '\0')
1107 p
= strchr (range
, '>');
1110 if (p
- range
> DECIMAL_STRLEN_MAX
)
1112 strncpy (buf
, range
, p
- range
);
1113 buf
[p
- range
] = '\0';
1114 max
= strtoul (buf
, &endptr
, 10);
1115 if (*endptr
!= '\0')
1118 if (val
< min
|| val
> max
)
1124 /* Make completion match and return match type flag. */
1125 static enum match_type
1126 cmd_filter_by_completion (char *command
, vector v
, unsigned int index
)
1130 struct cmd_element
*cmd_element
;
1131 enum match_type match_type
;
1135 match_type
= no_match
;
1137 /* If command and cmd_element string does not match set NULL to vector */
1138 for (i
= 0; i
< vector_active (v
); i
++)
1139 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1141 if (index
>= vector_active (cmd_element
->strvec
))
1142 vector_slot (v
, i
) = NULL
;
1148 descvec
= vector_slot (cmd_element
->strvec
, index
);
1150 for (j
= 0; j
< vector_active (descvec
); j
++)
1151 if ((desc
= vector_slot (descvec
, j
)))
1155 if (CMD_VARARG (str
))
1157 if (match_type
< vararg_match
)
1158 match_type
= vararg_match
;
1161 else if (CMD_RANGE (str
))
1163 if (cmd_range_match (str
, command
))
1165 if (match_type
< range_match
)
1166 match_type
= range_match
;
1172 else if (CMD_IPV6 (str
))
1174 if (cmd_ipv6_match (command
))
1176 if (match_type
< ipv6_match
)
1177 match_type
= ipv6_match
;
1182 else if (CMD_IPV6_PREFIX (str
))
1184 if (cmd_ipv6_prefix_match (command
))
1186 if (match_type
< ipv6_prefix_match
)
1187 match_type
= ipv6_prefix_match
;
1192 #endif /* HAVE_IPV6 */
1193 else if (CMD_IPV4 (str
))
1195 if (cmd_ipv4_match (command
))
1197 if (match_type
< ipv4_match
)
1198 match_type
= ipv4_match
;
1203 else if (CMD_IPV4_PREFIX (str
))
1205 if (cmd_ipv4_prefix_match (command
))
1207 if (match_type
< ipv4_prefix_match
)
1208 match_type
= ipv4_prefix_match
;
1213 /* Check is this point's argument optional ? */
1214 if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1216 if (match_type
< extend_match
)
1217 match_type
= extend_match
;
1220 else if (strncmp (command
, str
, strlen (command
)) == 0)
1222 if (strcmp (command
, str
) == 0)
1223 match_type
= exact_match
;
1226 if (match_type
< partly_match
)
1227 match_type
= partly_match
;
1233 vector_slot (v
, i
) = NULL
;
1239 /* Filter vector by command character with index. */
1240 static enum match_type
1241 cmd_filter_by_string (char *command
, vector v
, unsigned int index
)
1245 struct cmd_element
*cmd_element
;
1246 enum match_type match_type
;
1250 match_type
= no_match
;
1252 /* If command and cmd_element string does not match set NULL to vector */
1253 for (i
= 0; i
< vector_active (v
); i
++)
1254 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1256 /* If given index is bigger than max string vector of command,
1258 if (index
>= vector_active (cmd_element
->strvec
))
1259 vector_slot (v
, i
) = NULL
;
1265 descvec
= vector_slot (cmd_element
->strvec
, index
);
1267 for (j
= 0; j
< vector_active (descvec
); j
++)
1268 if ((desc
= vector_slot (descvec
, j
)))
1272 if (CMD_VARARG (str
))
1274 if (match_type
< vararg_match
)
1275 match_type
= vararg_match
;
1278 else if (CMD_RANGE (str
))
1280 if (cmd_range_match (str
, command
))
1282 if (match_type
< range_match
)
1283 match_type
= range_match
;
1288 else if (CMD_IPV6 (str
))
1290 if (cmd_ipv6_match (command
) == exact_match
)
1292 if (match_type
< ipv6_match
)
1293 match_type
= ipv6_match
;
1297 else if (CMD_IPV6_PREFIX (str
))
1299 if (cmd_ipv6_prefix_match (command
) == exact_match
)
1301 if (match_type
< ipv6_prefix_match
)
1302 match_type
= ipv6_prefix_match
;
1306 #endif /* HAVE_IPV6 */
1307 else if (CMD_IPV4 (str
))
1309 if (cmd_ipv4_match (command
) == exact_match
)
1311 if (match_type
< ipv4_match
)
1312 match_type
= ipv4_match
;
1316 else if (CMD_IPV4_PREFIX (str
))
1318 if (cmd_ipv4_prefix_match (command
) == exact_match
)
1320 if (match_type
< ipv4_prefix_match
)
1321 match_type
= ipv4_prefix_match
;
1325 else if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1327 if (match_type
< extend_match
)
1328 match_type
= extend_match
;
1333 if (strcmp (command
, str
) == 0)
1335 match_type
= exact_match
;
1341 vector_slot (v
, i
) = NULL
;
1347 /* Check ambiguous match */
1349 is_cmd_ambiguous (char *command
, vector v
, int index
, enum match_type type
)
1353 const char *str
= NULL
;
1354 struct cmd_element
*cmd_element
;
1355 const char *matched
= NULL
;
1359 for (i
= 0; i
< vector_active (v
); i
++)
1360 if ((cmd_element
= vector_slot (v
, i
)) != NULL
)
1364 descvec
= vector_slot (cmd_element
->strvec
, index
);
1366 for (j
= 0; j
< vector_active (descvec
); j
++)
1367 if ((desc
= vector_slot (descvec
, j
)))
1369 enum match_type ret
;
1376 if (!(CMD_OPTION (str
) || CMD_VARIABLE (str
))
1377 && strcmp (command
, str
) == 0)
1381 if (!(CMD_OPTION (str
) || CMD_VARIABLE (str
))
1382 && strncmp (command
, str
, strlen (command
)) == 0)
1384 if (matched
&& strcmp (matched
, str
) != 0)
1385 return 1; /* There is ambiguous match. */
1392 if (cmd_range_match (str
, command
))
1394 if (matched
&& strcmp (matched
, str
) != 0)
1406 case ipv6_prefix_match
:
1407 if ((ret
= cmd_ipv6_prefix_match (command
)) != no_match
)
1409 if (ret
== partly_match
)
1410 return 2; /* There is incomplete match. */
1415 #endif /* HAVE_IPV6 */
1420 case ipv4_prefix_match
:
1421 if ((ret
= cmd_ipv4_prefix_match (command
)) != no_match
)
1423 if (ret
== partly_match
)
1424 return 2; /* There is incomplete match. */
1430 if (CMD_OPTION (str
) || CMD_VARIABLE (str
))
1439 vector_slot (v
, i
) = NULL
;
1444 /* If src matches dst return dst string, otherwise return NULL */
1446 cmd_entry_function (const char *src
, const char *dst
)
1448 /* Skip variable arguments. */
1449 if (CMD_OPTION (dst
) || CMD_VARIABLE (dst
) || CMD_VARARG (dst
) ||
1450 CMD_IPV4 (dst
) || CMD_IPV4_PREFIX (dst
) || CMD_RANGE (dst
))
1453 /* In case of 'command \t', given src is NULL string. */
1457 /* Matched with input string. */
1458 if (strncmp (src
, dst
, strlen (src
)) == 0)
1464 /* If src matches dst return dst string, otherwise return NULL */
1465 /* This version will return the dst string always if it is
1466 CMD_VARIABLE for '?' key processing */
1468 cmd_entry_function_desc (const char *src
, const char *dst
)
1470 if (CMD_VARARG (dst
))
1473 if (CMD_RANGE (dst
))
1475 if (cmd_range_match (dst
, src
))
1484 if (cmd_ipv6_match (src
))
1490 if (CMD_IPV6_PREFIX (dst
))
1492 if (cmd_ipv6_prefix_match (src
))
1497 #endif /* HAVE_IPV6 */
1501 if (cmd_ipv4_match (src
))
1507 if (CMD_IPV4_PREFIX (dst
))
1509 if (cmd_ipv4_prefix_match (src
))
1515 /* Optional or variable commands always match on '?' */
1516 if (CMD_OPTION (dst
) || CMD_VARIABLE (dst
))
1519 /* In case of 'command \t', given src is NULL string. */
1523 if (strncmp (src
, dst
, strlen (src
)) == 0)
1529 /* Check same string element existence. If it isn't there return
1532 cmd_unique_string (vector v
, const char *str
)
1537 for (i
= 0; i
< vector_active (v
); i
++)
1538 if ((match
= vector_slot (v
, i
)) != NULL
)
1539 if (strcmp (match
, str
) == 0)
1544 /* Compare string to description vector. If there is same string
1545 return 1 else return 0. */
1547 desc_unique_string (vector v
, const char *str
)
1552 for (i
= 0; i
< vector_active (v
); i
++)
1553 if ((desc
= vector_slot (v
, i
)) != NULL
)
1554 if (strcmp (desc
->cmd
, str
) == 0)
1560 cmd_try_do_shortcut (enum node_type node
, char* first_word
) {
1561 if ( first_word
!= NULL
&&
1562 node
!= AUTH_NODE
&&
1563 node
!= VIEW_NODE
&&
1564 node
!= AUTH_ENABLE_NODE
&&
1565 node
!= ENABLE_NODE
&&
1566 0 == strcmp( "do", first_word
) )
1571 /* '?' describe command support. */
1573 cmd_describe_command_real (vector vline
, struct vty
*vty
, int *status
)
1577 #define INIT_MATCHVEC_SIZE 10
1579 struct cmd_element
*cmd_element
;
1582 enum match_type match
;
1584 static struct desc desc_cr
= { "<cr>", "" };
1587 if (vector_active (vline
) == 0)
1589 *status
= CMD_ERR_NO_MATCH
;
1593 index
= vector_active (vline
) - 1;
1595 /* Make copy vector of current node's command vector. */
1596 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
1598 /* Prepare match vector */
1599 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1601 /* Filter commands. */
1602 /* Only words precedes current word will be checked in this loop. */
1603 for (i
= 0; i
< index
; i
++)
1604 if ((command
= vector_slot (vline
, i
)))
1606 match
= cmd_filter_by_completion (command
, cmd_vector
, i
);
1608 if (match
== vararg_match
)
1610 struct cmd_element
*cmd_element
;
1614 for (j
= 0; j
< vector_active (cmd_vector
); j
++)
1615 if ((cmd_element
= vector_slot (cmd_vector
, j
)) != NULL
1616 && (vector_active (cmd_element
->strvec
)))
1618 descvec
= vector_slot (cmd_element
->strvec
,
1619 vector_active (cmd_element
->strvec
) - 1);
1620 for (k
= 0; k
< vector_active (descvec
); k
++)
1622 struct desc
*desc
= vector_slot (descvec
, k
);
1623 vector_set (matchvec
, desc
);
1627 vector_set (matchvec
, &desc_cr
);
1628 vector_free (cmd_vector
);
1633 if ((ret
= is_cmd_ambiguous (command
, cmd_vector
, i
, match
)) == 1)
1635 vector_free (cmd_vector
);
1636 vector_free (matchvec
);
1637 *status
= CMD_ERR_AMBIGUOUS
;
1642 vector_free (cmd_vector
);
1643 vector_free (matchvec
);
1644 *status
= CMD_ERR_NO_MATCH
;
1649 /* Prepare match vector */
1650 /* matchvec = vector_init (INIT_MATCHVEC_SIZE); */
1652 /* Make sure that cmd_vector is filtered based on current word */
1653 command
= vector_slot (vline
, index
);
1655 match
= cmd_filter_by_completion (command
, cmd_vector
, index
);
1657 /* Make description vector. */
1658 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
1659 if ((cmd_element
= vector_slot (cmd_vector
, i
)) != NULL
)
1661 const char *string
= NULL
;
1662 vector strvec
= cmd_element
->strvec
;
1664 /* if command is NULL, index may be equal to vector_active */
1665 if (command
&& index
>= vector_active (strvec
))
1666 vector_slot (cmd_vector
, i
) = NULL
;
1669 /* Check if command is completed. */
1670 if (command
== NULL
&& index
== vector_active (strvec
))
1673 if (!desc_unique_string (matchvec
, string
))
1674 vector_set (matchvec
, &desc_cr
);
1679 vector descvec
= vector_slot (strvec
, index
);
1682 for (j
= 0; j
< vector_active (descvec
); j
++)
1683 if ((desc
= vector_slot (descvec
, j
)))
1685 string
= cmd_entry_function_desc (command
, desc
->cmd
);
1688 /* Uniqueness check */
1689 if (!desc_unique_string (matchvec
, string
))
1690 vector_set (matchvec
, desc
);
1696 vector_free (cmd_vector
);
1698 if (vector_slot (matchvec
, 0) == NULL
)
1700 vector_free (matchvec
);
1701 *status
= CMD_ERR_NO_MATCH
;
1705 *status
= CMD_SUCCESS
;
1710 cmd_describe_command (vector vline
, struct vty
*vty
, int *status
)
1714 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
1716 enum node_type onode
;
1717 vector shifted_vline
;
1721 vty
->node
= ENABLE_NODE
;
1722 /* We can try it on enable node, cos' the vty is authenticated */
1724 shifted_vline
= vector_init (vector_count(vline
));
1726 for (index
= 1; index
< vector_active (vline
); index
++)
1728 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
1731 ret
= cmd_describe_command_real (shifted_vline
, vty
, status
);
1733 vector_free(shifted_vline
);
1739 return cmd_describe_command_real (vline
, vty
, status
);
1743 /* Check LCD of matched command. */
1745 cmd_lcd (char **matched
)
1753 if (matched
[0] == NULL
|| matched
[1] == NULL
)
1756 for (i
= 1; matched
[i
] != NULL
; i
++)
1758 s1
= matched
[i
- 1];
1761 for (j
= 0; (c1
= s1
[j
]) && (c2
= s2
[j
]); j
++)
1776 /* Command line completion support. */
1778 cmd_complete_command_real (vector vline
, struct vty
*vty
, int *status
)
1781 vector cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
1782 #define INIT_MATCHVEC_SIZE 10
1784 struct cmd_element
*cmd_element
;
1792 if (vector_active (vline
) == 0)
1794 vector_free (cmd_vector
);
1795 *status
= CMD_ERR_NO_MATCH
;
1799 index
= vector_active (vline
) - 1;
1801 /* First, filter by preceeding command string */
1802 for (i
= 0; i
< index
; i
++)
1803 if ((command
= vector_slot (vline
, i
)))
1805 enum match_type match
;
1808 /* First try completion match, if there is exactly match return 1 */
1809 match
= cmd_filter_by_completion (command
, cmd_vector
, i
);
1811 /* If there is exact match then filter ambiguous match else check
1813 if ((ret
= is_cmd_ambiguous (command
, cmd_vector
, i
, match
)) == 1)
1815 vector_free (cmd_vector
);
1816 *status
= CMD_ERR_AMBIGUOUS
;
1822 vector_free (cmd_vector);
1823 *status = CMD_ERR_NO_MATCH;
1829 /* Prepare match vector. */
1830 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1832 /* Now we got into completion */
1833 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
1834 if ((cmd_element
= vector_slot (cmd_vector
, i
)))
1837 vector strvec
= cmd_element
->strvec
;
1839 /* Check field length */
1840 if (index
>= vector_active (strvec
))
1841 vector_slot (cmd_vector
, i
) = NULL
;
1846 descvec
= vector_slot (strvec
, index
);
1847 for (j
= 0; j
< vector_active (descvec
); j
++)
1848 if ((desc
= vector_slot (descvec
, j
)))
1851 cmd_entry_function (vector_slot (vline
, index
),
1853 if (cmd_unique_string (matchvec
, string
))
1854 vector_set (matchvec
, XSTRDUP (MTYPE_TMP
, string
));
1859 /* We don't need cmd_vector any more. */
1860 vector_free (cmd_vector
);
1862 /* No matched command */
1863 if (vector_slot (matchvec
, 0) == NULL
)
1865 vector_free (matchvec
);
1867 /* In case of 'command \t' pattern. Do you need '?' command at
1868 the end of the line. */
1869 if (vector_slot (vline
, index
) == '\0')
1870 *status
= CMD_ERR_NOTHING_TODO
;
1872 *status
= CMD_ERR_NO_MATCH
;
1876 /* Only one matched */
1877 if (vector_slot (matchvec
, 1) == NULL
)
1879 match_str
= (char **) matchvec
->index
;
1880 vector_only_wrapper_free (matchvec
);
1881 *status
= CMD_COMPLETE_FULL_MATCH
;
1884 /* Make it sure last element is NULL. */
1885 vector_set (matchvec
, NULL
);
1887 /* Check LCD of matched strings. */
1888 if (vector_slot (vline
, index
) != NULL
)
1890 lcd
= cmd_lcd ((char **) matchvec
->index
);
1894 int len
= strlen (vector_slot (vline
, index
));
1900 lcdstr
= XMALLOC (MTYPE_STRVEC
, lcd
+ 1);
1901 memcpy (lcdstr
, matchvec
->index
[0], lcd
);
1904 /* match_str = (char **) &lcdstr; */
1906 /* Free matchvec. */
1907 for (i
= 0; i
< vector_active (matchvec
); i
++)
1909 if (vector_slot (matchvec
, i
))
1910 XFREE (MTYPE_STRVEC
, vector_slot (matchvec
, i
));
1912 vector_free (matchvec
);
1914 /* Make new matchvec. */
1915 matchvec
= vector_init (INIT_MATCHVEC_SIZE
);
1916 vector_set (matchvec
, lcdstr
);
1917 match_str
= (char **) matchvec
->index
;
1918 vector_only_wrapper_free (matchvec
);
1920 *status
= CMD_COMPLETE_MATCH
;
1926 match_str
= (char **) matchvec
->index
;
1927 vector_only_wrapper_free (matchvec
);
1928 *status
= CMD_COMPLETE_LIST_MATCH
;
1933 cmd_complete_command (vector vline
, struct vty
*vty
, int *status
)
1937 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
1939 enum node_type onode
;
1940 vector shifted_vline
;
1944 vty
->node
= ENABLE_NODE
;
1945 /* We can try it on enable node, cos' the vty is authenticated */
1947 shifted_vline
= vector_init (vector_count(vline
));
1949 for (index
= 1; index
< vector_active (vline
); index
++)
1951 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
1954 ret
= cmd_complete_command_real (shifted_vline
, vty
, status
);
1956 vector_free(shifted_vline
);
1962 return cmd_complete_command_real (vline
, vty
, status
);
1965 /* return parent node */
1966 /* MUST eventually converge on CONFIG_NODE */
1968 node_parent ( enum node_type node
)
1972 assert (node
> CONFIG_NODE
);
1976 case BGP_VPNV4_NODE
:
1978 case BGP_IPV4M_NODE
:
1980 case BGP_IPV6M_NODE
:
1983 case KEYCHAIN_KEY_NODE
:
1984 ret
= KEYCHAIN_NODE
;
1993 /* Execute command by argument vline vector. */
1995 cmd_execute_command_real (vector vline
, struct vty
*vty
,
1996 struct cmd_element
**cmd
)
2001 struct cmd_element
*cmd_element
;
2002 struct cmd_element
*matched_element
;
2003 unsigned int matched_count
, incomplete_count
;
2005 const char *argv
[CMD_ARGC_MAX
];
2006 enum match_type match
= 0;
2010 /* Make copy of command elements. */
2011 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
2013 for (index
= 0; index
< vector_active (vline
); index
++)
2014 if ((command
= vector_slot (vline
, index
)))
2018 match
= cmd_filter_by_completion (command
, cmd_vector
, index
);
2020 if (match
== vararg_match
)
2023 ret
= is_cmd_ambiguous (command
, cmd_vector
, index
, match
);
2027 vector_free (cmd_vector
);
2028 return CMD_ERR_AMBIGUOUS
;
2032 vector_free (cmd_vector
);
2033 return CMD_ERR_NO_MATCH
;
2037 /* Check matched count. */
2038 matched_element
= NULL
;
2040 incomplete_count
= 0;
2042 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
2043 if ((cmd_element
= vector_slot (cmd_vector
, i
)))
2045 if (match
== vararg_match
|| index
>= cmd_element
->cmdsize
)
2047 matched_element
= cmd_element
;
2049 printf ("DEBUG: %s\n", cmd_element
->string
);
2059 /* Finish of using cmd_vector. */
2060 vector_free (cmd_vector
);
2062 /* To execute command, matched_count must be 1. */
2063 if (matched_count
== 0)
2065 if (incomplete_count
)
2066 return CMD_ERR_INCOMPLETE
;
2068 return CMD_ERR_NO_MATCH
;
2071 if (matched_count
> 1)
2072 return CMD_ERR_AMBIGUOUS
;
2074 /* Argument treatment */
2078 for (i
= 0; i
< vector_active (vline
); i
++)
2081 argv
[argc
++] = vector_slot (vline
, i
);
2084 vector descvec
= vector_slot (matched_element
->strvec
, i
);
2086 if (vector_active (descvec
) == 1)
2088 struct desc
*desc
= vector_slot (descvec
, 0);
2090 if (CMD_VARARG (desc
->cmd
))
2093 if (varflag
|| CMD_VARIABLE (desc
->cmd
) || CMD_OPTION (desc
->cmd
))
2094 argv
[argc
++] = vector_slot (vline
, i
);
2097 argv
[argc
++] = vector_slot (vline
, i
);
2100 if (argc
>= CMD_ARGC_MAX
)
2101 return CMD_ERR_EXEED_ARGC_MAX
;
2104 /* For vtysh execution. */
2106 *cmd
= matched_element
;
2108 if (matched_element
->daemon
)
2109 return CMD_SUCCESS_DAEMON
;
2111 /* Execute matched command. */
2112 return (*matched_element
->func
) (matched_element
, vty
, argc
, argv
);
2116 cmd_execute_command (vector vline
, struct vty
*vty
, struct cmd_element
**cmd
,
2118 int ret
, saved_ret
, tried
= 0;
2119 enum node_type onode
, try_node
;
2121 onode
= try_node
= vty
->node
;
2123 if ( cmd_try_do_shortcut(vty
->node
, vector_slot(vline
, 0) ) )
2125 vector shifted_vline
;
2128 vty
->node
= ENABLE_NODE
;
2129 /* We can try it on enable node, cos' the vty is authenticated */
2131 shifted_vline
= vector_init (vector_count(vline
));
2133 for (index
= 1; index
< vector_active (vline
); index
++)
2135 vector_set_index (shifted_vline
, index
-1, vector_lookup(vline
, index
));
2138 ret
= cmd_execute_command_real (shifted_vline
, vty
, cmd
);
2140 vector_free(shifted_vline
);
2146 saved_ret
= ret
= cmd_execute_command_real (vline
, vty
, cmd
);
2151 /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
2152 while ( ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2153 && vty
->node
> CONFIG_NODE
)
2155 try_node
= node_parent(try_node
);
2156 vty
->node
= try_node
;
2157 ret
= cmd_execute_command_real (vline
, vty
, cmd
);
2159 if (ret
== CMD_SUCCESS
|| ret
== CMD_WARNING
)
2161 /* succesfull command, leave the node as is */
2165 /* no command succeeded, reset the vty to the original node and
2166 return the error for this node */
2172 /* Execute command by argument readline. */
2174 cmd_execute_command_strict (vector vline
, struct vty
*vty
,
2175 struct cmd_element
**cmd
)
2180 struct cmd_element
*cmd_element
;
2181 struct cmd_element
*matched_element
;
2182 unsigned int matched_count
, incomplete_count
;
2184 const char *argv
[CMD_ARGC_MAX
];
2186 enum match_type match
= 0;
2189 /* Make copy of command element */
2190 cmd_vector
= vector_copy (cmd_node_vector (cmdvec
, vty
->node
));
2192 for (index
= 0; index
< vector_active (vline
); index
++)
2193 if ((command
= vector_slot (vline
, index
)))
2197 match
= cmd_filter_by_string (vector_slot (vline
, index
),
2200 /* If command meets '.VARARG' then finish matching. */
2201 if (match
== vararg_match
)
2204 ret
= is_cmd_ambiguous (command
, cmd_vector
, index
, match
);
2207 vector_free (cmd_vector
);
2208 return CMD_ERR_AMBIGUOUS
;
2212 vector_free (cmd_vector
);
2213 return CMD_ERR_NO_MATCH
;
2217 /* Check matched count. */
2218 matched_element
= NULL
;
2220 incomplete_count
= 0;
2221 for (i
= 0; i
< vector_active (cmd_vector
); i
++)
2222 if (vector_slot (cmd_vector
, i
) != NULL
)
2224 cmd_element
= vector_slot (cmd_vector
, i
);
2226 if (match
== vararg_match
|| index
>= cmd_element
->cmdsize
)
2228 matched_element
= cmd_element
;
2235 /* Finish of using cmd_vector. */
2236 vector_free (cmd_vector
);
2238 /* To execute command, matched_count must be 1. */
2239 if (matched_count
== 0)
2241 if (incomplete_count
)
2242 return CMD_ERR_INCOMPLETE
;
2244 return CMD_ERR_NO_MATCH
;
2247 if (matched_count
> 1)
2248 return CMD_ERR_AMBIGUOUS
;
2250 /* Argument treatment */
2254 for (i
= 0; i
< vector_active (vline
); i
++)
2257 argv
[argc
++] = vector_slot (vline
, i
);
2260 vector descvec
= vector_slot (matched_element
->strvec
, i
);
2262 if (vector_active (descvec
) == 1)
2264 struct desc
*desc
= vector_slot (descvec
, 0);
2266 if (CMD_VARARG (desc
->cmd
))
2269 if (varflag
|| CMD_VARIABLE (desc
->cmd
) || CMD_OPTION (desc
->cmd
))
2270 argv
[argc
++] = vector_slot (vline
, i
);
2273 argv
[argc
++] = vector_slot (vline
, i
);
2276 if (argc
>= CMD_ARGC_MAX
)
2277 return CMD_ERR_EXEED_ARGC_MAX
;
2280 /* For vtysh execution. */
2282 *cmd
= matched_element
;
2284 if (matched_element
->daemon
)
2285 return CMD_SUCCESS_DAEMON
;
2287 /* Now execute matched command */
2288 return (*matched_element
->func
) (matched_element
, vty
, argc
, argv
);
2291 /* Configration make from file. */
2293 config_from_file (struct vty
*vty
, FILE *fp
)
2298 while (fgets (vty
->buf
, VTY_BUFSIZ
, fp
))
2300 vline
= cmd_make_strvec (vty
->buf
);
2302 /* In case of comment line */
2305 /* Execute configuration command : this is strict match */
2306 ret
= cmd_execute_command_strict (vline
, vty
, NULL
);
2308 /* Try again with setting node to CONFIG_NODE */
2309 while (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2310 && ret
!= CMD_ERR_NOTHING_TODO
&& vty
->node
!= CONFIG_NODE
)
2312 vty
->node
= node_parent(vty
->node
);
2313 ret
= cmd_execute_command_strict (vline
, vty
, NULL
);
2316 cmd_free_strvec (vline
);
2318 if (ret
!= CMD_SUCCESS
&& ret
!= CMD_WARNING
2319 && ret
!= CMD_ERR_NOTHING_TODO
)
2325 /* Configration from terminal */
2326 DEFUN (config_terminal
,
2327 config_terminal_cmd
,
2328 "configure terminal",
2329 "Configuration from vty interface\n"
2330 "Configuration terminal\n")
2332 if (vty_config_lock (vty
))
2333 vty
->node
= CONFIG_NODE
;
2336 vty_out (vty
, "VTY configuration is locked by other VTY%s", VTY_NEWLINE
);
2342 /* Enable command */
2346 "Turn on privileged mode command\n")
2348 /* If enable password is NULL, change to ENABLE_NODE */
2349 if ((host
.enable
== NULL
&& host
.enable_encrypt
== NULL
) ||
2350 vty
->type
== VTY_SHELL_SERV
)
2351 vty
->node
= ENABLE_NODE
;
2353 vty
->node
= AUTH_ENABLE_NODE
;
2358 /* Disable command */
2362 "Turn off privileged mode command\n")
2364 if (vty
->node
== ENABLE_NODE
)
2365 vty
->node
= VIEW_NODE
;
2369 /* Down vty node level. */
2373 "Exit current mode and down to previous mode\n")
2379 if (vty_shell (vty
))
2382 vty
->status
= VTY_CLOSE
;
2385 vty
->node
= ENABLE_NODE
;
2386 vty_config_unlock (vty
);
2388 case INTERFACE_NODE
:
2400 vty
->node
= CONFIG_NODE
;
2402 case BGP_VPNV4_NODE
:
2404 case BGP_IPV4M_NODE
:
2406 case BGP_IPV6M_NODE
:
2407 vty
->node
= BGP_NODE
;
2409 case KEYCHAIN_KEY_NODE
:
2410 vty
->node
= KEYCHAIN_NODE
;
2418 /* quit is alias of exit. */
2422 "Exit current mode and down to previous mode\n")
2424 /* End of configuration. */
2428 "End current mode and change to enable mode.")
2434 /* Nothing to do. */
2437 case INTERFACE_NODE
:
2442 case BGP_VPNV4_NODE
:
2444 case BGP_IPV4M_NODE
:
2446 case BGP_IPV6M_NODE
:
2452 case KEYCHAIN_KEY_NODE
:
2455 vty_config_unlock (vty
);
2456 vty
->node
= ENABLE_NODE
;
2465 DEFUN (show_version
,
2469 "Displays zebra version\n")
2471 vty_out (vty
, "Quagga %s (%s).%s", QUAGGA_VERSION
, host
.name
?host
.name
:"",
2473 vty_out (vty
, "%s%s", QUAGGA_COPYRIGHT
, VTY_NEWLINE
);
2478 /* Help display function for all node. */
2482 "Description of the interactive help system\n")
2485 "Quagga VTY provides advanced help feature. When you need help,%s\
2486 anytime at the command line please press '?'.%s\
2488 If nothing matches, the help list will be empty and you must backup%s\
2489 until entering a '?' shows the available options.%s\
2490 Two styles of help are provided:%s\
2491 1. Full help is available when you are ready to enter a%s\
2492 command argument (e.g. 'show ?') and describes each possible%s\
2494 2. Partial help is provided when an abbreviated argument is entered%s\
2495 and you want to know what arguments match the input%s\
2496 (e.g. 'show me?'.)%s%s", VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2497 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
,
2498 VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
, VTY_NEWLINE
);
2502 /* Help display function for all node. */
2506 "Print command list\n")
2509 struct cmd_node
*cnode
= vector_slot (cmdvec
, vty
->node
);
2510 struct cmd_element
*cmd
;
2512 for (i
= 0; i
< vector_active (cnode
->cmd_vector
); i
++)
2513 if ((cmd
= vector_slot (cnode
->cmd_vector
, i
)) != NULL
2514 && !(cmd
->attr
== CMD_ATTR_DEPRECATED
2515 || cmd
->attr
== CMD_ATTR_HIDDEN
))
2516 vty_out (vty
, " %s%s", cmd
->string
,
2521 /* Write current configuration into file. */
2522 DEFUN (config_write_file
,
2523 config_write_file_cmd
,
2525 "Write running configuration to memory, network, or terminal\n"
2526 "Write to configuration file\n")
2530 struct cmd_node
*node
;
2532 char *config_file_tmp
= NULL
;
2533 char *config_file_sav
= NULL
;
2534 int ret
= CMD_WARNING
;
2535 struct vty
*file_vty
;
2537 /* Check and see if we are operating under vtysh configuration */
2538 if (host
.config
== NULL
)
2540 vty_out (vty
, "Can't save to configuration file, using vtysh.%s",
2546 config_file
= host
.config
;
2549 XMALLOC (MTYPE_TMP
, strlen (config_file
) + strlen (CONF_BACKUP_EXT
) + 1);
2550 strcpy (config_file_sav
, config_file
);
2551 strcat (config_file_sav
, CONF_BACKUP_EXT
);
2554 config_file_tmp
= XMALLOC (MTYPE_TMP
, strlen (config_file
) + 8);
2555 sprintf (config_file_tmp
, "%s.XXXXXX", config_file
);
2557 /* Open file to configuration write. */
2558 fd
= mkstemp (config_file_tmp
);
2561 vty_out (vty
, "Can't open configuration file %s.%s", config_file_tmp
,
2566 /* Make vty for configuration file. */
2567 file_vty
= vty_new ();
2569 file_vty
->type
= VTY_FILE
;
2571 /* Config file header print. */
2572 vty_out (file_vty
, "!\n! Zebra configuration saved from vty\n! ");
2573 vty_time_print (file_vty
, 1);
2574 vty_out (file_vty
, "!\n");
2576 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2577 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
2579 if ((*node
->func
) (file_vty
))
2580 vty_out (file_vty
, "!\n");
2582 vty_close (file_vty
);
2584 if (unlink (config_file_sav
) != 0)
2585 if (errno
!= ENOENT
)
2587 vty_out (vty
, "Can't unlink backup configuration file %s.%s", config_file_sav
,
2591 if (link (config_file
, config_file_sav
) != 0)
2593 vty_out (vty
, "Can't backup old configuration file %s.%s", config_file_sav
,
2598 if (unlink (config_file
) != 0)
2600 vty_out (vty
, "Can't unlink configuration file %s.%s", config_file
,
2604 if (link (config_file_tmp
, config_file
) != 0)
2606 vty_out (vty
, "Can't save configuration file %s.%s", config_file
,
2612 if (chmod (config_file
, CONFIGFILE_MASK
) != 0)
2614 vty_out (vty
, "Can't chmod configuration file %s: %s (%d).%s",
2615 config_file
, safe_strerror(errno
), errno
, VTY_NEWLINE
);
2619 vty_out (vty
, "Configuration saved to %s%s", config_file
,
2624 unlink (config_file_tmp
);
2625 XFREE (MTYPE_TMP
, config_file_tmp
);
2626 XFREE (MTYPE_TMP
, config_file_sav
);
2630 ALIAS (config_write_file
,
2633 "Write running configuration to memory, network, or terminal\n")
2635 ALIAS (config_write_file
,
2636 config_write_memory_cmd
,
2638 "Write running configuration to memory, network, or terminal\n"
2639 "Write configuration to the file (same as write file)\n")
2641 ALIAS (config_write_file
,
2642 copy_runningconfig_startupconfig_cmd
,
2643 "copy running-config startup-config",
2644 "Copy configuration\n"
2645 "Copy running config to... \n"
2646 "Copy running config to startup config (same as write file)\n")
2648 /* Write current configuration into the terminal. */
2649 DEFUN (config_write_terminal
,
2650 config_write_terminal_cmd
,
2652 "Write running configuration to memory, network, or terminal\n"
2653 "Write to terminal\n")
2656 struct cmd_node
*node
;
2658 if (vty
->type
== VTY_SHELL_SERV
)
2660 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2661 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
&& node
->vtysh
)
2663 if ((*node
->func
) (vty
))
2664 vty_out (vty
, "!%s", VTY_NEWLINE
);
2669 vty_out (vty
, "%sCurrent configuration:%s", VTY_NEWLINE
,
2671 vty_out (vty
, "!%s", VTY_NEWLINE
);
2673 for (i
= 0; i
< vector_active (cmdvec
); i
++)
2674 if ((node
= vector_slot (cmdvec
, i
)) && node
->func
)
2676 if ((*node
->func
) (vty
))
2677 vty_out (vty
, "!%s", VTY_NEWLINE
);
2679 vty_out (vty
, "end%s",VTY_NEWLINE
);
2684 /* Write current configuration into the terminal. */
2685 ALIAS (config_write_terminal
,
2686 show_running_config_cmd
,
2687 "show running-config",
2689 "running configuration\n")
2691 /* Write startup configuration into the terminal. */
2692 DEFUN (show_startup_config
,
2693 show_startup_config_cmd
,
2694 "show startup-config",
2696 "Contentes of startup configuration\n")
2701 confp
= fopen (host
.config
, "r");
2704 vty_out (vty
, "Can't open configuration file [%s]%s",
2705 host
.config
, VTY_NEWLINE
);
2709 while (fgets (buf
, BUFSIZ
, confp
))
2713 while (*cp
!= '\r' && *cp
!= '\n' && *cp
!= '\0')
2717 vty_out (vty
, "%s%s", buf
, VTY_NEWLINE
);
2725 /* Hostname configuration */
2726 DEFUN (config_hostname
,
2729 "Set system's network name\n"
2730 "This system's network name\n")
2732 if (!isalpha((int) *argv
[0]))
2734 vty_out (vty
, "Please specify string starting with alphabet%s", VTY_NEWLINE
);
2739 XFREE (MTYPE_HOST
, host
.name
);
2741 host
.name
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2745 DEFUN (config_no_hostname
,
2747 "no hostname [HOSTNAME]",
2749 "Reset system's network name\n"
2750 "Host name of this router\n")
2753 XFREE (MTYPE_HOST
, host
.name
);
2758 /* VTY interface password set. */
2759 DEFUN (config_password
, password_cmd
,
2760 "password (8|) WORD",
2761 "Assign the terminal connection password\n"
2762 "Specifies a HIDDEN password will follow\n"
2764 "The HIDDEN line password string\n")
2766 /* Argument check. */
2769 vty_out (vty
, "Please specify password.%s", VTY_NEWLINE
);
2775 if (*argv
[0] == '8')
2778 XFREE (MTYPE_HOST
, host
.password
);
2779 host
.password
= NULL
;
2780 if (host
.password_encrypt
)
2781 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2782 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[1]);
2787 vty_out (vty
, "Unknown encryption type.%s", VTY_NEWLINE
);
2792 if (!isalnum ((int) *argv
[0]))
2795 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
2800 XFREE (MTYPE_HOST
, host
.password
);
2801 host
.password
= NULL
;
2805 if (host
.password_encrypt
)
2806 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2807 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[0]));
2810 host
.password
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2815 ALIAS (config_password
, password_text_cmd
,
2817 "Assign the terminal connection password\n"
2818 "The UNENCRYPTED (cleartext) line password\n")
2820 /* VTY enable password set. */
2821 DEFUN (config_enable_password
, enable_password_cmd
,
2822 "enable password (8|) WORD",
2823 "Modify enable password parameters\n"
2824 "Assign the privileged level password\n"
2825 "Specifies a HIDDEN password will follow\n"
2827 "The HIDDEN 'enable' password string\n")
2829 /* Argument check. */
2832 vty_out (vty
, "Please specify password.%s", VTY_NEWLINE
);
2836 /* Crypt type is specified. */
2839 if (*argv
[0] == '8')
2842 XFREE (MTYPE_HOST
, host
.enable
);
2845 if (host
.enable_encrypt
)
2846 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2847 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, argv
[1]);
2853 vty_out (vty
, "Unknown encryption type.%s", VTY_NEWLINE
);
2858 if (!isalnum ((int) *argv
[0]))
2861 "Please specify string starting with alphanumeric%s", VTY_NEWLINE
);
2866 XFREE (MTYPE_HOST
, host
.enable
);
2869 /* Plain password input. */
2872 if (host
.enable_encrypt
)
2873 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2874 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (argv
[0]));
2877 host
.enable
= XSTRDUP (MTYPE_HOST
, argv
[0]);
2882 ALIAS (config_enable_password
,
2883 enable_password_text_cmd
,
2884 "enable password LINE",
2885 "Modify enable password parameters\n"
2886 "Assign the privileged level password\n"
2887 "The UNENCRYPTED (cleartext) 'enable' password\n")
2889 /* VTY enable password delete. */
2890 DEFUN (no_config_enable_password
, no_enable_password_cmd
,
2891 "no enable password",
2893 "Modify enable password parameters\n"
2894 "Assign the privileged level password\n")
2897 XFREE (MTYPE_HOST
, host
.enable
);
2900 if (host
.enable_encrypt
)
2901 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2902 host
.enable_encrypt
= NULL
;
2907 DEFUN (service_password_encrypt
,
2908 service_password_encrypt_cmd
,
2909 "service password-encryption",
2910 "Set up miscellaneous service\n"
2911 "Enable encrypted passwords\n")
2920 if (host
.password_encrypt
)
2921 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2922 host
.password_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.password
));
2926 if (host
.enable_encrypt
)
2927 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2928 host
.enable_encrypt
= XSTRDUP (MTYPE_HOST
, zencrypt (host
.enable
));
2934 DEFUN (no_service_password_encrypt
,
2935 no_service_password_encrypt_cmd
,
2936 "no service password-encryption",
2938 "Set up miscellaneous service\n"
2939 "Enable encrypted passwords\n")
2946 if (host
.password_encrypt
)
2947 XFREE (MTYPE_HOST
, host
.password_encrypt
);
2948 host
.password_encrypt
= NULL
;
2950 if (host
.enable_encrypt
)
2951 XFREE (MTYPE_HOST
, host
.enable_encrypt
);
2952 host
.enable_encrypt
= NULL
;
2957 DEFUN (config_terminal_length
, config_terminal_length_cmd
,
2958 "terminal length <0-512>",
2959 "Set terminal line parameters\n"
2960 "Set number of lines on a screen\n"
2961 "Number of lines on screen (0 for no pausing)\n")
2964 char *endptr
= NULL
;
2966 lines
= strtol (argv
[0], &endptr
, 10);
2967 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
2969 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
2977 DEFUN (config_terminal_no_length
, config_terminal_no_length_cmd
,
2978 "terminal no length",
2979 "Set terminal line parameters\n"
2981 "Set number of lines on a screen\n")
2987 DEFUN (service_terminal_length
, service_terminal_length_cmd
,
2988 "service terminal-length <0-512>",
2989 "Set up miscellaneous service\n"
2990 "System wide terminal length configuration\n"
2991 "Number of lines of VTY (0 means no line control)\n")
2994 char *endptr
= NULL
;
2996 lines
= strtol (argv
[0], &endptr
, 10);
2997 if (lines
< 0 || lines
> 512 || *endptr
!= '\0')
2999 vty_out (vty
, "length is malformed%s", VTY_NEWLINE
);
3007 DEFUN (no_service_terminal_length
, no_service_terminal_length_cmd
,
3008 "no service terminal-length [<0-512>]",
3010 "Set up miscellaneous service\n"
3011 "System wide terminal length configuration\n"
3012 "Number of lines of VTY (0 means no line control)\n")
3018 DEFUN_HIDDEN (do_echo
,
3021 "Echo a message back to the vty\n"
3022 "The message to echo\n")
3026 vty_out (vty
, "%s%s", ((message
= argv_concat(argv
, argc
, 0)) ? message
: ""),
3029 XFREE(MTYPE_TMP
, message
);
3033 DEFUN (config_logmsg
,
3035 "logmsg "LOG_LEVELS
" .MESSAGE",
3036 "Send a message to enabled logging destinations\n"
3038 "The message to send\n")
3043 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3044 return CMD_ERR_NO_MATCH
;
3046 zlog(NULL
, level
, ((message
= argv_concat(argv
, argc
, 1)) ? message
: ""));
3048 XFREE(MTYPE_TMP
, message
);
3052 DEFUN (show_logging
,
3056 "Show current logging configuration\n")
3058 struct zlog
*zl
= zlog_default
;
3060 vty_out (vty
, "Syslog logging: ");
3061 if (zl
->maxlvl
[ZLOG_DEST_SYSLOG
] == ZLOG_DISABLED
)
3062 vty_out (vty
, "disabled");
3064 vty_out (vty
, "level %s, facility %s, ident %s",
3065 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_SYSLOG
]],
3066 facility_name(zl
->facility
), zl
->ident
);
3067 vty_out (vty
, "%s", VTY_NEWLINE
);
3069 vty_out (vty
, "Stdout logging: ");
3070 if (zl
->maxlvl
[ZLOG_DEST_STDOUT
] == ZLOG_DISABLED
)
3071 vty_out (vty
, "disabled");
3073 vty_out (vty
, "level %s",
3074 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_STDOUT
]]);
3075 vty_out (vty
, "%s", VTY_NEWLINE
);
3077 vty_out (vty
, "Monitor logging: ");
3078 if (zl
->maxlvl
[ZLOG_DEST_MONITOR
] == ZLOG_DISABLED
)
3079 vty_out (vty
, "disabled");
3081 vty_out (vty
, "level %s",
3082 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_MONITOR
]]);
3083 vty_out (vty
, "%s", VTY_NEWLINE
);
3085 vty_out (vty
, "File logging: ");
3086 if ((zl
->maxlvl
[ZLOG_DEST_FILE
] == ZLOG_DISABLED
) ||
3088 vty_out (vty
, "disabled");
3090 vty_out (vty
, "level %s, filename %s",
3091 zlog_priority
[zl
->maxlvl
[ZLOG_DEST_FILE
]],
3093 vty_out (vty
, "%s", VTY_NEWLINE
);
3095 vty_out (vty
, "Protocol name: %s%s",
3096 zlog_proto_names
[zl
->protocol
], VTY_NEWLINE
);
3097 vty_out (vty
, "Record priority: %s%s",
3098 (zl
->record_priority
? "enabled" : "disabled"), VTY_NEWLINE
);
3099 vty_out (vty
, "Timestamp precision: %d%s",
3100 zl
->timestamp_precision
, VTY_NEWLINE
);
3105 DEFUN (config_log_stdout
,
3106 config_log_stdout_cmd
,
3109 "Set stdout logging level\n")
3111 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, zlog_default
->default_lvl
);
3115 DEFUN (config_log_stdout_level
,
3116 config_log_stdout_level_cmd
,
3117 "log stdout "LOG_LEVELS
,
3119 "Set stdout logging level\n"
3124 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3125 return CMD_ERR_NO_MATCH
;
3126 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, level
);
3130 DEFUN (no_config_log_stdout
,
3131 no_config_log_stdout_cmd
,
3132 "no log stdout [LEVEL]",
3135 "Cancel logging to stdout\n"
3138 zlog_set_level (NULL
, ZLOG_DEST_STDOUT
, ZLOG_DISABLED
);
3142 DEFUN (config_log_monitor
,
3143 config_log_monitor_cmd
,
3146 "Set terminal line (monitor) logging level\n")
3148 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, zlog_default
->default_lvl
);
3152 DEFUN (config_log_monitor_level
,
3153 config_log_monitor_level_cmd
,
3154 "log monitor "LOG_LEVELS
,
3156 "Set terminal line (monitor) logging level\n"
3161 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3162 return CMD_ERR_NO_MATCH
;
3163 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, level
);
3167 DEFUN (no_config_log_monitor
,
3168 no_config_log_monitor_cmd
,
3169 "no log monitor [LEVEL]",
3172 "Disable terminal line (monitor) logging\n"
3175 zlog_set_level (NULL
, ZLOG_DEST_MONITOR
, ZLOG_DISABLED
);
3180 set_log_file(struct vty
*vty
, const char *fname
, int loglevel
)
3184 const char *fullpath
;
3186 /* Path detection. */
3187 if (! IS_DIRECTORY_SEP (*fname
))
3189 char cwd
[MAXPATHLEN
+1];
3190 cwd
[MAXPATHLEN
] = '\0';
3192 if (getcwd (cwd
, MAXPATHLEN
) == NULL
)
3194 zlog_err ("config_log_file: Unable to alloc mem!");
3198 if ( (p
= XMALLOC (MTYPE_TMP
, strlen (cwd
) + strlen (fname
) + 2))
3201 zlog_err ("config_log_file: Unable to alloc mem!");
3204 sprintf (p
, "%s/%s", cwd
, fname
);
3210 ret
= zlog_set_file (NULL
, fullpath
, loglevel
);
3213 XFREE (MTYPE_TMP
, p
);
3217 vty_out (vty
, "can't open logfile %s\n", fname
);
3222 XFREE (MTYPE_HOST
, host
.logfile
);
3224 host
.logfile
= XSTRDUP (MTYPE_HOST
, fname
);
3229 DEFUN (config_log_file
,
3230 config_log_file_cmd
,
3231 "log file FILENAME",
3234 "Logging filename\n")
3236 return set_log_file(vty
, argv
[0], zlog_default
->default_lvl
);
3239 DEFUN (config_log_file_level
,
3240 config_log_file_level_cmd
,
3241 "log file FILENAME "LOG_LEVELS
,
3244 "Logging filename\n"
3249 if ((level
= level_match(argv
[1])) == ZLOG_DISABLED
)
3250 return CMD_ERR_NO_MATCH
;
3251 return set_log_file(vty
, argv
[0], level
);
3254 DEFUN (no_config_log_file
,
3255 no_config_log_file_cmd
,
3256 "no log file [FILENAME]",
3259 "Cancel logging to file\n"
3260 "Logging file name\n")
3262 zlog_reset_file (NULL
);
3265 XFREE (MTYPE_HOST
, host
.logfile
);
3267 host
.logfile
= NULL
;
3272 ALIAS (no_config_log_file
,
3273 no_config_log_file_level_cmd
,
3274 "no log file FILENAME LEVEL",
3277 "Cancel logging to file\n"
3278 "Logging file name\n"
3281 DEFUN (config_log_syslog
,
3282 config_log_syslog_cmd
,
3285 "Set syslog logging level\n")
3287 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
3291 DEFUN (config_log_syslog_level
,
3292 config_log_syslog_level_cmd
,
3293 "log syslog "LOG_LEVELS
,
3295 "Set syslog logging level\n"
3300 if ((level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3301 return CMD_ERR_NO_MATCH
;
3302 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, level
);
3306 DEFUN_DEPRECATED (config_log_syslog_facility
,
3307 config_log_syslog_facility_cmd
,
3308 "log syslog facility "LOG_FACILITIES
,
3310 "Logging goes to syslog\n"
3311 "(Deprecated) Facility parameter for syslog messages\n"
3316 if ((facility
= facility_match(argv
[0])) < 0)
3317 return CMD_ERR_NO_MATCH
;
3319 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, zlog_default
->default_lvl
);
3320 zlog_default
->facility
= facility
;
3324 DEFUN (no_config_log_syslog
,
3325 no_config_log_syslog_cmd
,
3326 "no log syslog [LEVEL]",
3329 "Cancel logging to syslog\n"
3332 zlog_set_level (NULL
, ZLOG_DEST_SYSLOG
, ZLOG_DISABLED
);
3336 ALIAS (no_config_log_syslog
,
3337 no_config_log_syslog_facility_cmd
,
3338 "no log syslog facility "LOG_FACILITIES
,
3341 "Logging goes to syslog\n"
3342 "Facility parameter for syslog messages\n"
3345 DEFUN (config_log_facility
,
3346 config_log_facility_cmd
,
3347 "log facility "LOG_FACILITIES
,
3349 "Facility parameter for syslog messages\n"
3354 if ((facility
= facility_match(argv
[0])) < 0)
3355 return CMD_ERR_NO_MATCH
;
3356 zlog_default
->facility
= facility
;
3360 DEFUN (no_config_log_facility
,
3361 no_config_log_facility_cmd
,
3362 "no log facility [FACILITY]",
3365 "Reset syslog facility to default (daemon)\n"
3366 "Syslog facility\n")
3368 zlog_default
->facility
= LOG_DAEMON
;
3372 DEFUN_DEPRECATED (config_log_trap
,
3373 config_log_trap_cmd
,
3374 "log trap "LOG_LEVELS
,
3376 "(Deprecated) Set logging level and default for all destinations\n"
3382 if ((new_level
= level_match(argv
[0])) == ZLOG_DISABLED
)
3383 return CMD_ERR_NO_MATCH
;
3385 zlog_default
->default_lvl
= new_level
;
3386 for (i
= 0; i
< ZLOG_NUM_DESTS
; i
++)
3387 if (zlog_default
->maxlvl
[i
] != ZLOG_DISABLED
)
3388 zlog_default
->maxlvl
[i
] = new_level
;
3392 DEFUN_DEPRECATED (no_config_log_trap
,
3393 no_config_log_trap_cmd
,
3394 "no log trap [LEVEL]",
3397 "Permit all logging information\n"
3400 zlog_default
->default_lvl
= LOG_DEBUG
;
3404 DEFUN (config_log_record_priority
,
3405 config_log_record_priority_cmd
,
3406 "log record-priority",
3408 "Log the priority of the message within the message\n")
3410 zlog_default
->record_priority
= 1 ;
3414 DEFUN (no_config_log_record_priority
,
3415 no_config_log_record_priority_cmd
,
3416 "no log record-priority",
3419 "Do not log the priority of the message within the message\n")
3421 zlog_default
->record_priority
= 0 ;
3425 DEFUN (config_log_timestamp_precision
,
3426 config_log_timestamp_precision_cmd
,
3427 "log timestamp precision <0-6>",
3429 "Timestamp configuration\n"
3430 "Set the timestamp precision\n"
3431 "Number of subsecond digits\n")
3435 vty_out (vty
, "Insufficient arguments%s", VTY_NEWLINE
);
3439 VTY_GET_INTEGER_RANGE("Timestamp Precision",
3440 zlog_default
->timestamp_precision
, argv
[0], 0, 6);
3444 DEFUN (no_config_log_timestamp_precision
,
3445 no_config_log_timestamp_precision_cmd
,
3446 "no log timestamp precision",
3449 "Timestamp configuration\n"
3450 "Reset the timestamp precision to the default value of 0\n")
3452 zlog_default
->timestamp_precision
= 0 ;
3456 DEFUN (banner_motd_file
,
3457 banner_motd_file_cmd
,
3458 "banner motd file [FILE]",
3461 "Banner from a file\n"
3465 XFREE (MTYPE_HOST
, host
.motdfile
);
3466 host
.motdfile
= XSTRDUP (MTYPE_HOST
, argv
[0]);
3471 DEFUN (banner_motd_default
,
3472 banner_motd_default_cmd
,
3473 "banner motd default",
3474 "Set banner string\n"
3475 "Strings for motd\n"
3478 host
.motd
= default_motd
;
3482 DEFUN (no_banner_motd
,
3486 "Set banner string\n"
3487 "Strings for motd\n")
3491 XFREE (MTYPE_HOST
, host
.motdfile
);
3492 host
.motdfile
= NULL
;
3496 /* Set config filename. Called from vty.c */
3498 host_config_set (char *filename
)
3500 host
.config
= XSTRDUP (MTYPE_HOST
, filename
);
3504 install_default (enum node_type node
)
3506 install_element (node
, &config_exit_cmd
);
3507 install_element (node
, &config_quit_cmd
);
3508 install_element (node
, &config_end_cmd
);
3509 install_element (node
, &config_help_cmd
);
3510 install_element (node
, &config_list_cmd
);
3512 install_element (node
, &config_write_terminal_cmd
);
3513 install_element (node
, &config_write_file_cmd
);
3514 install_element (node
, &config_write_memory_cmd
);
3515 install_element (node
, &config_write_cmd
);
3516 install_element (node
, &show_running_config_cmd
);
3519 /* Initialize command interface. Install basic nodes and commands. */
3521 cmd_init (int terminal
)
3523 /* Allocate initial top vector of commands. */
3524 cmdvec
= vector_init (VECTOR_MIN_SIZE
);
3526 /* Default host value settings. */
3528 host
.password
= NULL
;
3530 host
.logfile
= NULL
;
3533 host
.motd
= default_motd
;
3534 host
.motdfile
= NULL
;
3536 /* Install top nodes. */
3537 install_node (&view_node
, NULL
);
3538 install_node (&enable_node
, NULL
);
3539 install_node (&auth_node
, NULL
);
3540 install_node (&auth_enable_node
, NULL
);
3541 install_node (&config_node
, config_write_host
);
3543 /* Each node's basic commands. */
3544 install_element (VIEW_NODE
, &show_version_cmd
);
3547 install_element (VIEW_NODE
, &config_list_cmd
);
3548 install_element (VIEW_NODE
, &config_exit_cmd
);
3549 install_element (VIEW_NODE
, &config_quit_cmd
);
3550 install_element (VIEW_NODE
, &config_help_cmd
);
3551 install_element (VIEW_NODE
, &config_enable_cmd
);
3552 install_element (VIEW_NODE
, &config_terminal_length_cmd
);
3553 install_element (VIEW_NODE
, &config_terminal_no_length_cmd
);
3554 install_element (VIEW_NODE
, &show_logging_cmd
);
3555 install_element (VIEW_NODE
, &echo_cmd
);
3560 install_default (ENABLE_NODE
);
3561 install_element (ENABLE_NODE
, &config_disable_cmd
);
3562 install_element (ENABLE_NODE
, &config_terminal_cmd
);
3563 install_element (ENABLE_NODE
, ©_runningconfig_startupconfig_cmd
);
3565 install_element (ENABLE_NODE
, &show_startup_config_cmd
);
3566 install_element (ENABLE_NODE
, &show_version_cmd
);
3570 install_element (ENABLE_NODE
, &config_terminal_length_cmd
);
3571 install_element (ENABLE_NODE
, &config_terminal_no_length_cmd
);
3572 install_element (ENABLE_NODE
, &show_logging_cmd
);
3573 install_element (ENABLE_NODE
, &echo_cmd
);
3574 install_element (ENABLE_NODE
, &config_logmsg_cmd
);
3576 install_default (CONFIG_NODE
);
3579 install_element (CONFIG_NODE
, &hostname_cmd
);
3580 install_element (CONFIG_NODE
, &no_hostname_cmd
);
3584 install_element (CONFIG_NODE
, &password_cmd
);
3585 install_element (CONFIG_NODE
, &password_text_cmd
);
3586 install_element (CONFIG_NODE
, &enable_password_cmd
);
3587 install_element (CONFIG_NODE
, &enable_password_text_cmd
);
3588 install_element (CONFIG_NODE
, &no_enable_password_cmd
);
3590 install_element (CONFIG_NODE
, &config_log_stdout_cmd
);
3591 install_element (CONFIG_NODE
, &config_log_stdout_level_cmd
);
3592 install_element (CONFIG_NODE
, &no_config_log_stdout_cmd
);
3593 install_element (CONFIG_NODE
, &config_log_monitor_cmd
);
3594 install_element (CONFIG_NODE
, &config_log_monitor_level_cmd
);
3595 install_element (CONFIG_NODE
, &no_config_log_monitor_cmd
);
3596 install_element (CONFIG_NODE
, &config_log_file_cmd
);
3597 install_element (CONFIG_NODE
, &config_log_file_level_cmd
);
3598 install_element (CONFIG_NODE
, &no_config_log_file_cmd
);
3599 install_element (CONFIG_NODE
, &no_config_log_file_level_cmd
);
3600 install_element (CONFIG_NODE
, &config_log_syslog_cmd
);
3601 install_element (CONFIG_NODE
, &config_log_syslog_level_cmd
);
3602 install_element (CONFIG_NODE
, &config_log_syslog_facility_cmd
);
3603 install_element (CONFIG_NODE
, &no_config_log_syslog_cmd
);
3604 install_element (CONFIG_NODE
, &no_config_log_syslog_facility_cmd
);
3605 install_element (CONFIG_NODE
, &config_log_facility_cmd
);
3606 install_element (CONFIG_NODE
, &no_config_log_facility_cmd
);
3607 install_element (CONFIG_NODE
, &config_log_trap_cmd
);
3608 install_element (CONFIG_NODE
, &no_config_log_trap_cmd
);
3609 install_element (CONFIG_NODE
, &config_log_record_priority_cmd
);
3610 install_element (CONFIG_NODE
, &no_config_log_record_priority_cmd
);
3611 install_element (CONFIG_NODE
, &config_log_timestamp_precision_cmd
);
3612 install_element (CONFIG_NODE
, &no_config_log_timestamp_precision_cmd
);
3613 install_element (CONFIG_NODE
, &service_password_encrypt_cmd
);
3614 install_element (CONFIG_NODE
, &no_service_password_encrypt_cmd
);
3615 install_element (CONFIG_NODE
, &banner_motd_default_cmd
);
3616 install_element (CONFIG_NODE
, &banner_motd_file_cmd
);
3617 install_element (CONFIG_NODE
, &no_banner_motd_cmd
);
3618 install_element (CONFIG_NODE
, &service_terminal_length_cmd
);
3619 install_element (CONFIG_NODE
, &no_service_terminal_length_cmd
);
3621 install_element (VIEW_NODE
, &show_thread_cpu_cmd
);
3622 install_element (ENABLE_NODE
, &show_thread_cpu_cmd
);
3623 install_element (VIEW_NODE
, &show_work_queues_cmd
);
3624 install_element (ENABLE_NODE
, &show_work_queues_cmd
);