1
/* Command interpreter routine for virtual terminal [aka TeletYpe]
2
Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4
This file is part of GNU Zebra.
6
GNU Zebra is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published
8
by the Free Software Foundation; either version 2, or (at your
9
option) any later version.
11
GNU Zebra is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with GNU Zebra; see the file COPYING. If not, write to the
18
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
Boston, MA 02111-1307, USA. */
26
#include <lib/version.h>
32
/* Command vector which includes some level of command lists. Normally
33
each daemon maintains each own cmdvec. */
36
/* Host information structure. */
39
/* Default motd string. */
42
Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
43
Copyright 1996-2002 Kunihiro Ishiguro.\r\n\
46
/* Standard command node structures. */
47
struct cmd_node auth_node =
53
struct cmd_node view_node =
59
struct cmd_node auth_enable_node =
65
struct cmd_node enable_node =
71
struct cmd_node config_node =
78
/* Utility function to concatenate argv argument into a single string
79
with inserting ' ' character between each argument. */
81
argv_concat (char **argv, int argc, int shift)
91
for (i = shift; i < argc; i++)
93
len = strlen (argv[i]);
97
str = XSTRDUP (MTYPE_TMP, argv[i]);
102
str = XREALLOC (MTYPE_TMP, str, (index + len + 2));
104
memcpy (str + index, argv[i], len);
112
/* Install top node of command vector. */
114
install_node (struct cmd_node *node,
115
int (*func) (struct vty *))
117
vector_set_index (cmdvec, node->node, node);
119
node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
122
/* Compare two command's string. Used in sort_node (). */
124
cmp_node (const void *p, const void *q)
126
struct cmd_element *a = *(struct cmd_element **)p;
127
struct cmd_element *b = *(struct cmd_element **)q;
129
return strcmp (a->string, b->string);
133
cmp_desc (const void *p, const void *q)
135
struct desc *a = *(struct desc **)p;
136
struct desc *b = *(struct desc **)q;
138
return strcmp (a->cmd, b->cmd);
141
/* Sort each node's command element according to command string. */
146
struct cmd_node *cnode;
148
struct cmd_element *cmd_element;
150
for (i = 0; i < vector_max (cmdvec); i++)
151
if ((cnode = vector_slot (cmdvec, i)) != NULL)
153
vector cmd_vector = cnode->cmd_vector;
154
qsort (cmd_vector->index, cmd_vector->max, sizeof (void *), cmp_node);
156
for (j = 0; j < vector_max (cmd_vector); j++)
157
if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
159
descvec = vector_slot (cmd_element->strvec,
160
vector_max (cmd_element->strvec) - 1);
161
qsort (descvec->index, descvec->max, sizeof (void *), cmp_desc);
166
/* Breaking up string into each command piece. I assume given
167
character is separated by a space character. Return value is a
168
vector which includes char ** data element. */
170
cmd_make_strvec (char *string)
172
char *cp, *start, *token;
181
/* Skip white spaces. */
182
while (isspace ((int) *cp) && *cp != '\0')
185
/* Return if there is only white spaces */
189
if (*cp == '!' || *cp == '#')
192
/* Prepare return vector. */
193
strvec = vector_init (VECTOR_MIN_SIZE);
195
/* Copy each command piece and set into vector. */
199
while (!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') &&
203
token = XMALLOC (MTYPE_STRVEC, strlen + 1);
204
memcpy (token, start, strlen);
205
*(token + strlen) = '\0';
206
vector_set (strvec, token);
208
while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r') &&
217
/* Free allocated string vector. */
219
cmd_free_strvec (vector v)
227
for (i = 0; i < vector_max (v); i++)
228
if ((cp = vector_slot (v, i)) != NULL)
229
XFREE (MTYPE_STRVEC, cp);
234
/* Fetch next description. Used in cmd_make_descvec(). */
236
cmd_desc_str (char **string)
238
char *cp, *start, *token;
246
/* Skip white spaces. */
247
while (isspace ((int) *cp) && *cp != '\0')
250
/* Return if there is only white spaces */
256
while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
260
token = XMALLOC (MTYPE_STRVEC, strlen + 1);
261
memcpy (token, start, strlen);
262
*(token + strlen) = '\0';
269
/* New string vector. */
271
cmd_make_descvec (char *string, char *descstr)
280
vector strvec = NULL;
289
allvec = vector_init (VECTOR_MIN_SIZE);
293
while (isspace ((int) *cp) && *cp != '\0')
310
fprintf (stderr, "Command parse error!: %s\n", string);
316
while (isspace ((int) *cp) && *cp != '\0')
330
while (! (isspace ((int) *cp) || *cp == '\r' || *cp == '\n' || *cp == ')' || *cp == '|') && *cp != '\0')
335
token = XMALLOC (MTYPE_STRVEC, len + 1);
336
memcpy (token, sp, len);
337
*(token + len) = '\0';
339
desc = XCALLOC (MTYPE_DESC, sizeof (struct desc));
341
desc->str = cmd_desc_str (&dp);
347
strvec = vector_init (VECTOR_MIN_SIZE);
348
vector_set (allvec, strvec);
354
strvec = vector_init (VECTOR_MIN_SIZE);
355
vector_set (allvec, strvec);
357
vector_set (strvec, desc);
361
/* Count mandantory string vector size. This is to determine inputed
362
command has enough command length. */
364
cmd_cmdsize (vector strvec)
371
for (i = 0; i < vector_max (strvec); i++)
373
descvec = vector_slot (strvec, i);
375
if (vector_max (descvec) == 1)
377
struct desc *desc = vector_slot (descvec, 0);
381
if (str == NULL || CMD_OPTION (str))
392
/* Return prompt character of specified node. */
394
cmd_prompt (enum node_type node)
396
struct cmd_node *cnode;
398
cnode = vector_slot (cmdvec, node);
399
return cnode->prompt;
402
/* Install a command into a node. */
404
install_element (enum node_type ntype, struct cmd_element *cmd)
406
struct cmd_node *cnode;
408
cnode = vector_slot (cmdvec, ntype);
412
fprintf (stderr, "Command node %d doesn't exist, please check it\n",
417
vector_set (cnode->cmd_vector, cmd);
419
cmd->strvec = cmd_make_descvec (cmd->string, cmd->doc);
420
cmd->cmdsize = cmd_cmdsize (cmd->strvec);
423
static unsigned char itoa64[] =
424
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
427
to64(char *s, long v, int n)
431
*s++ = itoa64[v&0x3f];
436
char *zencrypt (char *passwd)
440
char *crypt (const char *, const char *);
444
to64(&salt[0], random(), 3);
445
to64(&salt[3], tv.tv_usec, 3);
448
return crypt (passwd, salt);
452
syslog_facility_print (int facility)
516
/* This function write configuration of this host. */
518
config_write_host (struct vty *vty)
521
vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE);
525
if (host.password_encrypt)
526
vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE);
527
if (host.enable_encrypt)
528
vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE);
533
vty_out (vty, "password %s%s", host.password, VTY_NEWLINE);
535
vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE);
539
vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE);
542
vty_out (vty, "log stdout%s", VTY_NEWLINE);
546
vty_out (vty, "log syslog");
547
if (zlog_default->facility != LOG_DAEMON)
548
vty_out (vty, " facility %s", syslog_facility_print (zlog_default->facility));
549
vty_out (vty, "%s", VTY_NEWLINE);
551
if (zlog_default->maskpri != LOG_DEBUG)
552
vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], VTY_NEWLINE);
554
if (zlog_default->record_priority == 1)
555
vty_out (vty, "log record-priority%s", VTY_NEWLINE);
558
vty_out (vty, "service advanced-vty%s", VTY_NEWLINE);
561
vty_out (vty, "service password-encryption%s", VTY_NEWLINE);
564
vty_out (vty, "service terminal-length %d%s", host.lines,
568
vty_out (vty, "no banner motd%s", VTY_NEWLINE);
573
/* Utility function for getting command vector. */
575
cmd_node_vector (vector v, enum node_type ntype)
577
struct cmd_node *cnode = vector_slot (v, ntype);
578
return cnode->cmd_vector;
581
/* Filter command vector by symbol */
583
cmd_filter_by_symbol (char *command, char *symbol)
587
if (strcmp (symbol, "IPV4_ADDRESS") == 0)
590
lim = strlen (command);
593
if (! (isdigit ((int) command[i]) || command[i] == '.' || command[i] == '/'))
599
if (strcmp (symbol, "STRING") == 0)
602
lim = strlen (command);
605
if (! (isalpha ((int) command[i]) || command[i] == '_' || command[i] == '-'))
611
if (strcmp (symbol, "IFNAME") == 0)
614
lim = strlen (command);
617
if (! isalnum ((int) command[i]))
626
/* Completion match types. */
642
cmd_ipv4_match (char *str)
645
int dots = 0, nums = 0;
653
memset (buf, 0, sizeof (buf));
662
if (*(str + 1) == '.')
665
if (*(str + 1) == '\0')
671
if (!isdigit ((int) *str))
680
strncpy (buf, sp, str - sp);
681
if (atoi (buf) > 255)
699
cmd_ipv4_prefix_match (char *str)
710
memset (buf, 0, sizeof (buf));
712
while (*str != '\0' && *str != '/')
719
if (*(str + 1) == '.' || *(str + 1) == '/')
722
if (*(str + 1) == '\0')
729
if (!isdigit ((int) *str))
738
strncpy (buf, sp, str - sp);
739
if (atoi (buf) > 255)
746
if (*(str + 1) == '\0')
752
else if (*str == '\0')
765
if (!isdigit ((int) *str))
777
#define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
778
#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
779
#define STATE_START 1
780
#define STATE_COLON 2
781
#define STATE_DOUBLE 3
784
#define STATE_SLASH 6
790
cmd_ipv6_match (char *str)
792
int state = STATE_START;
793
int colons = 0, nums = 0, double_colon = 0;
795
struct sockaddr_in6 sin6_dummy;
801
if (strspn (str, IPV6_ADDR_STR) != strlen (str))
804
/* use inet_pton that has a better support,
805
* for example inet_pton can support the automatic addresses:
808
ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
820
if (*(str + 1) != ':' && *(str + 1) != '\0')
834
if (*(str + 1) == ':')
835
state = STATE_DOUBLE;
846
if (*(str + 1) == ':')
850
if (*(str + 1) != '\0')
860
if (*(str + 1) == ':' || *(str + 1) == '\0')
868
if (*(str + 1) == '.')
896
cmd_ipv6_prefix_match (char *str)
898
int state = STATE_START;
899
int colons = 0, nums = 0, double_colon = 0;
907
if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
910
while (*str != '\0' && state != STATE_MASK)
917
if (*(str + 1) != ':' && *(str + 1) != '\0')
931
if (*(str + 1) == '/')
933
else if (*(str + 1) == ':')
934
state = STATE_DOUBLE;
945
if (*(str + 1) == ':')
949
if (*(str + 1) != '\0' && *(str + 1) != '/')
953
if (*(str + 1) == '/')
963
if (*(str + 1) == ':' || *(str + 1) == '.'
964
|| *(str + 1) == '\0' || *(str + 1) == '/')
969
for (; sp <= str; sp++)
975
if (*(str + 1) == ':')
977
else if (*(str + 1) == '.')
979
else if (*(str + 1) == '/')
987
if (*(str + 1) == '\0')
1005
if (state < STATE_MASK)
1006
return partly_match;
1008
mask = strtol (str, &endptr, 10);
1009
if (*endptr != '\0')
1012
if (mask < 0 || mask > 128)
1015
/* I don't know why mask < 13 makes command match partly.
1016
Forgive me to make this comments. I Want to set static default route
1017
because of lack of function to originate default in ospf6d; sorry
1020
return partly_match;
1026
#endif /* HAVE_IPV6 */
1028
#define DECIMAL_STRLEN_MAX 10
1031
cmd_range_match (char *range, char *str)
1034
char buf[DECIMAL_STRLEN_MAX + 1];
1035
char *endptr = NULL;
1036
unsigned long min, max, val;
1041
val = strtoul (str, &endptr, 10);
1042
if (*endptr != '\0')
1046
p = strchr (range, '-');
1049
if (p - range > DECIMAL_STRLEN_MAX)
1051
strncpy (buf, range, p - range);
1052
buf[p - range] = '\0';
1053
min = strtoul (buf, &endptr, 10);
1054
if (*endptr != '\0')
1058
p = strchr (range, '>');
1061
if (p - range > DECIMAL_STRLEN_MAX)
1063
strncpy (buf, range, p - range);
1064
buf[p - range] = '\0';
1065
max = strtoul (buf, &endptr, 10);
1066
if (*endptr != '\0')
1069
if (val < min || val > max)
1075
/* Make completion match and return match type flag. */
1077
cmd_filter_by_completion (char *command, vector v, int index)
1081
struct cmd_element *cmd_element;
1082
enum match_type match_type;
1086
match_type = no_match;
1088
/* If command and cmd_element string does not match set NULL to vector */
1089
for (i = 0; i < vector_max (v); i++)
1090
if ((cmd_element = vector_slot (v, i)) != NULL)
1092
if (index >= vector_max (cmd_element->strvec))
1093
vector_slot (v, i) = NULL;
1099
descvec = vector_slot (cmd_element->strvec, index);
1101
for (j = 0; j < vector_max (descvec); j++)
1103
desc = vector_slot (descvec, j);
1106
if (CMD_VARARG (str))
1108
if (match_type < vararg_match)
1109
match_type = vararg_match;
1112
else if (CMD_RANGE (str))
1114
if (cmd_range_match (str, command))
1116
if (match_type < range_match)
1117
match_type = range_match;
1123
else if (CMD_IPV6 (str))
1125
if (cmd_ipv6_match (command))
1127
if (match_type < ipv6_match)
1128
match_type = ipv6_match;
1133
else if (CMD_IPV6_PREFIX (str))
1135
if (cmd_ipv6_prefix_match (command))
1137
if (match_type < ipv6_prefix_match)
1138
match_type = ipv6_prefix_match;
1143
#endif /* HAVE_IPV6 */
1144
else if (CMD_IPV4 (str))
1146
if (cmd_ipv4_match (command))
1148
if (match_type < ipv4_match)
1149
match_type = ipv4_match;
1154
else if (CMD_IPV4_PREFIX (str))
1156
if (cmd_ipv4_prefix_match (command))
1158
if (match_type < ipv4_prefix_match)
1159
match_type = ipv4_prefix_match;
1164
/* Check is this point's argument optional ? */
1165
if (CMD_OPTION (str) || CMD_VARIABLE (str))
1167
if (match_type < extend_match)
1168
match_type = extend_match;
1171
else if (strncmp (command, str, strlen (command)) == 0)
1173
if (strcmp (command, str) == 0)
1174
match_type = exact_match;
1177
if (match_type < partly_match)
1178
match_type = partly_match;
1184
vector_slot (v, i) = NULL;
1190
/* Filter vector by command character with index. */
1192
cmd_filter_by_string (char *command, vector v, int index)
1196
struct cmd_element *cmd_element;
1197
enum match_type match_type;
1201
match_type = no_match;
1203
/* If command and cmd_element string does not match set NULL to vector */
1204
for (i = 0; i < vector_max (v); i++)
1205
if ((cmd_element = vector_slot (v, i)) != NULL)
1207
/* If given index is bigger than max string vector of command,
1209
if (index >= vector_max (cmd_element->strvec))
1210
vector_slot (v, i) = NULL;
1216
descvec = vector_slot (cmd_element->strvec, index);
1218
for (j = 0; j < vector_max (descvec); j++)
1220
desc = vector_slot (descvec, j);
1223
if (CMD_VARARG (str))
1225
if (match_type < vararg_match)
1226
match_type = vararg_match;
1229
else if (CMD_RANGE (str))
1231
if (cmd_range_match (str, command))
1233
if (match_type < range_match)
1234
match_type = range_match;
1239
else if (CMD_IPV6 (str))
1241
if (cmd_ipv6_match (command) == exact_match)
1243
if (match_type < ipv6_match)
1244
match_type = ipv6_match;
1248
else if (CMD_IPV6_PREFIX (str))
1250
if (cmd_ipv6_prefix_match (command) == exact_match)
1252
if (match_type < ipv6_prefix_match)
1253
match_type = ipv6_prefix_match;
1257
#endif /* HAVE_IPV6 */
1258
else if (CMD_IPV4 (str))
1260
if (cmd_ipv4_match (command) == exact_match)
1262
if (match_type < ipv4_match)
1263
match_type = ipv4_match;
1267
else if (CMD_IPV4_PREFIX (str))
1269
if (cmd_ipv4_prefix_match (command) == exact_match)
1271
if (match_type < ipv4_prefix_match)
1272
match_type = ipv4_prefix_match;
1276
else if (CMD_OPTION (str) || CMD_VARIABLE (str))
1278
if (match_type < extend_match)
1279
match_type = extend_match;
1284
if (strcmp (command, str) == 0)
1286
match_type = exact_match;
1292
vector_slot (v, i) = NULL;
1298
/* Check ambiguous match */
1300
is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
1305
struct cmd_element *cmd_element;
1306
char *matched = NULL;
1310
for (i = 0; i < vector_max (v); i++)
1311
if ((cmd_element = vector_slot (v, i)) != NULL)
1315
descvec = vector_slot (cmd_element->strvec, index);
1317
for (j = 0; j < vector_max (descvec); j++)
1319
enum match_type ret;
1321
desc = vector_slot (descvec, j);
1327
if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
1328
&& strcmp (command, str) == 0)
1332
if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
1333
&& strncmp (command, str, strlen (command)) == 0)
1335
if (matched && strcmp (matched, str) != 0)
1336
return 1; /* There is ambiguous match. */
1343
if (cmd_range_match (str, command))
1345
if (matched && strcmp (matched, str) != 0)
1357
case ipv6_prefix_match:
1358
if ((ret = cmd_ipv6_prefix_match (command)) != no_match)
1360
if (ret == partly_match)
1361
return 2; /* There is incomplete match. */
1366
#endif /* HAVE_IPV6 */
1371
case ipv4_prefix_match:
1372
if ((ret = cmd_ipv4_prefix_match (command)) != no_match)
1374
if (ret == partly_match)
1375
return 2; /* There is incomplete match. */
1381
if (CMD_OPTION (str) || CMD_VARIABLE (str))
1390
vector_slot (v, i) = NULL;
1395
/* If src matches dst return dst string, otherwise return NULL */
1397
cmd_entry_function (char *src, char *dst)
1399
/* Skip variable arguments. */
1400
if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) ||
1401
CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst))
1404
/* In case of 'command \t', given src is NULL string. */
1408
/* Matched with input string. */
1409
if (strncmp (src, dst, strlen (src)) == 0)
1415
/* If src matches dst return dst string, otherwise return NULL */
1416
/* This version will return the dst string always if it is
1417
CMD_VARIABLE for '?' key processing */
1419
cmd_entry_function_desc (char *src, char *dst)
1421
if (CMD_VARARG (dst))
1424
if (CMD_RANGE (dst))
1426
if (cmd_range_match (dst, src))
1435
if (cmd_ipv6_match (src))
1441
if (CMD_IPV6_PREFIX (dst))
1443
if (cmd_ipv6_prefix_match (src))
1448
#endif /* HAVE_IPV6 */
1452
if (cmd_ipv4_match (src))
1458
if (CMD_IPV4_PREFIX (dst))
1460
if (cmd_ipv4_prefix_match (src))
1466
/* Optional or variable commands always match on '?' */
1467
if (CMD_OPTION (dst) || CMD_VARIABLE (dst))
1470
/* In case of 'command \t', given src is NULL string. */
1474
if (strncmp (src, dst, strlen (src)) == 0)
1480
/* Check same string element existence. If it isn't there return
1483
cmd_unique_string (vector v, char *str)
1488
for (i = 0; i < vector_max (v); i++)
1489
if ((match = vector_slot (v, i)) != NULL)
1490
if (strcmp (match, str) == 0)
1495
/* Compare string to description vector. If there is same string
1496
return 1 else return 0. */
1498
desc_unique_string (vector v, char *str)
1503
for (i = 0; i < vector_max (v); i++)
1504
if ((desc = vector_slot (v, i)) != NULL)
1505
if (strcmp (desc->cmd, str) == 0)
1511
cmd_try_do_shortcut (enum node_type node, char* first_word) {
1512
if ( first_word != NULL &&
1513
node != AUTH_NODE &&
1514
node != VIEW_NODE &&
1515
node != AUTH_ENABLE_NODE &&
1516
node != ENABLE_NODE &&
1517
0 == strcmp( "do", first_word ) )
1522
/* '?' describe command support. */
1524
cmd_describe_command_real (vector vline, struct vty *vty, int *status)
1528
#define INIT_MATCHVEC_SIZE 10
1530
struct cmd_element *cmd_element;
1533
enum match_type match;
1535
static struct desc desc_cr = { "<cr>", "" };
1538
index = vector_max (vline) - 1;
1540
/* Make copy vector of current node's command vector. */
1541
cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1543
/* Prepare match vector */
1544
matchvec = vector_init (INIT_MATCHVEC_SIZE);
1546
/* Filter commands. */
1547
/* Only words precedes current word will be checked in this loop. */
1548
for (i = 0; i < index; i++)
1550
command = vector_slot (vline, i);
1551
match = cmd_filter_by_completion (command, cmd_vector, i);
1553
if (match == vararg_match)
1555
struct cmd_element *cmd_element;
1559
for (j = 0; j < vector_max (cmd_vector); j++)
1560
if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
1562
descvec = vector_slot (cmd_element->strvec,
1563
vector_max (cmd_element->strvec) - 1);
1564
for (k = 0; k < vector_max (descvec); k++)
1566
struct desc *desc = vector_slot (descvec, k);
1567
vector_set (matchvec, desc);
1571
vector_set (matchvec, &desc_cr);
1572
vector_free (cmd_vector);
1577
if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
1579
vector_free (cmd_vector);
1580
*status = CMD_ERR_AMBIGUOUS;
1585
vector_free (cmd_vector);
1586
*status = CMD_ERR_NO_MATCH;
1591
/* Prepare match vector */
1592
/* matchvec = vector_init (INIT_MATCHVEC_SIZE); */
1594
/* Make sure that cmd_vector is filtered based on current word */
1595
command = vector_slot (vline, index);
1597
match = cmd_filter_by_completion (command, cmd_vector, index);
1599
/* Make description vector. */
1600
for (i = 0; i < vector_max (cmd_vector); i++)
1601
if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
1603
char *string = NULL;
1604
vector strvec = cmd_element->strvec;
1606
/* if command is NULL, index may be equal to vector_max */
1607
if (command && index >= vector_max (strvec))
1608
vector_slot (cmd_vector, i) = NULL;
1611
/* Check if command is completed. */
1612
if (command == NULL && index == vector_max (strvec))
1615
if (! desc_unique_string (matchvec, string))
1616
vector_set (matchvec, &desc_cr);
1621
vector descvec = vector_slot (strvec, index);
1624
for (j = 0; j < vector_max (descvec); j++)
1626
desc = vector_slot (descvec, j);
1627
string = cmd_entry_function_desc (command, desc->cmd);
1630
/* Uniqueness check */
1631
if (! desc_unique_string (matchvec, string))
1632
vector_set (matchvec, desc);
1638
vector_free (cmd_vector);
1640
if (vector_slot (matchvec, 0) == NULL)
1642
vector_free (matchvec);
1643
*status= CMD_ERR_NO_MATCH;
1646
*status = CMD_SUCCESS;
1652
cmd_describe_command (vector vline, struct vty *vty, int *status)
1656
if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
1658
enum node_type onode;
1659
vector shifted_vline;
1663
vty->node = ENABLE_NODE;
1664
/* We can try it on enable node, cos' the vty is authenticated */
1666
shifted_vline = vector_init (vector_count(vline));
1668
for (index = 1; index < vector_max (vline); index++)
1670
vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
1673
ret = cmd_describe_command_real (shifted_vline, vty, status);
1675
vector_free(shifted_vline);
1681
return cmd_describe_command_real (vline, vty, status);
1685
/* Check LCD of matched command. */
1687
cmd_lcd (char **matched)
1695
if (matched[0] == NULL || matched[1] == NULL)
1698
for (i = 1; matched[i] != NULL; i++)
1700
s1 = matched[i - 1];
1703
for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
1718
/* Command line completion support. */
1720
cmd_complete_command_real (vector vline, struct vty *vty, int *status)
1723
vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1724
#define INIT_MATCHVEC_SIZE 10
1726
struct cmd_element *cmd_element;
1727
int index = vector_max (vline) - 1;
1734
/* First, filter by preceeding command string */
1735
for (i = 0; i < index; i++)
1737
enum match_type match;
1740
command = vector_slot (vline, i);
1742
/* First try completion match, if there is exactly match return 1 */
1743
match = cmd_filter_by_completion (command, cmd_vector, i);
1745
/* If there is exact match then filter ambiguous match else check
1747
if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
1749
vector_free (cmd_vector);
1750
*status = CMD_ERR_AMBIGUOUS;
1756
vector_free (cmd_vector);
1757
*status = CMD_ERR_NO_MATCH;
1763
/* Prepare match vector. */
1764
matchvec = vector_init (INIT_MATCHVEC_SIZE);
1766
/* Now we got into completion */
1767
for (i = 0; i < vector_max (cmd_vector); i++)
1768
if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
1771
vector strvec = cmd_element->strvec;
1773
/* Check field length */
1774
if (index >= vector_max (strvec))
1775
vector_slot (cmd_vector, i) = NULL;
1780
descvec = vector_slot (strvec, index);
1781
for (j = 0; j < vector_max (descvec); j++)
1783
desc = vector_slot (descvec, j);
1785
if ((string = cmd_entry_function (vector_slot (vline, index),
1787
if (cmd_unique_string (matchvec, string))
1788
vector_set (matchvec, XSTRDUP (MTYPE_TMP, string));
1793
/* We don't need cmd_vector any more. */
1794
vector_free (cmd_vector);
1796
/* No matched command */
1797
if (vector_slot (matchvec, 0) == NULL)
1799
vector_free (matchvec);
1801
/* In case of 'command \t' pattern. Do you need '?' command at
1802
the end of the line. */
1803
if (vector_slot (vline, index) == '\0')
1804
*status = CMD_ERR_NOTHING_TODO;
1806
*status = CMD_ERR_NO_MATCH;
1810
/* Only one matched */
1811
if (vector_slot (matchvec, 1) == NULL)
1813
match_str = (char **) matchvec->index;
1814
vector_only_wrapper_free (matchvec);
1815
*status = CMD_COMPLETE_FULL_MATCH;
1818
/* Make it sure last element is NULL. */
1819
vector_set (matchvec, NULL);
1821
/* Check LCD of matched strings. */
1822
if (vector_slot (vline, index) != NULL)
1824
lcd = cmd_lcd ((char **) matchvec->index);
1828
int len = strlen (vector_slot (vline, index));
1834
lcdstr = XMALLOC (MTYPE_TMP, lcd + 1);
1835
memcpy (lcdstr, matchvec->index[0], lcd);
1838
/* match_str = (char **) &lcdstr; */
1840
/* Free matchvec. */
1841
for (i = 0; i < vector_max (matchvec); i++)
1843
if (vector_slot (matchvec, i))
1844
XFREE (MTYPE_TMP, vector_slot (matchvec, i));
1846
vector_free (matchvec);
1848
/* Make new matchvec. */
1849
matchvec = vector_init (INIT_MATCHVEC_SIZE);
1850
vector_set (matchvec, lcdstr);
1851
match_str = (char **) matchvec->index;
1852
vector_only_wrapper_free (matchvec);
1854
*status = CMD_COMPLETE_MATCH;
1860
match_str = (char **) matchvec->index;
1861
vector_only_wrapper_free (matchvec);
1862
*status = CMD_COMPLETE_LIST_MATCH;
1867
cmd_complete_command (vector vline, struct vty *vty, int *status)
1871
if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
1873
enum node_type onode;
1874
vector shifted_vline;
1878
vty->node = ENABLE_NODE;
1879
/* We can try it on enable node, cos' the vty is authenticated */
1881
shifted_vline = vector_init (vector_count(vline));
1883
for (index = 1; index < vector_max (vline); index++)
1885
vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
1888
ret = cmd_complete_command_real (shifted_vline, vty, status);
1890
vector_free(shifted_vline);
1896
return cmd_complete_command_real (vline, vty, status);
1899
/* return parent node */
1900
/* MUST eventually converge on CONFIG_NODE */
1901
enum node_type node_parent ( enum node_type node )
1905
assert (node > CONFIG_NODE);
1909
case BGP_VPNV4_NODE:
1911
case BGP_IPV4M_NODE:
1915
case KEYCHAIN_KEY_NODE:
1916
ret = KEYCHAIN_NODE;
1925
/* Execute command by argument vline vector. */
1927
cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd)
1932
struct cmd_element *cmd_element;
1933
struct cmd_element *matched_element;
1934
unsigned int matched_count, incomplete_count;
1936
char *argv[CMD_ARGC_MAX];
1937
enum match_type match = 0;
1941
/* Make copy of command elements. */
1942
cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1944
for (index = 0; index < vector_max (vline); index++)
1948
command = vector_slot (vline, index);
1950
match = cmd_filter_by_completion (command, cmd_vector, index);
1952
if (match == vararg_match)
1955
ret = is_cmd_ambiguous (command, cmd_vector, index, match);
1959
vector_free (cmd_vector);
1960
return CMD_ERR_AMBIGUOUS;
1964
vector_free (cmd_vector);
1965
return CMD_ERR_NO_MATCH;
1969
/* Check matched count. */
1970
matched_element = NULL;
1972
incomplete_count = 0;
1974
for (i = 0; i < vector_max (cmd_vector); i++)
1975
if (vector_slot (cmd_vector,i) != NULL)
1977
cmd_element = vector_slot (cmd_vector,i);
1979
if (match == vararg_match || index >= cmd_element->cmdsize)
1981
matched_element = cmd_element;
1983
printf ("DEBUG: %s\n", cmd_element->string);
1993
/* Finish of using cmd_vector. */
1994
vector_free (cmd_vector);
1996
/* To execute command, matched_count must be 1.*/
1997
if (matched_count == 0)
1999
if (incomplete_count)
2000
return CMD_ERR_INCOMPLETE;
2002
return CMD_ERR_NO_MATCH;
2005
if (matched_count > 1)
2006
return CMD_ERR_AMBIGUOUS;
2008
/* Argument treatment */
2012
for (i = 0; i < vector_max (vline); i++)
2015
argv[argc++] = vector_slot (vline, i);
2018
vector descvec = vector_slot (matched_element->strvec, i);
2020
if (vector_max (descvec) == 1)
2022
struct desc *desc = vector_slot (descvec, 0);
2023
char *str = desc->cmd;
2025
if (CMD_VARARG (str))
2028
if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str))
2029
argv[argc++] = vector_slot (vline, i);
2032
argv[argc++] = vector_slot (vline, i);
2035
if (argc >= CMD_ARGC_MAX)
2036
return CMD_ERR_EXEED_ARGC_MAX;
2039
/* For vtysh execution. */
2041
*cmd = matched_element;
2043
if (matched_element->daemon)
2044
return CMD_SUCCESS_DAEMON;
2046
/* Execute matched command. */
2047
return (*matched_element->func) (matched_element, vty, argc, argv);
2052
cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) {
2053
int ret, saved_ret, tried = 0;
2054
enum node_type onode, try_node;
2056
onode = try_node = vty->node;
2058
if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
2060
vector shifted_vline;
2063
vty->node = ENABLE_NODE;
2064
/* We can try it on enable node, cos' the vty is authenticated */
2066
shifted_vline = vector_init (vector_count(vline));
2068
for (index = 1; index < vector_max (vline); index++)
2070
vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
2073
ret = cmd_execute_command_real (shifted_vline, vty, cmd);
2075
vector_free(shifted_vline);
2081
saved_ret = ret = cmd_execute_command_real (vline, vty, cmd);
2083
/* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
2084
while ( ret != CMD_SUCCESS && ret != CMD_WARNING
2085
&& vty->node > CONFIG_NODE )
2087
try_node = node_parent(try_node);
2088
vty->node = try_node;
2089
ret = cmd_execute_command_real (vline, vty, cmd);
2091
if (ret == CMD_SUCCESS || ret == CMD_WARNING)
2093
/* succesfull command, leave the node as is */
2097
/* no command succeeded, reset the vty to the original node and
2098
return the error for this node */
2104
/* Execute command by argument readline. */
2106
cmd_execute_command_strict (vector vline, struct vty *vty,
2107
struct cmd_element **cmd)
2112
struct cmd_element *cmd_element;
2113
struct cmd_element *matched_element;
2114
unsigned int matched_count, incomplete_count;
2116
char *argv[CMD_ARGC_MAX];
2118
enum match_type match = 0;
2121
/* Make copy of command element */
2122
cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
2124
for (index = 0; index < vector_max (vline); index++)
2128
command = vector_slot (vline, index);
2130
match = cmd_filter_by_string (vector_slot (vline, index),
2133
/* If command meets '.VARARG' then finish matching. */
2134
if (match == vararg_match)
2137
ret = is_cmd_ambiguous (command, cmd_vector, index, match);
2140
vector_free (cmd_vector);
2141
return CMD_ERR_AMBIGUOUS;
2145
vector_free (cmd_vector);
2146
return CMD_ERR_NO_MATCH;
2150
/* Check matched count. */
2151
matched_element = NULL;
2153
incomplete_count = 0;
2154
for (i = 0; i < vector_max (cmd_vector); i++)
2155
if (vector_slot (cmd_vector,i) != NULL)
2157
cmd_element = vector_slot (cmd_vector,i);
2159
if (match == vararg_match || index >= cmd_element->cmdsize)
2161
matched_element = cmd_element;
2168
/* Finish of using cmd_vector. */
2169
vector_free (cmd_vector);
2171
/* To execute command, matched_count must be 1.*/
2172
if (matched_count == 0)
2174
if (incomplete_count)
2175
return CMD_ERR_INCOMPLETE;
2177
return CMD_ERR_NO_MATCH;
2180
if (matched_count > 1)
2181
return CMD_ERR_AMBIGUOUS;
2183
/* Argument treatment */
2187
for (i = 0; i < vector_max (vline); i++)
2190
argv[argc++] = vector_slot (vline, i);
2193
vector descvec = vector_slot (matched_element->strvec, i);
2195
if (vector_max (descvec) == 1)
2197
struct desc *desc = vector_slot (descvec, 0);
2198
char *str = desc->cmd;
2200
if (CMD_VARARG (str))
2203
if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str))
2204
argv[argc++] = vector_slot (vline, i);
2207
argv[argc++] = vector_slot (vline, i);
2210
if (argc >= CMD_ARGC_MAX)
2211
return CMD_ERR_EXEED_ARGC_MAX;
2214
/* For vtysh execution. */
2216
*cmd = matched_element;
2218
if (matched_element->daemon)
2219
return CMD_SUCCESS_DAEMON;
2221
/* Now execute matched command */
2222
return (*matched_element->func) (matched_element, vty, argc, argv);
2225
/* Configration make from file. */
2227
config_from_file (struct vty *vty, FILE *fp)
2232
while (fgets (vty->buf, VTY_BUFSIZ, fp))
2234
vline = cmd_make_strvec (vty->buf);
2236
/* In case of comment line */
2239
/* Execute configuration command : this is strict match */
2240
ret = cmd_execute_command_strict (vline, vty, NULL);
2242
/* Try again with setting node to CONFIG_NODE */
2243
while (ret != CMD_SUCCESS && ret != CMD_WARNING
2244
&& vty->node != CONFIG_NODE)
2246
vty->node = node_parent(vty->node);
2247
ret = cmd_execute_command_strict (vline, vty, NULL);
2250
cmd_free_strvec (vline);
2252
if (ret != CMD_SUCCESS && ret != CMD_WARNING)
2258
/* Configration from terminal */
2259
DEFUN (config_terminal,
2260
config_terminal_cmd,
2261
"configure terminal",
2262
"Configuration from vty interface\n"
2263
"Configuration terminal\n")
2265
if (vty_config_lock (vty))
2266
vty->node = CONFIG_NODE;
2269
vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
2275
/* Enable command */
2279
"Turn on privileged mode command\n")
2281
/* If enable password is NULL, change to ENABLE_NODE */
2282
if ((host.enable == NULL && host.enable_encrypt == NULL) ||
2283
vty->type == VTY_SHELL_SERV)
2284
vty->node = ENABLE_NODE;
2286
vty->node = AUTH_ENABLE_NODE;
2291
/* Disable command */
2295
"Turn off privileged mode command\n")
2297
if (vty->node == ENABLE_NODE)
2298
vty->node = VIEW_NODE;
2302
/* Down vty node level. */
2306
"Exit current mode and down to previous mode\n")
2312
if (vty_shell (vty))
2315
vty->status = VTY_CLOSE;
2318
vty->node = ENABLE_NODE;
2319
vty_config_unlock (vty);
2321
case INTERFACE_NODE:
2333
vty->node = CONFIG_NODE;
2335
case BGP_VPNV4_NODE:
2337
case BGP_IPV4M_NODE:
2339
vty->node = BGP_NODE;
2341
case KEYCHAIN_KEY_NODE:
2342
vty->node = KEYCHAIN_NODE;
2350
/* quit is alias of exit. */
2354
"Exit current mode and down to previous mode\n")
2356
/* End of configuration. */
2360
"End current mode and change to enable mode.")
2366
/* Nothing to do. */
2369
case INTERFACE_NODE:
2374
case BGP_VPNV4_NODE:
2376
case BGP_IPV4M_NODE:
2383
case KEYCHAIN_KEY_NODE:
2386
vty_config_unlock (vty);
2387
vty->node = ENABLE_NODE;
2396
DEFUN (show_version,
2400
"Displays zebra version\n")
2402
vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION,
2405
vty_out (vty, "Copyright 1996-2002, Kunihiro Ishiguro.%s", VTY_NEWLINE);
2410
/* Help display function for all node. */
2414
"Description of the interactive help system\n")
2417
"Zebra VTY provides advanced help feature. When you need help,%s\
2418
anytime at the command line please press '?'.%s\
2420
If nothing matches, the help list will be empty and you must backup%s\
2421
until entering a '?' shows the available options.%s\
2422
Two styles of help are provided:%s\
2423
1. Full help is available when you are ready to enter a%s\
2424
command argument (e.g. 'show ?') and describes each possible%s\
2426
2. Partial help is provided when an abbreviated argument is entered%s\
2427
and you want to know what arguments match the input%s\
2428
(e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2429
VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2430
VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2434
/* Help display function for all node. */
2438
"Print command list\n")
2441
struct cmd_node *cnode = vector_slot (cmdvec, vty->node);
2442
struct cmd_element *cmd;
2444
for (i = 0; i < vector_max (cnode->cmd_vector); i++)
2445
if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL)
2446
vty_out (vty, " %s%s", cmd->string,
2451
/* Write current configuration into file. */
2452
DEFUN (config_write_file,
2453
config_write_file_cmd,
2455
"Write running configuration to memory, network, or terminal\n"
2456
"Write to configuration file\n")
2460
struct cmd_node *node;
2462
char *config_file_tmp = NULL;
2463
char *config_file_sav = NULL;
2464
struct vty *file_vty;
2466
/* Check and see if we are operating under vtysh configuration */
2467
if (host.config == NULL)
2469
vty_out (vty, "Can't save to configuration file, using vtysh.%s",
2475
config_file = host.config;
2477
config_file_sav = malloc (strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1);
2478
strcpy (config_file_sav, config_file);
2479
strcat (config_file_sav, CONF_BACKUP_EXT);
2482
config_file_tmp = malloc (strlen (config_file) + 8);
2483
sprintf (config_file_tmp, "%s.XXXXXX", config_file);
2485
/* Open file to configuration write. */
2486
fd = mkstemp (config_file_tmp);
2489
vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp,
2491
free (config_file_tmp);
2492
free (config_file_sav);
2496
/* Make vty for configuration file. */
2497
file_vty = vty_new ();
2499
file_vty->type = VTY_FILE;
2501
/* Config file header print. */
2502
vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! ");
2503
vty_time_print (file_vty, 1);
2504
vty_out (file_vty, "!\n");
2506
for (i = 0; i < vector_max (cmdvec); i++)
2507
if ((node = vector_slot (cmdvec, i)) && node->func)
2509
if ((*node->func) (file_vty))
2510
vty_out (file_vty, "!\n");
2512
vty_close (file_vty);
2514
if (unlink (config_file_sav) != 0)
2515
if (errno != ENOENT)
2517
vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav,
2519
free (config_file_sav);
2520
free (config_file_tmp);
2521
unlink (config_file_tmp);
2524
if (link (config_file, config_file_sav) != 0)
2526
vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
2528
free (config_file_sav);
2529
free (config_file_tmp);
2530
unlink (config_file_tmp);
2534
if (unlink (config_file) != 0)
2536
vty_out (vty, "Can't unlink configuration file %s.%s", config_file,
2538
free (config_file_sav);
2539
free (config_file_tmp);
2540
unlink (config_file_tmp);
2543
if (link (config_file_tmp, config_file) != 0)
2545
vty_out (vty, "Can't save configuration file %s.%s", config_file,
2547
free (config_file_sav);
2548
free (config_file_tmp);
2549
unlink (config_file_tmp);
2552
unlink (config_file_tmp);
2555
free (config_file_sav);
2556
free (config_file_tmp);
2558
if (chmod (config_file, CONFIGFILE_MASK) != 0)
2560
vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s",
2561
config_file, strerror(errno), errno, VTY_NEWLINE);
2565
vty_out (vty, "Configuration saved to %s%s", config_file,
2570
ALIAS (config_write_file,
2573
"Write running configuration to memory, network, or terminal\n")
2575
ALIAS (config_write_file,
2576
config_write_memory_cmd,
2578
"Write running configuration to memory, network, or terminal\n"
2579
"Write configuration to the file (same as write file)\n")
2581
ALIAS (config_write_file,
2582
copy_runningconfig_startupconfig_cmd,
2583
"copy running-config startup-config",
2584
"Copy configuration\n"
2585
"Copy running config to... \n"
2586
"Copy running config to startup config (same as write file)\n")
2588
/* Write current configuration into the terminal. */
2589
DEFUN (config_write_terminal,
2590
config_write_terminal_cmd,
2592
"Write running configuration to memory, network, or terminal\n"
2593
"Write to terminal\n")
2596
struct cmd_node *node;
2598
if (vty->type == VTY_SHELL_SERV)
2600
for (i = 0; i < vector_max (cmdvec); i++)
2601
if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
2603
if ((*node->func) (vty))
2604
vty_out (vty, "!%s", VTY_NEWLINE);
2609
vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
2611
vty_out (vty, "!%s", VTY_NEWLINE);
2613
for (i = 0; i < vector_max (cmdvec); i++)
2614
if ((node = vector_slot (cmdvec, i)) && node->func)
2616
if ((*node->func) (vty))
2617
vty_out (vty, "!%s", VTY_NEWLINE);
2619
vty_out (vty, "end%s",VTY_NEWLINE);
2624
/* Write current configuration into the terminal. */
2625
ALIAS (config_write_terminal,
2626
show_running_config_cmd,
2627
"show running-config",
2629
"running configuration\n")
2631
/* Write startup configuration into the terminal. */
2632
DEFUN (show_startup_config,
2633
show_startup_config_cmd,
2634
"show startup-config",
2636
"Contentes of startup configuration\n")
2641
confp = fopen (host.config, "r");
2644
vty_out (vty, "Can't open configuration file [%s]%s",
2645
host.config, VTY_NEWLINE);
2649
while (fgets (buf, BUFSIZ, confp))
2653
while (*cp != '\r' && *cp != '\n' && *cp != '\0')
2657
vty_out (vty, "%s%s", buf, VTY_NEWLINE);
2665
/* Hostname configuration */
2666
DEFUN (config_hostname,
2669
"Set system's network name\n"
2670
"This system's network name\n")
2672
if (!isalpha((int) *argv[0]))
2674
vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE);
2679
XFREE (0, host.name);
2681
host.name = strdup (argv[0]);
2685
DEFUN (config_no_hostname,
2687
"no hostname [HOSTNAME]",
2689
"Reset system's network name\n"
2690
"Host name of this router\n")
2693
XFREE (0, host.name);
2698
/* VTY interface password set. */
2699
DEFUN (config_password, password_cmd,
2700
"password (8|) WORD",
2701
"Assign the terminal connection password\n"
2702
"Specifies a HIDDEN password will follow\n"
2704
"The HIDDEN line password string\n")
2706
/* Argument check. */
2709
vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
2715
if (*argv[0] == '8')
2718
XFREE (0, host.password);
2719
host.password = NULL;
2720
if (host.password_encrypt)
2721
XFREE (0, host.password_encrypt);
2722
host.password_encrypt = XSTRDUP (0, strdup (argv[1]));
2727
vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
2732
if (!isalnum ((int) *argv[0]))
2735
"Please specify string starting with alphanumeric%s", VTY_NEWLINE);
2740
XFREE (0, host.password);
2741
host.password = NULL;
2745
if (host.password_encrypt)
2746
XFREE (0, host.password_encrypt);
2747
host.password_encrypt = XSTRDUP (0, zencrypt (argv[0]));
2750
host.password = XSTRDUP (0, argv[0]);
2755
ALIAS (config_password, password_text_cmd,
2757
"Assign the terminal connection password\n"
2758
"The UNENCRYPTED (cleartext) line password\n")
2760
/* VTY enable password set. */
2761
DEFUN (config_enable_password, enable_password_cmd,
2762
"enable password (8|) WORD",
2763
"Modify enable password parameters\n"
2764
"Assign the privileged level password\n"
2765
"Specifies a HIDDEN password will follow\n"
2767
"The HIDDEN 'enable' password string\n")
2769
/* Argument check. */
2772
vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
2776
/* Crypt type is specified. */
2779
if (*argv[0] == '8')
2782
XFREE (0, host.enable);
2785
if (host.enable_encrypt)
2786
XFREE (0, host.enable_encrypt);
2787
host.enable_encrypt = XSTRDUP (0, argv[1]);
2793
vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
2798
if (!isalnum ((int) *argv[0]))
2801
"Please specify string starting with alphanumeric%s", VTY_NEWLINE);
2806
XFREE (0, host.enable);
2809
/* Plain password input. */
2812
if (host.enable_encrypt)
2813
XFREE (0, host.enable_encrypt);
2814
host.enable_encrypt = XSTRDUP (0, zencrypt (argv[0]));
2817
host.enable = XSTRDUP (0, argv[0]);
2822
ALIAS (config_enable_password,
2823
enable_password_text_cmd,
2824
"enable password LINE",
2825
"Modify enable password parameters\n"
2826
"Assign the privileged level password\n"
2827
"The UNENCRYPTED (cleartext) 'enable' password\n")
2829
/* VTY enable password delete. */
2830
DEFUN (no_config_enable_password, no_enable_password_cmd,
2831
"no enable password",
2833
"Modify enable password parameters\n"
2834
"Assign the privileged level password\n")
2837
XFREE (0, host.enable);
2840
if (host.enable_encrypt)
2841
XFREE (0, host.enable_encrypt);
2842
host.enable_encrypt = NULL;
2847
DEFUN (service_password_encrypt,
2848
service_password_encrypt_cmd,
2849
"service password-encryption",
2850
"Set up miscellaneous service\n"
2851
"Enable encrypted passwords\n")
2860
if (host.password_encrypt)
2861
XFREE (0, host.password_encrypt);
2862
host.password_encrypt = XSTRDUP (0, zencrypt (host.password));
2866
if (host.enable_encrypt)
2867
XFREE (0, host.enable_encrypt);
2868
host.enable_encrypt = XSTRDUP (0, zencrypt (host.enable));
2874
DEFUN (no_service_password_encrypt,
2875
no_service_password_encrypt_cmd,
2876
"no service password-encryption",
2878
"Set up miscellaneous service\n"
2879
"Enable encrypted passwords\n")
2886
if (host.password_encrypt)
2887
XFREE (0, host.password_encrypt);
2888
host.password_encrypt = NULL;
2890
if (host.enable_encrypt)
2891
XFREE (0, host.enable_encrypt);
2892
host.enable_encrypt = NULL;
2897
DEFUN (config_terminal_length, config_terminal_length_cmd,
2898
"terminal length <0-512>",
2899
"Set terminal line parameters\n"
2900
"Set number of lines on a screen\n"
2901
"Number of lines on screen (0 for no pausing)\n")
2904
char *endptr = NULL;
2906
lines = strtol (argv[0], &endptr, 10);
2907
if (lines < 0 || lines > 512 || *endptr != '\0')
2909
vty_out (vty, "length is malformed%s", VTY_NEWLINE);
2917
DEFUN (config_terminal_no_length, config_terminal_no_length_cmd,
2918
"terminal no length",
2919
"Set terminal line parameters\n"
2921
"Set number of lines on a screen\n")
2927
DEFUN (service_terminal_length, service_terminal_length_cmd,
2928
"service terminal-length <0-512>",
2929
"Set up miscellaneous service\n"
2930
"System wide terminal length configuration\n"
2931
"Number of lines of VTY (0 means no line control)\n")
2934
char *endptr = NULL;
2936
lines = strtol (argv[0], &endptr, 10);
2937
if (lines < 0 || lines > 512 || *endptr != '\0')
2939
vty_out (vty, "length is malformed%s", VTY_NEWLINE);
2947
DEFUN (no_service_terminal_length, no_service_terminal_length_cmd,
2948
"no service terminal-length [<0-512>]",
2950
"Set up miscellaneous service\n"
2951
"System wide terminal length configuration\n"
2952
"Number of lines of VTY (0 means no line control)\n")
2958
DEFUN (config_log_stdout,
2959
config_log_stdout_cmd,
2962
"Logging goes to stdout\n")
2964
zlog_set_flag (NULL, ZLOG_STDOUT);
2965
host.log_stdout = 1;
2969
DEFUN (no_config_log_stdout,
2970
no_config_log_stdout_cmd,
2974
"Cancel logging to stdout\n")
2976
zlog_reset_flag (NULL, ZLOG_STDOUT);
2977
host.log_stdout = 0;
2981
DEFUN (config_log_file,
2982
config_log_file_cmd,
2983
"log file FILENAME",
2986
"Logging filename\n")
2992
/* Path detection. */
2993
if (! IS_DIRECTORY_SEP (*argv[0]))
2995
cwd = getcwd (NULL, MAXPATHLEN);
2996
fullpath = XMALLOC (MTYPE_TMP,
2997
strlen (cwd) + strlen (argv[0]) + 2);
2998
sprintf (fullpath, "%s/%s", cwd, argv[0]);
3003
ret = zlog_set_file (NULL, ZLOG_FILE, fullpath);
3007
vty_out (vty, "can't open logfile %s\n", argv[0]);
3012
XFREE (MTYPE_TMP, host.logfile);
3014
host.logfile = strdup (argv[0]);
3019
DEFUN (no_config_log_file,
3020
no_config_log_file_cmd,
3021
"no log file [FILENAME]",
3024
"Cancel logging to file\n"
3025
"Logging file name\n")
3027
zlog_reset_file (NULL);
3030
XFREE (MTYPE_TMP, host.logfile);
3032
host.logfile = NULL;
3037
DEFUN (config_log_syslog,
3038
config_log_syslog_cmd,
3041
"Logging goes to syslog\n")
3043
zlog_set_flag (NULL, ZLOG_SYSLOG);
3044
host.log_syslog = 1;
3045
zlog_default->facility = LOG_DAEMON;
3049
DEFUN (config_log_syslog_facility,
3050
config_log_syslog_facility_cmd,
3051
"log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)",
3053
"Logging goes to syslog\n"
3054
"Facility parameter for syslog messages\n"
3059
"Authorization system\n"
3061
"Line printer system\n"
3063
"Unix-to-Unix copy system\n"
3064
"Cron/at facility\n"
3074
int facility = LOG_DAEMON;
3076
zlog_set_flag (NULL, ZLOG_SYSLOG);
3077
host.log_syslog = 1;
3079
if (strncmp (argv[0], "kern", 1) == 0)
3080
facility = LOG_KERN;
3081
else if (strncmp (argv[0], "user", 2) == 0)
3082
facility = LOG_USER;
3083
else if (strncmp (argv[0], "mail", 1) == 0)
3084
facility = LOG_MAIL;
3085
else if (strncmp (argv[0], "daemon", 1) == 0)
3086
facility = LOG_DAEMON;
3087
else if (strncmp (argv[0], "auth", 1) == 0)
3088
facility = LOG_AUTH;
3089
else if (strncmp (argv[0], "syslog", 1) == 0)
3090
facility = LOG_SYSLOG;
3091
else if (strncmp (argv[0], "lpr", 2) == 0)
3093
else if (strncmp (argv[0], "news", 1) == 0)
3094
facility = LOG_NEWS;
3095
else if (strncmp (argv[0], "uucp", 2) == 0)
3096
facility = LOG_UUCP;
3097
else if (strncmp (argv[0], "cron", 1) == 0)
3098
facility = LOG_CRON;
3099
else if (strncmp (argv[0], "local0", 6) == 0)
3100
facility = LOG_LOCAL0;
3101
else if (strncmp (argv[0], "local1", 6) == 0)
3102
facility = LOG_LOCAL1;
3103
else if (strncmp (argv[0], "local2", 6) == 0)
3104
facility = LOG_LOCAL2;
3105
else if (strncmp (argv[0], "local3", 6) == 0)
3106
facility = LOG_LOCAL3;
3107
else if (strncmp (argv[0], "local4", 6) == 0)
3108
facility = LOG_LOCAL4;
3109
else if (strncmp (argv[0], "local5", 6) == 0)
3110
facility = LOG_LOCAL5;
3111
else if (strncmp (argv[0], "local6", 6) == 0)
3112
facility = LOG_LOCAL6;
3113
else if (strncmp (argv[0], "local7", 6) == 0)
3114
facility = LOG_LOCAL7;
3116
zlog_default->facility = facility;
3121
DEFUN (no_config_log_syslog,
3122
no_config_log_syslog_cmd,
3126
"Cancel logging to syslog\n")
3128
zlog_reset_flag (NULL, ZLOG_SYSLOG);
3129
host.log_syslog = 0;
3130
zlog_default->facility = LOG_DAEMON;
3134
ALIAS (no_config_log_syslog,
3135
no_config_log_syslog_facility_cmd,
3136
"no log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)",
3139
"Logging goes to syslog\n"
3140
"Facility parameter for syslog messages\n"
3145
"Authorization system\n"
3147
"Line printer system\n"
3149
"Unix-to-Unix copy system\n"
3150
"Cron/at facility\n"
3160
DEFUN (config_log_trap,
3161
config_log_trap_cmd,
3162
"log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)",
3164
"Limit logging to specifed level\n")
3168
for ( new_level = 0 ; zlog_priority [new_level] != NULL ; new_level ++ )
3170
if ( strcmp ( argv[0], zlog_priority [new_level] ) == 0 )
3171
/* found new logging level */
3173
zlog_default->maskpri = new_level;
3177
return CMD_ERR_NO_MATCH;
3180
DEFUN (no_config_log_trap,
3181
no_config_log_trap_cmd,
3185
"Permit all logging information\n")
3187
zlog_default->maskpri = LOG_DEBUG;
3191
DEFUN (config_log_record_priority,
3192
config_log_record_priority_cmd,
3193
"log record-priority",
3195
"Log the priority of the message within the message\n")
3197
zlog_default->record_priority = 1 ;
3201
DEFUN (no_config_log_record_priority,
3202
no_config_log_record_priority_cmd,
3203
"no log record-priority",
3206
"Do not log the priority of the message within the message\n")
3208
zlog_default->record_priority = 0 ;
3213
DEFUN (banner_motd_default,
3214
banner_motd_default_cmd,
3215
"banner motd default",
3216
"Set banner string\n"
3217
"Strings for motd\n"
3220
host.motd = default_motd;
3224
DEFUN (no_banner_motd,
3228
"Set banner string\n"
3229
"Strings for motd\n")
3235
/* Set config filename. Called from vty.c */
3237
host_config_set (char *filename)
3239
host.config = strdup (filename);
3243
install_default (enum node_type node)
3245
install_element (node, &config_exit_cmd);
3246
install_element (node, &config_quit_cmd);
3247
install_element (node, &config_end_cmd);
3248
install_element (node, &config_help_cmd);
3249
install_element (node, &config_list_cmd);
3251
install_element (node, &config_write_terminal_cmd);
3252
install_element (node, &config_write_file_cmd);
3253
install_element (node, &config_write_memory_cmd);
3254
install_element (node, &config_write_cmd);
3255
install_element (node, &show_running_config_cmd);
3258
/* Initialize command interface. Install basic nodes and commands. */
3260
cmd_init (int terminal)
3262
/* Allocate initial top vector of commands. */
3263
cmdvec = vector_init (VECTOR_MIN_SIZE);
3265
/* Default host value settings. */
3267
host.password = NULL;
3269
host.logfile = NULL;
3272
host.motd = default_motd;
3274
/* Install top nodes. */
3275
install_node (&view_node, NULL);
3276
install_node (&enable_node, NULL);
3277
install_node (&auth_node, NULL);
3278
install_node (&auth_enable_node, NULL);
3279
install_node (&config_node, config_write_host);
3281
/* Each node's basic commands. */
3282
install_element (VIEW_NODE, &show_version_cmd);
3285
install_element (VIEW_NODE, &config_list_cmd);
3286
install_element (VIEW_NODE, &config_exit_cmd);
3287
install_element (VIEW_NODE, &config_quit_cmd);
3288
install_element (VIEW_NODE, &config_help_cmd);
3289
install_element (VIEW_NODE, &config_enable_cmd);
3290
install_element (VIEW_NODE, &config_terminal_length_cmd);
3291
install_element (VIEW_NODE, &config_terminal_no_length_cmd);
3296
install_default (ENABLE_NODE);
3297
install_element (ENABLE_NODE, &config_disable_cmd);
3298
install_element (ENABLE_NODE, &config_terminal_cmd);
3299
install_element (ENABLE_NODE, ©_runningconfig_startupconfig_cmd);
3301
install_element (ENABLE_NODE, &show_startup_config_cmd);
3302
install_element (ENABLE_NODE, &show_version_cmd);
3303
install_element (ENABLE_NODE, &config_terminal_length_cmd);
3304
install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
3307
install_default (CONFIG_NODE);
3308
install_element (CONFIG_NODE, &hostname_cmd);
3309
install_element (CONFIG_NODE, &no_hostname_cmd);
3310
install_element (CONFIG_NODE, &password_cmd);
3311
install_element (CONFIG_NODE, &password_text_cmd);
3312
install_element (CONFIG_NODE, &enable_password_cmd);
3313
install_element (CONFIG_NODE, &enable_password_text_cmd);
3314
install_element (CONFIG_NODE, &no_enable_password_cmd);
3317
install_element (CONFIG_NODE, &config_log_stdout_cmd);
3318
install_element (CONFIG_NODE, &no_config_log_stdout_cmd);
3319
install_element (CONFIG_NODE, &config_log_file_cmd);
3320
install_element (CONFIG_NODE, &no_config_log_file_cmd);
3321
install_element (CONFIG_NODE, &config_log_syslog_cmd);
3322
install_element (CONFIG_NODE, &config_log_syslog_facility_cmd);
3323
install_element (CONFIG_NODE, &no_config_log_syslog_cmd);
3324
install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd);
3325
install_element (CONFIG_NODE, &config_log_trap_cmd);
3326
install_element (CONFIG_NODE, &no_config_log_trap_cmd);
3327
install_element (CONFIG_NODE, &config_log_record_priority_cmd);
3328
install_element (CONFIG_NODE, &no_config_log_record_priority_cmd);
3329
install_element (CONFIG_NODE, &service_password_encrypt_cmd);
3330
install_element (CONFIG_NODE, &no_service_password_encrypt_cmd);
3331
install_element (CONFIG_NODE, &banner_motd_default_cmd);
3332
install_element (CONFIG_NODE, &no_banner_motd_cmd);
3333
install_element (CONFIG_NODE, &service_terminal_length_cmd);
3334
install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
3339
install_element(VIEW_NODE, &show_thread_cpu_cmd);
3340
install_element(ENABLE_NODE, &show_thread_cpu_cmd);