blob: 3891733baccd857bb512c280831aa495e08d8e4b [file] [log] [blame]
ajs274a4a42004-12-07 15:39:31 +00001/*
gdtf867d322005-01-14 15:47:33 +00002 $Id: command.c,v 1.32 2005/01/14 15:47:33 gdt Exp $
ajs274a4a42004-12-07 15:39:31 +00003
4 Command interpreter routine for virtual terminal [aka TeletYpe]
paul718e3742002-12-13 20:15:29 +00005 Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
6
7This file is part of GNU Zebra.
8
9GNU Zebra is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published
11by the Free Software Foundation; either version 2, or (at your
12option) any later version.
13
14GNU Zebra is distributed in the hope that it will be useful, but
15WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU Zebra; see the file COPYING. If not, write to the
21Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
23
24#include <zebra.h>
25
paulb21b19c2003-06-15 01:28:29 +000026
paul718e3742002-12-13 20:15:29 +000027#include "memory.h"
28#include "log.h"
gdt5e4fa162004-03-16 14:38:36 +000029#include <lib/version.h>
paul9ab68122003-01-18 01:16:20 +000030#include "thread.h"
paulb21b19c2003-06-15 01:28:29 +000031#include "vector.h"
32#include "vty.h"
33#include "command.h"
paul718e3742002-12-13 20:15:29 +000034
35/* Command vector which includes some level of command lists. Normally
36 each daemon maintains each own cmdvec. */
37vector cmdvec;
38
39/* Host information structure. */
40struct host host;
41
paul718e3742002-12-13 20:15:29 +000042/* Standard command node structures. */
43struct cmd_node auth_node =
44{
45 AUTH_NODE,
46 "Password: ",
47};
48
49struct cmd_node view_node =
50{
51 VIEW_NODE,
52 "%s> ",
53};
54
55struct cmd_node auth_enable_node =
56{
57 AUTH_ENABLE_NODE,
58 "Password: ",
59};
60
61struct cmd_node enable_node =
62{
63 ENABLE_NODE,
64 "%s# ",
65};
66
67struct cmd_node config_node =
68{
69 CONFIG_NODE,
70 "%s(config)# ",
71 1
72};
hasso6590f2c2004-10-19 20:40:08 +000073
74/* Default motd string. */
75const char *default_motd =
76"\r\n\
77Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
78" QUAGGA_COPYRIGHT "\r\n\
79\r\n";
80
ajs274a4a42004-12-07 15:39:31 +000081
82static struct facility_map {
83 int facility;
84 const char *name;
85 size_t match;
86} syslog_facilities[] =
87 {
88 { LOG_KERN, "kern", 1 },
89 { LOG_USER, "user", 2 },
90 { LOG_MAIL, "mail", 1 },
91 { LOG_DAEMON, "daemon", 1 },
92 { LOG_AUTH, "auth", 1 },
93 { LOG_SYSLOG, "syslog", 1 },
94 { LOG_LPR, "lpr", 2 },
95 { LOG_NEWS, "news", 1 },
96 { LOG_UUCP, "uucp", 2 },
97 { LOG_CRON, "cron", 1 },
98#ifdef LOG_FTP
99 { LOG_FTP, "ftp", 1 },
100#endif
101 { LOG_LOCAL0, "local0", 6 },
102 { LOG_LOCAL1, "local1", 6 },
103 { LOG_LOCAL2, "local2", 6 },
104 { LOG_LOCAL3, "local3", 6 },
105 { LOG_LOCAL4, "local4", 6 },
106 { LOG_LOCAL5, "local5", 6 },
107 { LOG_LOCAL6, "local6", 6 },
108 { LOG_LOCAL7, "local7", 6 },
109 { 0, NULL, 0 },
110 };
111
112static const char *
113facility_name(int facility)
114{
115 struct facility_map *fm;
116
117 for (fm = syslog_facilities; fm->name; fm++)
118 if (fm->facility == facility)
119 return fm->name;
120 return "";
121}
122
123static int
124facility_match(const char *str)
125{
126 struct facility_map *fm;
127
128 for (fm = syslog_facilities; fm->name; fm++)
129 if (!strncmp(str,fm->name,fm->match))
130 return fm->facility;
131 return -1;
132}
133
134static int
135level_match(const char *s)
136{
137 int level ;
138
139 for ( level = 0 ; zlog_priority [level] != NULL ; level ++ )
140 if (!strncmp (s, zlog_priority[level], 2))
141 return level;
142 return ZLOG_DISABLED;
143}
144
hasso6590f2c2004-10-19 20:40:08 +0000145void
146print_version (const char *progname)
147{
gdtf867d322005-01-14 15:47:33 +0000148 printf ("%s version %s", progname, QUAGGA_VERSION);
149 if (host.name != NULL)
150 printf (" (%s)", host.name);
151 printf ("\n%s\n", QUAGGA_COPYRIGHT);
hasso6590f2c2004-10-19 20:40:08 +0000152}
153
paul718e3742002-12-13 20:15:29 +0000154
155/* Utility function to concatenate argv argument into a single string
156 with inserting ' ' character between each argument. */
157char *
paul42d49862004-10-13 05:22:18 +0000158argv_concat (const char **argv, int argc, int shift)
paul718e3742002-12-13 20:15:29 +0000159{
160 int i;
161 int len;
162 int index;
163 char *str;
164
165 str = NULL;
166 index = 0;
167
168 for (i = shift; i < argc; i++)
169 {
170 len = strlen (argv[i]);
171
172 if (i == shift)
173 {
174 str = XSTRDUP (MTYPE_TMP, argv[i]);
175 index = len;
176 }
177 else
178 {
179 str = XREALLOC (MTYPE_TMP, str, (index + len + 2));
180 str[index++] = ' ';
181 memcpy (str + index, argv[i], len);
182 index += len;
183 str[index] = '\0';
184 }
185 }
186 return str;
187}
188
189/* Install top node of command vector. */
190void
191install_node (struct cmd_node *node,
192 int (*func) (struct vty *))
193{
194 vector_set_index (cmdvec, node->node, node);
195 node->func = func;
196 node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
197}
198
199/* Compare two command's string. Used in sort_node (). */
ajs274a4a42004-12-07 15:39:31 +0000200static int
paul718e3742002-12-13 20:15:29 +0000201cmp_node (const void *p, const void *q)
202{
203 struct cmd_element *a = *(struct cmd_element **)p;
204 struct cmd_element *b = *(struct cmd_element **)q;
205
206 return strcmp (a->string, b->string);
207}
208
ajs274a4a42004-12-07 15:39:31 +0000209static int
paul718e3742002-12-13 20:15:29 +0000210cmp_desc (const void *p, const void *q)
211{
212 struct desc *a = *(struct desc **)p;
213 struct desc *b = *(struct desc **)q;
214
215 return strcmp (a->cmd, b->cmd);
216}
217
218/* Sort each node's command element according to command string. */
219void
220sort_node ()
221{
hasso8c328f12004-10-05 21:01:23 +0000222 unsigned int i, j;
paul718e3742002-12-13 20:15:29 +0000223 struct cmd_node *cnode;
224 vector descvec;
225 struct cmd_element *cmd_element;
226
227 for (i = 0; i < vector_max (cmdvec); i++)
228 if ((cnode = vector_slot (cmdvec, i)) != NULL)
229 {
230 vector cmd_vector = cnode->cmd_vector;
231 qsort (cmd_vector->index, cmd_vector->max, sizeof (void *), cmp_node);
232
233 for (j = 0; j < vector_max (cmd_vector); j++)
234 if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
235 {
236 descvec = vector_slot (cmd_element->strvec,
237 vector_max (cmd_element->strvec) - 1);
238 qsort (descvec->index, descvec->max, sizeof (void *), cmp_desc);
239 }
240 }
241}
242
243/* Breaking up string into each command piece. I assume given
244 character is separated by a space character. Return value is a
245 vector which includes char ** data element. */
246vector
hassoea8e9d92004-10-07 21:32:14 +0000247cmd_make_strvec (const char *string)
paul718e3742002-12-13 20:15:29 +0000248{
hassoea8e9d92004-10-07 21:32:14 +0000249 const char *cp, *start;
250 char *token;
paul718e3742002-12-13 20:15:29 +0000251 int strlen;
252 vector strvec;
253
254 if (string == NULL)
255 return NULL;
256
257 cp = string;
258
259 /* Skip white spaces. */
260 while (isspace ((int) *cp) && *cp != '\0')
261 cp++;
262
263 /* Return if there is only white spaces */
264 if (*cp == '\0')
265 return NULL;
266
267 if (*cp == '!' || *cp == '#')
268 return NULL;
269
270 /* Prepare return vector. */
271 strvec = vector_init (VECTOR_MIN_SIZE);
272
273 /* Copy each command piece and set into vector. */
274 while (1)
275 {
276 start = cp;
277 while (!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') &&
278 *cp != '\0')
279 cp++;
280 strlen = cp - start;
281 token = XMALLOC (MTYPE_STRVEC, strlen + 1);
282 memcpy (token, start, strlen);
283 *(token + strlen) = '\0';
284 vector_set (strvec, token);
285
286 while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r') &&
287 *cp != '\0')
288 cp++;
289
290 if (*cp == '\0')
291 return strvec;
292 }
293}
294
295/* Free allocated string vector. */
296void
297cmd_free_strvec (vector v)
298{
hasso8c328f12004-10-05 21:01:23 +0000299 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000300 char *cp;
301
302 if (!v)
303 return;
304
305 for (i = 0; i < vector_max (v); i++)
306 if ((cp = vector_slot (v, i)) != NULL)
307 XFREE (MTYPE_STRVEC, cp);
308
309 vector_free (v);
310}
311
312/* Fetch next description. Used in cmd_make_descvec(). */
ajs274a4a42004-12-07 15:39:31 +0000313static char *
hasso6ad96ea2004-10-07 19:33:46 +0000314cmd_desc_str (const char **string)
paul718e3742002-12-13 20:15:29 +0000315{
hasso6ad96ea2004-10-07 19:33:46 +0000316 const char *cp, *start;
317 char *token;
paul718e3742002-12-13 20:15:29 +0000318 int strlen;
319
320 cp = *string;
321
322 if (cp == NULL)
323 return NULL;
324
325 /* Skip white spaces. */
326 while (isspace ((int) *cp) && *cp != '\0')
327 cp++;
328
329 /* Return if there is only white spaces */
330 if (*cp == '\0')
331 return NULL;
332
333 start = cp;
334
335 while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
336 cp++;
337
338 strlen = cp - start;
339 token = XMALLOC (MTYPE_STRVEC, strlen + 1);
340 memcpy (token, start, strlen);
341 *(token + strlen) = '\0';
342
343 *string = cp;
344
345 return token;
346}
347
348/* New string vector. */
ajs274a4a42004-12-07 15:39:31 +0000349static vector
hasso8c328f12004-10-05 21:01:23 +0000350cmd_make_descvec (const char *string, const char *descstr)
paul718e3742002-12-13 20:15:29 +0000351{
352 int multiple = 0;
hasso8c328f12004-10-05 21:01:23 +0000353 const char *sp;
paul718e3742002-12-13 20:15:29 +0000354 char *token;
355 int len;
hasso8c328f12004-10-05 21:01:23 +0000356 const char *cp;
357 const char *dp;
paul718e3742002-12-13 20:15:29 +0000358 vector allvec;
359 vector strvec = NULL;
360 struct desc *desc;
361
362 cp = string;
363 dp = descstr;
364
365 if (cp == NULL)
366 return NULL;
367
368 allvec = vector_init (VECTOR_MIN_SIZE);
369
370 while (1)
371 {
372 while (isspace ((int) *cp) && *cp != '\0')
373 cp++;
374
375 if (*cp == '(')
376 {
377 multiple = 1;
378 cp++;
379 }
380 if (*cp == ')')
381 {
382 multiple = 0;
383 cp++;
384 }
385 if (*cp == '|')
386 {
387 if (! multiple)
388 {
389 fprintf (stderr, "Command parse error!: %s\n", string);
390 exit (1);
391 }
392 cp++;
393 }
394
395 while (isspace ((int) *cp) && *cp != '\0')
396 cp++;
397
398 if (*cp == '(')
399 {
400 multiple = 1;
401 cp++;
402 }
403
404 if (*cp == '\0')
405 return allvec;
406
407 sp = cp;
408
409 while (! (isspace ((int) *cp) || *cp == '\r' || *cp == '\n' || *cp == ')' || *cp == '|') && *cp != '\0')
410 cp++;
411
412 len = cp - sp;
413
414 token = XMALLOC (MTYPE_STRVEC, len + 1);
415 memcpy (token, sp, len);
416 *(token + len) = '\0';
417
418 desc = XCALLOC (MTYPE_DESC, sizeof (struct desc));
419 desc->cmd = token;
420 desc->str = cmd_desc_str (&dp);
421
422 if (multiple)
423 {
424 if (multiple == 1)
425 {
426 strvec = vector_init (VECTOR_MIN_SIZE);
427 vector_set (allvec, strvec);
428 }
429 multiple++;
430 }
431 else
432 {
433 strvec = vector_init (VECTOR_MIN_SIZE);
434 vector_set (allvec, strvec);
435 }
436 vector_set (strvec, desc);
437 }
438}
439
440/* Count mandantory string vector size. This is to determine inputed
441 command has enough command length. */
ajs274a4a42004-12-07 15:39:31 +0000442static int
paul718e3742002-12-13 20:15:29 +0000443cmd_cmdsize (vector strvec)
444{
hasso8c328f12004-10-05 21:01:23 +0000445 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000446 int size = 0;
447 vector descvec;
448
449 for (i = 0; i < vector_max (strvec); i++)
450 {
451 descvec = vector_slot (strvec, i);
452
453 if (vector_max (descvec) == 1)
454 {
455 struct desc *desc = vector_slot (descvec, 0);
456
hasso8c328f12004-10-05 21:01:23 +0000457 if (desc->cmd == NULL || CMD_OPTION (desc->cmd))
paul718e3742002-12-13 20:15:29 +0000458 return size;
459 else
460 size++;
461 }
462 else
463 size++;
464 }
465 return size;
466}
467
468/* Return prompt character of specified node. */
hasso8c328f12004-10-05 21:01:23 +0000469const char *
paul718e3742002-12-13 20:15:29 +0000470cmd_prompt (enum node_type node)
471{
472 struct cmd_node *cnode;
473
474 cnode = vector_slot (cmdvec, node);
475 return cnode->prompt;
476}
477
478/* Install a command into a node. */
479void
480install_element (enum node_type ntype, struct cmd_element *cmd)
481{
482 struct cmd_node *cnode;
483
484 cnode = vector_slot (cmdvec, ntype);
485
486 if (cnode == NULL)
487 {
488 fprintf (stderr, "Command node %d doesn't exist, please check it\n",
489 ntype);
490 exit (1);
491 }
492
493 vector_set (cnode->cmd_vector, cmd);
494
495 cmd->strvec = cmd_make_descvec (cmd->string, cmd->doc);
496 cmd->cmdsize = cmd_cmdsize (cmd->strvec);
497}
498
499static unsigned char itoa64[] =
500"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
501
ajs274a4a42004-12-07 15:39:31 +0000502static void
paul718e3742002-12-13 20:15:29 +0000503to64(char *s, long v, int n)
504{
505 while (--n >= 0)
506 {
507 *s++ = itoa64[v&0x3f];
508 v >>= 6;
509 }
510}
511
ajs274a4a42004-12-07 15:39:31 +0000512static char *
513zencrypt (const char *passwd)
paul718e3742002-12-13 20:15:29 +0000514{
515 char salt[6];
516 struct timeval tv;
517 char *crypt (const char *, const char *);
518
519 gettimeofday(&tv,0);
520
521 to64(&salt[0], random(), 3);
522 to64(&salt[3], tv.tv_usec, 3);
523 salt[5] = '\0';
524
525 return crypt (passwd, salt);
526}
527
528/* This function write configuration of this host. */
ajs274a4a42004-12-07 15:39:31 +0000529static int
paul718e3742002-12-13 20:15:29 +0000530config_write_host (struct vty *vty)
531{
532 if (host.name)
533 vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE);
534
535 if (host.encrypt)
536 {
537 if (host.password_encrypt)
538 vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE);
539 if (host.enable_encrypt)
540 vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE);
541 }
542 else
543 {
544 if (host.password)
545 vty_out (vty, "password %s%s", host.password, VTY_NEWLINE);
546 if (host.enable)
547 vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE);
548 }
549
ajs274a4a42004-12-07 15:39:31 +0000550 if (zlog_default->default_lvl != LOG_DEBUG)
ajs82146b82004-12-07 17:15:55 +0000551 {
552 vty_out (vty, "! N.B. The 'log trap' command is deprecated.%s",
553 VTY_NEWLINE);
554 vty_out (vty, "log trap %s%s",
555 zlog_priority[zlog_default->default_lvl], VTY_NEWLINE);
556 }
paul718e3742002-12-13 20:15:29 +0000557
ajs274a4a42004-12-07 15:39:31 +0000558 if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED))
paul12ab19f2003-07-26 06:14:55 +0000559 {
ajs274a4a42004-12-07 15:39:31 +0000560 vty_out (vty, "log file %s", host.logfile);
561 if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl)
562 vty_out (vty, " %s",
563 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]);
paul12ab19f2003-07-26 06:14:55 +0000564 vty_out (vty, "%s", VTY_NEWLINE);
565 }
ajs274a4a42004-12-07 15:39:31 +0000566
567 if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED)
568 {
569 vty_out (vty, "log stdout");
570 if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl)
571 vty_out (vty, " %s",
572 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]);
573 vty_out (vty, "%s", VTY_NEWLINE);
574 }
575
576 if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
577 vty_out(vty,"no log monitor%s",VTY_NEWLINE);
578 else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl)
579 vty_out(vty,"log monitor %s%s",
580 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE);
581
582 if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
583 {
584 vty_out (vty, "log syslog");
585 if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl)
586 vty_out (vty, " %s",
587 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]);
588 vty_out (vty, "%s", VTY_NEWLINE);
589 }
590
591 if (zlog_default->facility != LOG_DAEMON)
592 vty_out (vty, "log facility %s%s",
593 facility_name(zlog_default->facility), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000594
595 if (zlog_default->record_priority == 1)
596 vty_out (vty, "log record-priority%s", VTY_NEWLINE);
597
598 if (host.advanced)
599 vty_out (vty, "service advanced-vty%s", VTY_NEWLINE);
600
601 if (host.encrypt)
602 vty_out (vty, "service password-encryption%s", VTY_NEWLINE);
603
604 if (host.lines >= 0)
605 vty_out (vty, "service terminal-length %d%s", host.lines,
606 VTY_NEWLINE);
607
608 if (! host.motd)
609 vty_out (vty, "no banner motd%s", VTY_NEWLINE);
610
611 return 1;
612}
613
614/* Utility function for getting command vector. */
ajs274a4a42004-12-07 15:39:31 +0000615static vector
paul718e3742002-12-13 20:15:29 +0000616cmd_node_vector (vector v, enum node_type ntype)
617{
618 struct cmd_node *cnode = vector_slot (v, ntype);
619 return cnode->cmd_vector;
620}
621
ajs274a4a42004-12-07 15:39:31 +0000622#if 0
623/* Filter command vector by symbol. This function is not actually used;
624 * should it be deleted? */
625static int
paul718e3742002-12-13 20:15:29 +0000626cmd_filter_by_symbol (char *command, char *symbol)
627{
628 int i, lim;
629
630 if (strcmp (symbol, "IPV4_ADDRESS") == 0)
631 {
632 i = 0;
633 lim = strlen (command);
634 while (i < lim)
635 {
636 if (! (isdigit ((int) command[i]) || command[i] == '.' || command[i] == '/'))
637 return 1;
638 i++;
639 }
640 return 0;
641 }
642 if (strcmp (symbol, "STRING") == 0)
643 {
644 i = 0;
645 lim = strlen (command);
646 while (i < lim)
647 {
648 if (! (isalpha ((int) command[i]) || command[i] == '_' || command[i] == '-'))
649 return 1;
650 i++;
651 }
652 return 0;
653 }
654 if (strcmp (symbol, "IFNAME") == 0)
655 {
656 i = 0;
657 lim = strlen (command);
658 while (i < lim)
659 {
660 if (! isalnum ((int) command[i]))
661 return 1;
662 i++;
663 }
664 return 0;
665 }
666 return 0;
667}
ajs274a4a42004-12-07 15:39:31 +0000668#endif
paul718e3742002-12-13 20:15:29 +0000669
670/* Completion match types. */
671enum match_type
672{
673 no_match,
674 extend_match,
675 ipv4_prefix_match,
676 ipv4_match,
677 ipv6_prefix_match,
678 ipv6_match,
679 range_match,
680 vararg_match,
681 partly_match,
682 exact_match
683};
684
ajs274a4a42004-12-07 15:39:31 +0000685static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000686cmd_ipv4_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000687{
hasso8c328f12004-10-05 21:01:23 +0000688 const char *sp;
paul718e3742002-12-13 20:15:29 +0000689 int dots = 0, nums = 0;
690 char buf[4];
691
692 if (str == NULL)
693 return partly_match;
694
695 for (;;)
696 {
697 memset (buf, 0, sizeof (buf));
698 sp = str;
699 while (*str != '\0')
700 {
701 if (*str == '.')
702 {
703 if (dots >= 3)
704 return no_match;
705
706 if (*(str + 1) == '.')
707 return no_match;
708
709 if (*(str + 1) == '\0')
710 return partly_match;
711
712 dots++;
713 break;
714 }
715 if (!isdigit ((int) *str))
716 return no_match;
717
718 str++;
719 }
720
721 if (str - sp > 3)
722 return no_match;
723
724 strncpy (buf, sp, str - sp);
725 if (atoi (buf) > 255)
726 return no_match;
727
728 nums++;
729
730 if (*str == '\0')
731 break;
732
733 str++;
734 }
735
736 if (nums < 4)
737 return partly_match;
738
739 return exact_match;
740}
741
ajs274a4a42004-12-07 15:39:31 +0000742static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000743cmd_ipv4_prefix_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000744{
hasso8c328f12004-10-05 21:01:23 +0000745 const char *sp;
paul718e3742002-12-13 20:15:29 +0000746 int dots = 0;
747 char buf[4];
748
749 if (str == NULL)
750 return partly_match;
751
752 for (;;)
753 {
754 memset (buf, 0, sizeof (buf));
755 sp = str;
756 while (*str != '\0' && *str != '/')
757 {
758 if (*str == '.')
759 {
760 if (dots == 3)
761 return no_match;
762
763 if (*(str + 1) == '.' || *(str + 1) == '/')
764 return no_match;
765
766 if (*(str + 1) == '\0')
767 return partly_match;
768
769 dots++;
770 break;
771 }
772
773 if (!isdigit ((int) *str))
774 return no_match;
775
776 str++;
777 }
778
779 if (str - sp > 3)
780 return no_match;
781
782 strncpy (buf, sp, str - sp);
783 if (atoi (buf) > 255)
784 return no_match;
785
786 if (dots == 3)
787 {
788 if (*str == '/')
789 {
790 if (*(str + 1) == '\0')
791 return partly_match;
792
793 str++;
794 break;
795 }
796 else if (*str == '\0')
797 return partly_match;
798 }
799
800 if (*str == '\0')
801 return partly_match;
802
803 str++;
804 }
805
806 sp = str;
807 while (*str != '\0')
808 {
809 if (!isdigit ((int) *str))
810 return no_match;
811
812 str++;
813 }
814
815 if (atoi (sp) > 32)
816 return no_match;
817
818 return exact_match;
819}
820
821#define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
822#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
823#define STATE_START 1
824#define STATE_COLON 2
825#define STATE_DOUBLE 3
826#define STATE_ADDR 4
827#define STATE_DOT 5
828#define STATE_SLASH 6
829#define STATE_MASK 7
830
paul22e0a9e2003-07-11 17:55:46 +0000831#ifdef HAVE_IPV6
832
ajs274a4a42004-12-07 15:39:31 +0000833static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000834cmd_ipv6_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000835{
836 int state = STATE_START;
837 int colons = 0, nums = 0, double_colon = 0;
hasso8c328f12004-10-05 21:01:23 +0000838 const char *sp = NULL;
hasso726f9b22003-05-25 21:04:54 +0000839 struct sockaddr_in6 sin6_dummy;
840 int ret;
paul718e3742002-12-13 20:15:29 +0000841
842 if (str == NULL)
843 return partly_match;
844
845 if (strspn (str, IPV6_ADDR_STR) != strlen (str))
846 return no_match;
847
hasso726f9b22003-05-25 21:04:54 +0000848 /* use inet_pton that has a better support,
849 * for example inet_pton can support the automatic addresses:
850 * ::1.2.3.4
851 */
852 ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
853
854 if (ret == 1)
855 return exact_match;
856
paul718e3742002-12-13 20:15:29 +0000857 while (*str != '\0')
858 {
859 switch (state)
860 {
861 case STATE_START:
862 if (*str == ':')
863 {
864 if (*(str + 1) != ':' && *(str + 1) != '\0')
865 return no_match;
866 colons--;
867 state = STATE_COLON;
868 }
869 else
870 {
871 sp = str;
872 state = STATE_ADDR;
873 }
874
875 continue;
876 case STATE_COLON:
877 colons++;
878 if (*(str + 1) == ':')
879 state = STATE_DOUBLE;
880 else
881 {
882 sp = str + 1;
883 state = STATE_ADDR;
884 }
885 break;
886 case STATE_DOUBLE:
887 if (double_colon)
888 return no_match;
889
890 if (*(str + 1) == ':')
891 return no_match;
892 else
893 {
894 if (*(str + 1) != '\0')
895 colons++;
896 sp = str + 1;
897 state = STATE_ADDR;
898 }
899
900 double_colon++;
901 nums++;
902 break;
903 case STATE_ADDR:
904 if (*(str + 1) == ':' || *(str + 1) == '\0')
905 {
906 if (str - sp > 3)
907 return no_match;
908
909 nums++;
910 state = STATE_COLON;
911 }
912 if (*(str + 1) == '.')
913 state = STATE_DOT;
914 break;
915 case STATE_DOT:
916 state = STATE_ADDR;
917 break;
918 default:
919 break;
920 }
921
922 if (nums > 8)
923 return no_match;
924
925 if (colons > 7)
926 return no_match;
927
928 str++;
929 }
930
931#if 0
932 if (nums < 11)
933 return partly_match;
934#endif /* 0 */
935
936 return exact_match;
937}
938
ajs274a4a42004-12-07 15:39:31 +0000939static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000940cmd_ipv6_prefix_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000941{
942 int state = STATE_START;
943 int colons = 0, nums = 0, double_colon = 0;
944 int mask;
hasso8c328f12004-10-05 21:01:23 +0000945 const char *sp = NULL;
paul718e3742002-12-13 20:15:29 +0000946 char *endptr = NULL;
947
948 if (str == NULL)
949 return partly_match;
950
951 if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
952 return no_match;
953
954 while (*str != '\0' && state != STATE_MASK)
955 {
956 switch (state)
957 {
958 case STATE_START:
959 if (*str == ':')
960 {
961 if (*(str + 1) != ':' && *(str + 1) != '\0')
962 return no_match;
963 colons--;
964 state = STATE_COLON;
965 }
966 else
967 {
968 sp = str;
969 state = STATE_ADDR;
970 }
971
972 continue;
973 case STATE_COLON:
974 colons++;
975 if (*(str + 1) == '/')
976 return no_match;
977 else if (*(str + 1) == ':')
978 state = STATE_DOUBLE;
979 else
980 {
981 sp = str + 1;
982 state = STATE_ADDR;
983 }
984 break;
985 case STATE_DOUBLE:
986 if (double_colon)
987 return no_match;
988
989 if (*(str + 1) == ':')
990 return no_match;
991 else
992 {
993 if (*(str + 1) != '\0' && *(str + 1) != '/')
994 colons++;
995 sp = str + 1;
996
997 if (*(str + 1) == '/')
998 state = STATE_SLASH;
999 else
1000 state = STATE_ADDR;
1001 }
1002
1003 double_colon++;
1004 nums += 1;
1005 break;
1006 case STATE_ADDR:
1007 if (*(str + 1) == ':' || *(str + 1) == '.'
1008 || *(str + 1) == '\0' || *(str + 1) == '/')
1009 {
1010 if (str - sp > 3)
1011 return no_match;
1012
1013 for (; sp <= str; sp++)
1014 if (*sp == '/')
1015 return no_match;
1016
1017 nums++;
1018
1019 if (*(str + 1) == ':')
1020 state = STATE_COLON;
1021 else if (*(str + 1) == '.')
1022 state = STATE_DOT;
1023 else if (*(str + 1) == '/')
1024 state = STATE_SLASH;
1025 }
1026 break;
1027 case STATE_DOT:
1028 state = STATE_ADDR;
1029 break;
1030 case STATE_SLASH:
1031 if (*(str + 1) == '\0')
1032 return partly_match;
1033
1034 state = STATE_MASK;
1035 break;
1036 default:
1037 break;
1038 }
1039
1040 if (nums > 11)
1041 return no_match;
1042
1043 if (colons > 7)
1044 return no_match;
1045
1046 str++;
1047 }
1048
1049 if (state < STATE_MASK)
1050 return partly_match;
1051
1052 mask = strtol (str, &endptr, 10);
1053 if (*endptr != '\0')
1054 return no_match;
1055
1056 if (mask < 0 || mask > 128)
1057 return no_match;
1058
1059/* I don't know why mask < 13 makes command match partly.
1060 Forgive me to make this comments. I Want to set static default route
1061 because of lack of function to originate default in ospf6d; sorry
1062 yasu
1063 if (mask < 13)
1064 return partly_match;
1065*/
1066
1067 return exact_match;
1068}
1069
paul22e0a9e2003-07-11 17:55:46 +00001070#endif /* HAVE_IPV6 */
1071
paul718e3742002-12-13 20:15:29 +00001072#define DECIMAL_STRLEN_MAX 10
1073
ajs274a4a42004-12-07 15:39:31 +00001074static int
hasso8c328f12004-10-05 21:01:23 +00001075cmd_range_match (const char *range, const char *str)
paul718e3742002-12-13 20:15:29 +00001076{
1077 char *p;
1078 char buf[DECIMAL_STRLEN_MAX + 1];
1079 char *endptr = NULL;
1080 unsigned long min, max, val;
1081
1082 if (str == NULL)
1083 return 1;
1084
1085 val = strtoul (str, &endptr, 10);
1086 if (*endptr != '\0')
1087 return 0;
1088
1089 range++;
1090 p = strchr (range, '-');
1091 if (p == NULL)
1092 return 0;
1093 if (p - range > DECIMAL_STRLEN_MAX)
1094 return 0;
1095 strncpy (buf, range, p - range);
1096 buf[p - range] = '\0';
1097 min = strtoul (buf, &endptr, 10);
1098 if (*endptr != '\0')
1099 return 0;
1100
1101 range = p + 1;
1102 p = strchr (range, '>');
1103 if (p == NULL)
1104 return 0;
1105 if (p - range > DECIMAL_STRLEN_MAX)
1106 return 0;
1107 strncpy (buf, range, p - range);
1108 buf[p - range] = '\0';
1109 max = strtoul (buf, &endptr, 10);
1110 if (*endptr != '\0')
1111 return 0;
1112
1113 if (val < min || val > max)
1114 return 0;
1115
1116 return 1;
1117}
1118
1119/* Make completion match and return match type flag. */
ajs274a4a42004-12-07 15:39:31 +00001120static enum match_type
hasso8c328f12004-10-05 21:01:23 +00001121cmd_filter_by_completion (char *command, vector v, unsigned int index)
paul718e3742002-12-13 20:15:29 +00001122{
hasso8c328f12004-10-05 21:01:23 +00001123 unsigned int i;
1124 const char *str;
paul718e3742002-12-13 20:15:29 +00001125 struct cmd_element *cmd_element;
1126 enum match_type match_type;
1127 vector descvec;
1128 struct desc *desc;
1129
1130 match_type = no_match;
1131
1132 /* If command and cmd_element string does not match set NULL to vector */
1133 for (i = 0; i < vector_max (v); i++)
1134 if ((cmd_element = vector_slot (v, i)) != NULL)
1135 {
1136 if (index >= vector_max (cmd_element->strvec))
1137 vector_slot (v, i) = NULL;
1138 else
1139 {
hasso8c328f12004-10-05 21:01:23 +00001140 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001141 int matched = 0;
1142
1143 descvec = vector_slot (cmd_element->strvec, index);
1144
1145 for (j = 0; j < vector_max (descvec); j++)
1146 {
1147 desc = vector_slot (descvec, j);
1148 str = desc->cmd;
1149
1150 if (CMD_VARARG (str))
1151 {
1152 if (match_type < vararg_match)
1153 match_type = vararg_match;
1154 matched++;
1155 }
1156 else if (CMD_RANGE (str))
1157 {
1158 if (cmd_range_match (str, command))
1159 {
1160 if (match_type < range_match)
1161 match_type = range_match;
1162
1163 matched++;
1164 }
1165 }
paul22e0a9e2003-07-11 17:55:46 +00001166#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001167 else if (CMD_IPV6 (str))
1168 {
1169 if (cmd_ipv6_match (command))
1170 {
1171 if (match_type < ipv6_match)
1172 match_type = ipv6_match;
1173
1174 matched++;
1175 }
1176 }
1177 else if (CMD_IPV6_PREFIX (str))
1178 {
1179 if (cmd_ipv6_prefix_match (command))
1180 {
1181 if (match_type < ipv6_prefix_match)
1182 match_type = ipv6_prefix_match;
1183
1184 matched++;
1185 }
1186 }
paul22e0a9e2003-07-11 17:55:46 +00001187#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001188 else if (CMD_IPV4 (str))
1189 {
1190 if (cmd_ipv4_match (command))
1191 {
1192 if (match_type < ipv4_match)
1193 match_type = ipv4_match;
1194
1195 matched++;
1196 }
1197 }
1198 else if (CMD_IPV4_PREFIX (str))
1199 {
1200 if (cmd_ipv4_prefix_match (command))
1201 {
1202 if (match_type < ipv4_prefix_match)
1203 match_type = ipv4_prefix_match;
1204 matched++;
1205 }
1206 }
1207 else
1208 /* Check is this point's argument optional ? */
1209 if (CMD_OPTION (str) || CMD_VARIABLE (str))
1210 {
1211 if (match_type < extend_match)
1212 match_type = extend_match;
1213 matched++;
1214 }
1215 else if (strncmp (command, str, strlen (command)) == 0)
1216 {
1217 if (strcmp (command, str) == 0)
1218 match_type = exact_match;
1219 else
1220 {
1221 if (match_type < partly_match)
1222 match_type = partly_match;
1223 }
1224 matched++;
1225 }
1226 }
1227 if (! matched)
1228 vector_slot (v, i) = NULL;
1229 }
1230 }
1231 return match_type;
1232}
1233
1234/* Filter vector by command character with index. */
ajs274a4a42004-12-07 15:39:31 +00001235static enum match_type
hasso8c328f12004-10-05 21:01:23 +00001236cmd_filter_by_string (char *command, vector v, unsigned int index)
paul718e3742002-12-13 20:15:29 +00001237{
hasso8c328f12004-10-05 21:01:23 +00001238 unsigned int i;
1239 const char *str;
paul718e3742002-12-13 20:15:29 +00001240 struct cmd_element *cmd_element;
1241 enum match_type match_type;
1242 vector descvec;
1243 struct desc *desc;
1244
1245 match_type = no_match;
1246
1247 /* If command and cmd_element string does not match set NULL to vector */
1248 for (i = 0; i < vector_max (v); i++)
1249 if ((cmd_element = vector_slot (v, i)) != NULL)
1250 {
1251 /* If given index is bigger than max string vector of command,
1252 set NULL*/
1253 if (index >= vector_max (cmd_element->strvec))
1254 vector_slot (v, i) = NULL;
1255 else
1256 {
hasso8c328f12004-10-05 21:01:23 +00001257 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001258 int matched = 0;
1259
1260 descvec = vector_slot (cmd_element->strvec, index);
1261
1262 for (j = 0; j < vector_max (descvec); j++)
1263 {
1264 desc = vector_slot (descvec, j);
1265 str = desc->cmd;
1266
1267 if (CMD_VARARG (str))
1268 {
1269 if (match_type < vararg_match)
1270 match_type = vararg_match;
1271 matched++;
1272 }
1273 else if (CMD_RANGE (str))
1274 {
1275 if (cmd_range_match (str, command))
1276 {
1277 if (match_type < range_match)
1278 match_type = range_match;
1279 matched++;
1280 }
1281 }
paul22e0a9e2003-07-11 17:55:46 +00001282#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001283 else if (CMD_IPV6 (str))
1284 {
1285 if (cmd_ipv6_match (command) == exact_match)
1286 {
1287 if (match_type < ipv6_match)
1288 match_type = ipv6_match;
1289 matched++;
1290 }
1291 }
1292 else if (CMD_IPV6_PREFIX (str))
1293 {
1294 if (cmd_ipv6_prefix_match (command) == exact_match)
1295 {
1296 if (match_type < ipv6_prefix_match)
1297 match_type = ipv6_prefix_match;
1298 matched++;
1299 }
1300 }
paul22e0a9e2003-07-11 17:55:46 +00001301#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001302 else if (CMD_IPV4 (str))
1303 {
1304 if (cmd_ipv4_match (command) == exact_match)
1305 {
1306 if (match_type < ipv4_match)
1307 match_type = ipv4_match;
1308 matched++;
1309 }
1310 }
1311 else if (CMD_IPV4_PREFIX (str))
1312 {
1313 if (cmd_ipv4_prefix_match (command) == exact_match)
1314 {
1315 if (match_type < ipv4_prefix_match)
1316 match_type = ipv4_prefix_match;
1317 matched++;
1318 }
1319 }
1320 else if (CMD_OPTION (str) || CMD_VARIABLE (str))
1321 {
1322 if (match_type < extend_match)
1323 match_type = extend_match;
1324 matched++;
1325 }
1326 else
1327 {
1328 if (strcmp (command, str) == 0)
1329 {
1330 match_type = exact_match;
1331 matched++;
1332 }
1333 }
1334 }
1335 if (! matched)
1336 vector_slot (v, i) = NULL;
1337 }
1338 }
1339 return match_type;
1340}
1341
1342/* Check ambiguous match */
ajs274a4a42004-12-07 15:39:31 +00001343static int
paul718e3742002-12-13 20:15:29 +00001344is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
1345{
hasso8c328f12004-10-05 21:01:23 +00001346 unsigned int i;
1347 unsigned int j;
1348 const char *str = NULL;
paul718e3742002-12-13 20:15:29 +00001349 struct cmd_element *cmd_element;
hasso8c328f12004-10-05 21:01:23 +00001350 const char *matched = NULL;
paul718e3742002-12-13 20:15:29 +00001351 vector descvec;
1352 struct desc *desc;
1353
1354 for (i = 0; i < vector_max (v); i++)
1355 if ((cmd_element = vector_slot (v, i)) != NULL)
1356 {
1357 int match = 0;
1358
1359 descvec = vector_slot (cmd_element->strvec, index);
1360
1361 for (j = 0; j < vector_max (descvec); j++)
1362 {
1363 enum match_type ret;
1364
1365 desc = vector_slot (descvec, j);
1366 str = desc->cmd;
1367
1368 switch (type)
1369 {
1370 case exact_match:
1371 if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
1372 && strcmp (command, str) == 0)
1373 match++;
1374 break;
1375 case partly_match:
1376 if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
1377 && strncmp (command, str, strlen (command)) == 0)
1378 {
1379 if (matched && strcmp (matched, str) != 0)
1380 return 1; /* There is ambiguous match. */
1381 else
1382 matched = str;
1383 match++;
1384 }
1385 break;
1386 case range_match:
1387 if (cmd_range_match (str, command))
1388 {
1389 if (matched && strcmp (matched, str) != 0)
1390 return 1;
1391 else
1392 matched = str;
1393 match++;
1394 }
1395 break;
paul22e0a9e2003-07-11 17:55:46 +00001396#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001397 case ipv6_match:
1398 if (CMD_IPV6 (str))
1399 match++;
1400 break;
1401 case ipv6_prefix_match:
1402 if ((ret = cmd_ipv6_prefix_match (command)) != no_match)
1403 {
1404 if (ret == partly_match)
1405 return 2; /* There is incomplete match. */
1406
1407 match++;
1408 }
1409 break;
paul22e0a9e2003-07-11 17:55:46 +00001410#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001411 case ipv4_match:
1412 if (CMD_IPV4 (str))
1413 match++;
1414 break;
1415 case ipv4_prefix_match:
1416 if ((ret = cmd_ipv4_prefix_match (command)) != no_match)
1417 {
1418 if (ret == partly_match)
1419 return 2; /* There is incomplete match. */
1420
1421 match++;
1422 }
1423 break;
1424 case extend_match:
1425 if (CMD_OPTION (str) || CMD_VARIABLE (str))
1426 match++;
1427 break;
1428 case no_match:
1429 default:
1430 break;
1431 }
1432 }
1433 if (! match)
1434 vector_slot (v, i) = NULL;
1435 }
1436 return 0;
1437}
1438
1439/* If src matches dst return dst string, otherwise return NULL */
ajs274a4a42004-12-07 15:39:31 +00001440static const char *
hasso8c328f12004-10-05 21:01:23 +00001441cmd_entry_function (const char *src, const char *dst)
paul718e3742002-12-13 20:15:29 +00001442{
1443 /* Skip variable arguments. */
1444 if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) ||
1445 CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst))
1446 return NULL;
1447
1448 /* In case of 'command \t', given src is NULL string. */
1449 if (src == NULL)
1450 return dst;
1451
1452 /* Matched with input string. */
1453 if (strncmp (src, dst, strlen (src)) == 0)
1454 return dst;
1455
1456 return NULL;
1457}
1458
1459/* If src matches dst return dst string, otherwise return NULL */
1460/* This version will return the dst string always if it is
1461 CMD_VARIABLE for '?' key processing */
ajs274a4a42004-12-07 15:39:31 +00001462static const char *
hasso8c328f12004-10-05 21:01:23 +00001463cmd_entry_function_desc (const char *src, const char *dst)
paul718e3742002-12-13 20:15:29 +00001464{
1465 if (CMD_VARARG (dst))
1466 return dst;
1467
1468 if (CMD_RANGE (dst))
1469 {
1470 if (cmd_range_match (dst, src))
1471 return dst;
1472 else
1473 return NULL;
1474 }
1475
paul22e0a9e2003-07-11 17:55:46 +00001476#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001477 if (CMD_IPV6 (dst))
1478 {
1479 if (cmd_ipv6_match (src))
1480 return dst;
1481 else
1482 return NULL;
1483 }
1484
1485 if (CMD_IPV6_PREFIX (dst))
1486 {
1487 if (cmd_ipv6_prefix_match (src))
1488 return dst;
1489 else
1490 return NULL;
1491 }
paul22e0a9e2003-07-11 17:55:46 +00001492#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001493
1494 if (CMD_IPV4 (dst))
1495 {
1496 if (cmd_ipv4_match (src))
1497 return dst;
1498 else
1499 return NULL;
1500 }
1501
1502 if (CMD_IPV4_PREFIX (dst))
1503 {
1504 if (cmd_ipv4_prefix_match (src))
1505 return dst;
1506 else
1507 return NULL;
1508 }
1509
1510 /* Optional or variable commands always match on '?' */
1511 if (CMD_OPTION (dst) || CMD_VARIABLE (dst))
1512 return dst;
1513
1514 /* In case of 'command \t', given src is NULL string. */
1515 if (src == NULL)
1516 return dst;
1517
1518 if (strncmp (src, dst, strlen (src)) == 0)
1519 return dst;
1520 else
1521 return NULL;
1522}
1523
1524/* Check same string element existence. If it isn't there return
1525 1. */
ajs274a4a42004-12-07 15:39:31 +00001526static int
hasso8c328f12004-10-05 21:01:23 +00001527cmd_unique_string (vector v, const char *str)
paul718e3742002-12-13 20:15:29 +00001528{
hasso8c328f12004-10-05 21:01:23 +00001529 unsigned int i;
paul718e3742002-12-13 20:15:29 +00001530 char *match;
1531
1532 for (i = 0; i < vector_max (v); i++)
1533 if ((match = vector_slot (v, i)) != NULL)
1534 if (strcmp (match, str) == 0)
1535 return 0;
1536 return 1;
1537}
1538
1539/* Compare string to description vector. If there is same string
1540 return 1 else return 0. */
ajs274a4a42004-12-07 15:39:31 +00001541static int
hasso8c328f12004-10-05 21:01:23 +00001542desc_unique_string (vector v, const char *str)
paul718e3742002-12-13 20:15:29 +00001543{
hasso8c328f12004-10-05 21:01:23 +00001544 unsigned int i;
paul718e3742002-12-13 20:15:29 +00001545 struct desc *desc;
1546
1547 for (i = 0; i < vector_max (v); i++)
1548 if ((desc = vector_slot (v, i)) != NULL)
1549 if (strcmp (desc->cmd, str) == 0)
1550 return 1;
1551 return 0;
1552}
1553
ajs274a4a42004-12-07 15:39:31 +00001554static int
paulb92938a2002-12-13 21:20:42 +00001555cmd_try_do_shortcut (enum node_type node, char* first_word) {
1556 if ( first_word != NULL &&
1557 node != AUTH_NODE &&
1558 node != VIEW_NODE &&
1559 node != AUTH_ENABLE_NODE &&
1560 node != ENABLE_NODE &&
1561 0 == strcmp( "do", first_word ) )
1562 return 1;
1563 return 0;
1564}
1565
paul718e3742002-12-13 20:15:29 +00001566/* '?' describe command support. */
ajs274a4a42004-12-07 15:39:31 +00001567static vector
paulb92938a2002-12-13 21:20:42 +00001568cmd_describe_command_real (vector vline, struct vty *vty, int *status)
paul718e3742002-12-13 20:15:29 +00001569{
hassocba8a602005-01-02 18:51:01 +00001570 int i;
paul718e3742002-12-13 20:15:29 +00001571 vector cmd_vector;
1572#define INIT_MATCHVEC_SIZE 10
1573 vector matchvec;
1574 struct cmd_element *cmd_element;
hassocba8a602005-01-02 18:51:01 +00001575 int index;
paul54aba542003-08-21 20:28:24 +00001576 int ret;
1577 enum match_type match;
1578 char *command;
paul718e3742002-12-13 20:15:29 +00001579 static struct desc desc_cr = { "<cr>", "" };
1580
1581 /* Set index. */
1582 index = vector_max (vline) - 1;
1583
1584 /* Make copy vector of current node's command vector. */
1585 cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1586
1587 /* Prepare match vector */
1588 matchvec = vector_init (INIT_MATCHVEC_SIZE);
1589
1590 /* Filter commands. */
paul54aba542003-08-21 20:28:24 +00001591 /* Only words precedes current word will be checked in this loop. */
paul718e3742002-12-13 20:15:29 +00001592 for (i = 0; i < index; i++)
1593 {
paul718e3742002-12-13 20:15:29 +00001594 command = vector_slot (vline, i);
paul718e3742002-12-13 20:15:29 +00001595 match = cmd_filter_by_completion (command, cmd_vector, i);
1596
1597 if (match == vararg_match)
1598 {
1599 struct cmd_element *cmd_element;
1600 vector descvec;
hasso8c328f12004-10-05 21:01:23 +00001601 unsigned int j, k;
paul718e3742002-12-13 20:15:29 +00001602
1603 for (j = 0; j < vector_max (cmd_vector); j++)
1604 if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
1605 {
1606 descvec = vector_slot (cmd_element->strvec,
1607 vector_max (cmd_element->strvec) - 1);
1608 for (k = 0; k < vector_max (descvec); k++)
1609 {
1610 struct desc *desc = vector_slot (descvec, k);
1611 vector_set (matchvec, desc);
1612 }
1613 }
1614
1615 vector_set (matchvec, &desc_cr);
paul718e3742002-12-13 20:15:29 +00001616 vector_free (cmd_vector);
1617
1618 return matchvec;
1619 }
1620
1621 if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
1622 {
1623 vector_free (cmd_vector);
1624 *status = CMD_ERR_AMBIGUOUS;
1625 return NULL;
1626 }
1627 else if (ret == 2)
1628 {
1629 vector_free (cmd_vector);
1630 *status = CMD_ERR_NO_MATCH;
1631 return NULL;
1632 }
1633 }
1634
1635 /* Prepare match vector */
1636 /* matchvec = vector_init (INIT_MATCHVEC_SIZE); */
1637
paul54aba542003-08-21 20:28:24 +00001638 /* Make sure that cmd_vector is filtered based on current word */
1639 command = vector_slot (vline, index);
1640 if (command)
1641 match = cmd_filter_by_completion (command, cmd_vector, index);
1642
paul718e3742002-12-13 20:15:29 +00001643 /* Make description vector. */
1644 for (i = 0; i < vector_max (cmd_vector); i++)
1645 if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
1646 {
hasso8c328f12004-10-05 21:01:23 +00001647 const char *string = NULL;
paul718e3742002-12-13 20:15:29 +00001648 vector strvec = cmd_element->strvec;
1649
paul54aba542003-08-21 20:28:24 +00001650 /* if command is NULL, index may be equal to vector_max */
1651 if (command && index >= vector_max (strvec))
paul718e3742002-12-13 20:15:29 +00001652 vector_slot (cmd_vector, i) = NULL;
1653 else
1654 {
paul54aba542003-08-21 20:28:24 +00001655 /* Check if command is completed. */
1656 if (command == NULL && index == vector_max (strvec))
paul718e3742002-12-13 20:15:29 +00001657 {
1658 string = "<cr>";
1659 if (! desc_unique_string (matchvec, string))
1660 vector_set (matchvec, &desc_cr);
1661 }
1662 else
1663 {
hasso8c328f12004-10-05 21:01:23 +00001664 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001665 vector descvec = vector_slot (strvec, index);
1666 struct desc *desc;
1667
1668 for (j = 0; j < vector_max (descvec); j++)
1669 {
1670 desc = vector_slot (descvec, j);
paul54aba542003-08-21 20:28:24 +00001671 string = cmd_entry_function_desc (command, desc->cmd);
paul718e3742002-12-13 20:15:29 +00001672 if (string)
1673 {
1674 /* Uniqueness check */
1675 if (! desc_unique_string (matchvec, string))
1676 vector_set (matchvec, desc);
1677 }
1678 }
1679 }
1680 }
1681 }
1682 vector_free (cmd_vector);
1683
1684 if (vector_slot (matchvec, 0) == NULL)
1685 {
1686 vector_free (matchvec);
1687 *status= CMD_ERR_NO_MATCH;
1688 }
1689 else
1690 *status = CMD_SUCCESS;
1691
1692 return matchvec;
1693}
1694
paulb92938a2002-12-13 21:20:42 +00001695vector
1696cmd_describe_command (vector vline, struct vty *vty, int *status)
1697{
1698 vector ret;
1699
1700 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
1701 {
1702 enum node_type onode;
1703 vector shifted_vline;
hasso8c328f12004-10-05 21:01:23 +00001704 unsigned int index;
paulb92938a2002-12-13 21:20:42 +00001705
1706 onode = vty->node;
1707 vty->node = ENABLE_NODE;
1708 /* We can try it on enable node, cos' the vty is authenticated */
1709
1710 shifted_vline = vector_init (vector_count(vline));
1711 /* use memcpy? */
1712 for (index = 1; index < vector_max (vline); index++)
1713 {
1714 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
1715 }
1716
1717 ret = cmd_describe_command_real (shifted_vline, vty, status);
1718
1719 vector_free(shifted_vline);
1720 vty->node = onode;
1721 return ret;
1722 }
1723
1724
1725 return cmd_describe_command_real (vline, vty, status);
1726}
1727
1728
paul718e3742002-12-13 20:15:29 +00001729/* Check LCD of matched command. */
ajs274a4a42004-12-07 15:39:31 +00001730static int
paul718e3742002-12-13 20:15:29 +00001731cmd_lcd (char **matched)
1732{
1733 int i;
1734 int j;
1735 int lcd = -1;
1736 char *s1, *s2;
1737 char c1, c2;
1738
1739 if (matched[0] == NULL || matched[1] == NULL)
1740 return 0;
1741
1742 for (i = 1; matched[i] != NULL; i++)
1743 {
1744 s1 = matched[i - 1];
1745 s2 = matched[i];
1746
1747 for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
1748 if (c1 != c2)
1749 break;
1750
1751 if (lcd < 0)
1752 lcd = j;
1753 else
1754 {
1755 if (lcd > j)
1756 lcd = j;
1757 }
1758 }
1759 return lcd;
1760}
1761
1762/* Command line completion support. */
ajs274a4a42004-12-07 15:39:31 +00001763static char **
paulb92938a2002-12-13 21:20:42 +00001764cmd_complete_command_real (vector vline, struct vty *vty, int *status)
paul718e3742002-12-13 20:15:29 +00001765{
hassocba8a602005-01-02 18:51:01 +00001766 int i;
paul718e3742002-12-13 20:15:29 +00001767 vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1768#define INIT_MATCHVEC_SIZE 10
1769 vector matchvec;
1770 struct cmd_element *cmd_element;
hassocba8a602005-01-02 18:51:01 +00001771 int index = vector_max (vline) - 1;
paul718e3742002-12-13 20:15:29 +00001772 char **match_str;
1773 struct desc *desc;
1774 vector descvec;
1775 char *command;
1776 int lcd;
1777
1778 /* First, filter by preceeding command string */
1779 for (i = 0; i < index; i++)
1780 {
1781 enum match_type match;
1782 int ret;
1783
1784 command = vector_slot (vline, i);
1785
1786 /* First try completion match, if there is exactly match return 1 */
1787 match = cmd_filter_by_completion (command, cmd_vector, i);
1788
1789 /* If there is exact match then filter ambiguous match else check
1790 ambiguousness. */
1791 if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
1792 {
1793 vector_free (cmd_vector);
1794 *status = CMD_ERR_AMBIGUOUS;
1795 return NULL;
1796 }
1797 /*
1798 else if (ret == 2)
1799 {
1800 vector_free (cmd_vector);
1801 *status = CMD_ERR_NO_MATCH;
1802 return NULL;
1803 }
1804 */
1805 }
1806
1807 /* Prepare match vector. */
1808 matchvec = vector_init (INIT_MATCHVEC_SIZE);
1809
1810 /* Now we got into completion */
1811 for (i = 0; i < vector_max (cmd_vector); i++)
1812 if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
1813 {
hasso8c328f12004-10-05 21:01:23 +00001814 const char *string;
paul718e3742002-12-13 20:15:29 +00001815 vector strvec = cmd_element->strvec;
1816
1817 /* Check field length */
1818 if (index >= vector_max (strvec))
1819 vector_slot (cmd_vector, i) = NULL;
1820 else
1821 {
hasso8c328f12004-10-05 21:01:23 +00001822 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001823
1824 descvec = vector_slot (strvec, index);
1825 for (j = 0; j < vector_max (descvec); j++)
1826 {
1827 desc = vector_slot (descvec, j);
1828
1829 if ((string = cmd_entry_function (vector_slot (vline, index),
1830 desc->cmd)))
1831 if (cmd_unique_string (matchvec, string))
1832 vector_set (matchvec, XSTRDUP (MTYPE_TMP, string));
1833 }
1834 }
1835 }
1836
1837 /* We don't need cmd_vector any more. */
1838 vector_free (cmd_vector);
1839
1840 /* No matched command */
1841 if (vector_slot (matchvec, 0) == NULL)
1842 {
1843 vector_free (matchvec);
1844
1845 /* In case of 'command \t' pattern. Do you need '?' command at
1846 the end of the line. */
1847 if (vector_slot (vline, index) == '\0')
1848 *status = CMD_ERR_NOTHING_TODO;
1849 else
1850 *status = CMD_ERR_NO_MATCH;
1851 return NULL;
1852 }
1853
1854 /* Only one matched */
1855 if (vector_slot (matchvec, 1) == NULL)
1856 {
1857 match_str = (char **) matchvec->index;
1858 vector_only_wrapper_free (matchvec);
1859 *status = CMD_COMPLETE_FULL_MATCH;
1860 return match_str;
1861 }
1862 /* Make it sure last element is NULL. */
1863 vector_set (matchvec, NULL);
1864
1865 /* Check LCD of matched strings. */
1866 if (vector_slot (vline, index) != NULL)
1867 {
1868 lcd = cmd_lcd ((char **) matchvec->index);
1869
1870 if (lcd)
1871 {
1872 int len = strlen (vector_slot (vline, index));
1873
1874 if (len < lcd)
1875 {
1876 char *lcdstr;
1877
1878 lcdstr = XMALLOC (MTYPE_TMP, lcd + 1);
1879 memcpy (lcdstr, matchvec->index[0], lcd);
1880 lcdstr[lcd] = '\0';
1881
1882 /* match_str = (char **) &lcdstr; */
1883
1884 /* Free matchvec. */
1885 for (i = 0; i < vector_max (matchvec); i++)
1886 {
1887 if (vector_slot (matchvec, i))
1888 XFREE (MTYPE_TMP, vector_slot (matchvec, i));
1889 }
1890 vector_free (matchvec);
1891
1892 /* Make new matchvec. */
1893 matchvec = vector_init (INIT_MATCHVEC_SIZE);
1894 vector_set (matchvec, lcdstr);
1895 match_str = (char **) matchvec->index;
1896 vector_only_wrapper_free (matchvec);
1897
1898 *status = CMD_COMPLETE_MATCH;
1899 return match_str;
1900 }
1901 }
1902 }
1903
1904 match_str = (char **) matchvec->index;
1905 vector_only_wrapper_free (matchvec);
1906 *status = CMD_COMPLETE_LIST_MATCH;
1907 return match_str;
1908}
1909
paulb92938a2002-12-13 21:20:42 +00001910char **
paul9ab68122003-01-18 01:16:20 +00001911cmd_complete_command (vector vline, struct vty *vty, int *status)
paulb92938a2002-12-13 21:20:42 +00001912{
1913 char **ret;
1914
1915 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
1916 {
1917 enum node_type onode;
1918 vector shifted_vline;
hasso8c328f12004-10-05 21:01:23 +00001919 unsigned int index;
paulb92938a2002-12-13 21:20:42 +00001920
1921 onode = vty->node;
1922 vty->node = ENABLE_NODE;
1923 /* We can try it on enable node, cos' the vty is authenticated */
1924
1925 shifted_vline = vector_init (vector_count(vline));
1926 /* use memcpy? */
1927 for (index = 1; index < vector_max (vline); index++)
1928 {
1929 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
1930 }
1931
1932 ret = cmd_complete_command_real (shifted_vline, vty, status);
1933
1934 vector_free(shifted_vline);
1935 vty->node = onode;
1936 return ret;
1937 }
1938
1939
1940 return cmd_complete_command_real (vline, vty, status);
1941}
1942
1943/* return parent node */
1944/* MUST eventually converge on CONFIG_NODE */
ajs274a4a42004-12-07 15:39:31 +00001945static enum node_type
1946node_parent ( enum node_type node )
paulb92938a2002-12-13 21:20:42 +00001947{
1948 enum node_type ret;
1949
paul9ab68122003-01-18 01:16:20 +00001950 assert (node > CONFIG_NODE);
1951
1952 switch (node)
1953 {
1954 case BGP_VPNV4_NODE:
1955 case BGP_IPV4_NODE:
1956 case BGP_IPV4M_NODE:
1957 case BGP_IPV6_NODE:
1958 ret = BGP_NODE;
1959 break;
1960 case KEYCHAIN_KEY_NODE:
1961 ret = KEYCHAIN_NODE;
1962 break;
1963 default:
1964 ret = CONFIG_NODE;
paulb92938a2002-12-13 21:20:42 +00001965 }
1966
1967 return ret;
1968}
1969
paul718e3742002-12-13 20:15:29 +00001970/* Execute command by argument vline vector. */
ajs274a4a42004-12-07 15:39:31 +00001971static int
paulb92938a2002-12-13 21:20:42 +00001972cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd)
paul718e3742002-12-13 20:15:29 +00001973{
hasso8c328f12004-10-05 21:01:23 +00001974 unsigned int i;
1975 unsigned int index;
paul718e3742002-12-13 20:15:29 +00001976 vector cmd_vector;
1977 struct cmd_element *cmd_element;
1978 struct cmd_element *matched_element;
1979 unsigned int matched_count, incomplete_count;
1980 int argc;
paul9035efa2004-10-10 11:56:56 +00001981 const char *argv[CMD_ARGC_MAX];
paul718e3742002-12-13 20:15:29 +00001982 enum match_type match = 0;
1983 int varflag;
1984 char *command;
1985
1986 /* Make copy of command elements. */
1987 cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1988
1989 for (index = 0; index < vector_max (vline); index++)
1990 {
1991 int ret;
1992
1993 command = vector_slot (vline, index);
1994
1995 match = cmd_filter_by_completion (command, cmd_vector, index);
1996
1997 if (match == vararg_match)
1998 break;
1999
2000 ret = is_cmd_ambiguous (command, cmd_vector, index, match);
2001
2002 if (ret == 1)
2003 {
2004 vector_free (cmd_vector);
2005 return CMD_ERR_AMBIGUOUS;
2006 }
2007 else if (ret == 2)
2008 {
2009 vector_free (cmd_vector);
2010 return CMD_ERR_NO_MATCH;
2011 }
2012 }
2013
2014 /* Check matched count. */
2015 matched_element = NULL;
2016 matched_count = 0;
2017 incomplete_count = 0;
2018
2019 for (i = 0; i < vector_max (cmd_vector); i++)
2020 if (vector_slot (cmd_vector,i) != NULL)
2021 {
2022 cmd_element = vector_slot (cmd_vector,i);
2023
2024 if (match == vararg_match || index >= cmd_element->cmdsize)
2025 {
2026 matched_element = cmd_element;
2027#if 0
2028 printf ("DEBUG: %s\n", cmd_element->string);
2029#endif
2030 matched_count++;
2031 }
2032 else
2033 {
2034 incomplete_count++;
2035 }
2036 }
2037
2038 /* Finish of using cmd_vector. */
2039 vector_free (cmd_vector);
2040
2041 /* To execute command, matched_count must be 1.*/
2042 if (matched_count == 0)
2043 {
2044 if (incomplete_count)
2045 return CMD_ERR_INCOMPLETE;
2046 else
2047 return CMD_ERR_NO_MATCH;
2048 }
2049
2050 if (matched_count > 1)
2051 return CMD_ERR_AMBIGUOUS;
2052
2053 /* Argument treatment */
2054 varflag = 0;
2055 argc = 0;
2056
2057 for (i = 0; i < vector_max (vline); i++)
2058 {
2059 if (varflag)
2060 argv[argc++] = vector_slot (vline, i);
2061 else
2062 {
2063 vector descvec = vector_slot (matched_element->strvec, i);
2064
2065 if (vector_max (descvec) == 1)
2066 {
2067 struct desc *desc = vector_slot (descvec, 0);
paul718e3742002-12-13 20:15:29 +00002068
hasso8c328f12004-10-05 21:01:23 +00002069 if (CMD_VARARG (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002070 varflag = 1;
2071
hasso8c328f12004-10-05 21:01:23 +00002072 if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002073 argv[argc++] = vector_slot (vline, i);
2074 }
2075 else
2076 argv[argc++] = vector_slot (vline, i);
2077 }
2078
2079 if (argc >= CMD_ARGC_MAX)
2080 return CMD_ERR_EXEED_ARGC_MAX;
2081 }
2082
2083 /* For vtysh execution. */
2084 if (cmd)
2085 *cmd = matched_element;
2086
2087 if (matched_element->daemon)
2088 return CMD_SUCCESS_DAEMON;
2089
2090 /* Execute matched command. */
2091 return (*matched_element->func) (matched_element, vty, argc, argv);
2092}
2093
paulb92938a2002-12-13 21:20:42 +00002094
2095int
2096cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) {
paul9ab68122003-01-18 01:16:20 +00002097 int ret, saved_ret, tried = 0;
2098 enum node_type onode, try_node;
2099
2100 onode = try_node = vty->node;
paulb92938a2002-12-13 21:20:42 +00002101
2102 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
2103 {
2104 vector shifted_vline;
hasso8c328f12004-10-05 21:01:23 +00002105 unsigned int index;
paulb92938a2002-12-13 21:20:42 +00002106
2107 vty->node = ENABLE_NODE;
2108 /* We can try it on enable node, cos' the vty is authenticated */
2109
2110 shifted_vline = vector_init (vector_count(vline));
2111 /* use memcpy? */
2112 for (index = 1; index < vector_max (vline); index++)
2113 {
2114 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
2115 }
2116
2117 ret = cmd_execute_command_real (shifted_vline, vty, cmd);
2118
2119 vector_free(shifted_vline);
2120 vty->node = onode;
2121 return ret;
2122 }
2123
2124
paul9ab68122003-01-18 01:16:20 +00002125 saved_ret = ret = cmd_execute_command_real (vline, vty, cmd);
paulb92938a2002-12-13 21:20:42 +00002126
2127 /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
paul9ab68122003-01-18 01:16:20 +00002128 while ( ret != CMD_SUCCESS && ret != CMD_WARNING
paulb92938a2002-12-13 21:20:42 +00002129 && vty->node > CONFIG_NODE )
2130 {
paul9ab68122003-01-18 01:16:20 +00002131 try_node = node_parent(try_node);
2132 vty->node = try_node;
paulb92938a2002-12-13 21:20:42 +00002133 ret = cmd_execute_command_real (vline, vty, cmd);
paul9ab68122003-01-18 01:16:20 +00002134 tried = 1;
2135 if (ret == CMD_SUCCESS || ret == CMD_WARNING)
paulb92938a2002-12-13 21:20:42 +00002136 {
paul9ab68122003-01-18 01:16:20 +00002137 /* succesfull command, leave the node as is */
paulb92938a2002-12-13 21:20:42 +00002138 return ret;
2139 }
paulb92938a2002-12-13 21:20:42 +00002140 }
paul9ab68122003-01-18 01:16:20 +00002141 /* no command succeeded, reset the vty to the original node and
2142 return the error for this node */
2143 if ( tried )
2144 vty->node = onode;
2145 return saved_ret;
pauleda031f2003-01-18 00:39:19 +00002146}
2147
paul718e3742002-12-13 20:15:29 +00002148/* Execute command by argument readline. */
2149int
2150cmd_execute_command_strict (vector vline, struct vty *vty,
2151 struct cmd_element **cmd)
2152{
hasso8c328f12004-10-05 21:01:23 +00002153 unsigned int i;
2154 unsigned int index;
paul718e3742002-12-13 20:15:29 +00002155 vector cmd_vector;
2156 struct cmd_element *cmd_element;
2157 struct cmd_element *matched_element;
2158 unsigned int matched_count, incomplete_count;
2159 int argc;
paul9035efa2004-10-10 11:56:56 +00002160 const char *argv[CMD_ARGC_MAX];
paul718e3742002-12-13 20:15:29 +00002161 int varflag;
2162 enum match_type match = 0;
2163 char *command;
2164
2165 /* Make copy of command element */
2166 cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
2167
2168 for (index = 0; index < vector_max (vline); index++)
2169 {
2170 int ret;
2171
2172 command = vector_slot (vline, index);
2173
2174 match = cmd_filter_by_string (vector_slot (vline, index),
2175 cmd_vector, index);
2176
2177 /* If command meets '.VARARG' then finish matching. */
2178 if (match == vararg_match)
2179 break;
2180
2181 ret = is_cmd_ambiguous (command, cmd_vector, index, match);
2182 if (ret == 1)
2183 {
2184 vector_free (cmd_vector);
2185 return CMD_ERR_AMBIGUOUS;
2186 }
2187 if (ret == 2)
2188 {
2189 vector_free (cmd_vector);
2190 return CMD_ERR_NO_MATCH;
2191 }
2192 }
2193
2194 /* Check matched count. */
2195 matched_element = NULL;
2196 matched_count = 0;
2197 incomplete_count = 0;
2198 for (i = 0; i < vector_max (cmd_vector); i++)
2199 if (vector_slot (cmd_vector,i) != NULL)
2200 {
2201 cmd_element = vector_slot (cmd_vector,i);
2202
2203 if (match == vararg_match || index >= cmd_element->cmdsize)
2204 {
2205 matched_element = cmd_element;
2206 matched_count++;
2207 }
2208 else
2209 incomplete_count++;
2210 }
2211
2212 /* Finish of using cmd_vector. */
2213 vector_free (cmd_vector);
2214
2215 /* To execute command, matched_count must be 1.*/
2216 if (matched_count == 0)
2217 {
2218 if (incomplete_count)
2219 return CMD_ERR_INCOMPLETE;
2220 else
2221 return CMD_ERR_NO_MATCH;
2222 }
2223
2224 if (matched_count > 1)
2225 return CMD_ERR_AMBIGUOUS;
2226
2227 /* Argument treatment */
2228 varflag = 0;
2229 argc = 0;
2230
2231 for (i = 0; i < vector_max (vline); i++)
2232 {
2233 if (varflag)
2234 argv[argc++] = vector_slot (vline, i);
2235 else
2236 {
2237 vector descvec = vector_slot (matched_element->strvec, i);
2238
2239 if (vector_max (descvec) == 1)
2240 {
2241 struct desc *desc = vector_slot (descvec, 0);
paul718e3742002-12-13 20:15:29 +00002242
hasso8c328f12004-10-05 21:01:23 +00002243 if (CMD_VARARG (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002244 varflag = 1;
2245
hasso8c328f12004-10-05 21:01:23 +00002246 if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002247 argv[argc++] = vector_slot (vline, i);
2248 }
2249 else
2250 argv[argc++] = vector_slot (vline, i);
2251 }
2252
2253 if (argc >= CMD_ARGC_MAX)
2254 return CMD_ERR_EXEED_ARGC_MAX;
2255 }
2256
2257 /* For vtysh execution. */
2258 if (cmd)
2259 *cmd = matched_element;
2260
2261 if (matched_element->daemon)
2262 return CMD_SUCCESS_DAEMON;
2263
2264 /* Now execute matched command */
2265 return (*matched_element->func) (matched_element, vty, argc, argv);
2266}
2267
2268/* Configration make from file. */
2269int
2270config_from_file (struct vty *vty, FILE *fp)
2271{
2272 int ret;
2273 vector vline;
2274
2275 while (fgets (vty->buf, VTY_BUFSIZ, fp))
2276 {
2277 vline = cmd_make_strvec (vty->buf);
2278
2279 /* In case of comment line */
2280 if (vline == NULL)
2281 continue;
2282 /* Execute configuration command : this is strict match */
2283 ret = cmd_execute_command_strict (vline, vty, NULL);
2284
2285 /* Try again with setting node to CONFIG_NODE */
paulb92938a2002-12-13 21:20:42 +00002286 while (ret != CMD_SUCCESS && ret != CMD_WARNING
hassoddd85ed2004-10-13 08:18:07 +00002287 && ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE)
2288 {
paulb92938a2002-12-13 21:20:42 +00002289 vty->node = node_parent(vty->node);
hassoddd85ed2004-10-13 08:18:07 +00002290 ret = cmd_execute_command_strict (vline, vty, NULL);
2291 }
paul9ab68122003-01-18 01:16:20 +00002292
paul718e3742002-12-13 20:15:29 +00002293 cmd_free_strvec (vline);
2294
hassoddd85ed2004-10-13 08:18:07 +00002295 if (ret != CMD_SUCCESS && ret != CMD_WARNING
2296 && ret != CMD_ERR_NOTHING_TODO)
paul718e3742002-12-13 20:15:29 +00002297 return ret;
2298 }
2299 return CMD_SUCCESS;
2300}
2301
2302/* Configration from terminal */
2303DEFUN (config_terminal,
2304 config_terminal_cmd,
2305 "configure terminal",
2306 "Configuration from vty interface\n"
2307 "Configuration terminal\n")
2308{
2309 if (vty_config_lock (vty))
2310 vty->node = CONFIG_NODE;
2311 else
2312 {
2313 vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
2314 return CMD_WARNING;
2315 }
2316 return CMD_SUCCESS;
2317}
2318
2319/* Enable command */
2320DEFUN (enable,
2321 config_enable_cmd,
2322 "enable",
2323 "Turn on privileged mode command\n")
2324{
2325 /* If enable password is NULL, change to ENABLE_NODE */
2326 if ((host.enable == NULL && host.enable_encrypt == NULL) ||
2327 vty->type == VTY_SHELL_SERV)
2328 vty->node = ENABLE_NODE;
2329 else
2330 vty->node = AUTH_ENABLE_NODE;
2331
2332 return CMD_SUCCESS;
2333}
2334
2335/* Disable command */
2336DEFUN (disable,
2337 config_disable_cmd,
2338 "disable",
2339 "Turn off privileged mode command\n")
2340{
2341 if (vty->node == ENABLE_NODE)
2342 vty->node = VIEW_NODE;
2343 return CMD_SUCCESS;
2344}
2345
2346/* Down vty node level. */
2347DEFUN (config_exit,
2348 config_exit_cmd,
2349 "exit",
2350 "Exit current mode and down to previous mode\n")
2351{
2352 switch (vty->node)
2353 {
2354 case VIEW_NODE:
2355 case ENABLE_NODE:
2356 if (vty_shell (vty))
2357 exit (0);
2358 else
2359 vty->status = VTY_CLOSE;
2360 break;
2361 case CONFIG_NODE:
2362 vty->node = ENABLE_NODE;
2363 vty_config_unlock (vty);
2364 break;
2365 case INTERFACE_NODE:
2366 case ZEBRA_NODE:
2367 case BGP_NODE:
2368 case RIP_NODE:
2369 case RIPNG_NODE:
2370 case OSPF_NODE:
2371 case OSPF6_NODE:
jardin9e867fe2003-12-23 08:56:18 +00002372 case ISIS_NODE:
paul718e3742002-12-13 20:15:29 +00002373 case KEYCHAIN_NODE:
2374 case MASC_NODE:
2375 case RMAP_NODE:
2376 case VTY_NODE:
2377 vty->node = CONFIG_NODE;
2378 break;
2379 case BGP_VPNV4_NODE:
2380 case BGP_IPV4_NODE:
2381 case BGP_IPV4M_NODE:
2382 case BGP_IPV6_NODE:
2383 vty->node = BGP_NODE;
2384 break;
2385 case KEYCHAIN_KEY_NODE:
2386 vty->node = KEYCHAIN_NODE;
2387 break;
2388 default:
2389 break;
2390 }
2391 return CMD_SUCCESS;
2392}
2393
2394/* quit is alias of exit. */
2395ALIAS (config_exit,
2396 config_quit_cmd,
2397 "quit",
2398 "Exit current mode and down to previous mode\n")
2399
2400/* End of configuration. */
2401DEFUN (config_end,
2402 config_end_cmd,
2403 "end",
2404 "End current mode and change to enable mode.")
2405{
2406 switch (vty->node)
2407 {
2408 case VIEW_NODE:
2409 case ENABLE_NODE:
2410 /* Nothing to do. */
2411 break;
2412 case CONFIG_NODE:
2413 case INTERFACE_NODE:
2414 case ZEBRA_NODE:
2415 case RIP_NODE:
2416 case RIPNG_NODE:
2417 case BGP_NODE:
2418 case BGP_VPNV4_NODE:
2419 case BGP_IPV4_NODE:
2420 case BGP_IPV4M_NODE:
2421 case BGP_IPV6_NODE:
2422 case RMAP_NODE:
2423 case OSPF_NODE:
2424 case OSPF6_NODE:
jardin9e867fe2003-12-23 08:56:18 +00002425 case ISIS_NODE:
paul718e3742002-12-13 20:15:29 +00002426 case KEYCHAIN_NODE:
2427 case KEYCHAIN_KEY_NODE:
2428 case MASC_NODE:
2429 case VTY_NODE:
2430 vty_config_unlock (vty);
2431 vty->node = ENABLE_NODE;
2432 break;
2433 default:
2434 break;
2435 }
2436 return CMD_SUCCESS;
2437}
2438
2439/* Show version. */
2440DEFUN (show_version,
2441 show_version_cmd,
2442 "show version",
2443 SHOW_STR
2444 "Displays zebra version\n")
2445{
hasso6590f2c2004-10-19 20:40:08 +00002446 vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name, VTY_NEWLINE);
2447 vty_out (vty, "%s%s", QUAGGA_COPYRIGHT, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002448
2449 return CMD_SUCCESS;
2450}
2451
2452/* Help display function for all node. */
2453DEFUN (config_help,
2454 config_help_cmd,
2455 "help",
2456 "Description of the interactive help system\n")
2457{
2458 vty_out (vty,
hasso6590f2c2004-10-19 20:40:08 +00002459 "Quagga VTY provides advanced help feature. When you need help,%s\
paul718e3742002-12-13 20:15:29 +00002460anytime at the command line please press '?'.%s\
2461%s\
2462If nothing matches, the help list will be empty and you must backup%s\
2463 until entering a '?' shows the available options.%s\
2464Two styles of help are provided:%s\
24651. Full help is available when you are ready to enter a%s\
2466command argument (e.g. 'show ?') and describes each possible%s\
2467argument.%s\
24682. Partial help is provided when an abbreviated argument is entered%s\
2469 and you want to know what arguments match the input%s\
2470 (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2471 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2472 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2473 return CMD_SUCCESS;
2474}
2475
2476/* Help display function for all node. */
2477DEFUN (config_list,
2478 config_list_cmd,
2479 "list",
2480 "Print command list\n")
2481{
hasso8c328f12004-10-05 21:01:23 +00002482 unsigned int i;
paul718e3742002-12-13 20:15:29 +00002483 struct cmd_node *cnode = vector_slot (cmdvec, vty->node);
2484 struct cmd_element *cmd;
2485
2486 for (i = 0; i < vector_max (cnode->cmd_vector); i++)
2487 if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL)
2488 vty_out (vty, " %s%s", cmd->string,
2489 VTY_NEWLINE);
2490 return CMD_SUCCESS;
2491}
2492
2493/* Write current configuration into file. */
2494DEFUN (config_write_file,
2495 config_write_file_cmd,
2496 "write file",
2497 "Write running configuration to memory, network, or terminal\n"
2498 "Write to configuration file\n")
2499{
hasso8c328f12004-10-05 21:01:23 +00002500 unsigned int i;
paul718e3742002-12-13 20:15:29 +00002501 int fd;
2502 struct cmd_node *node;
2503 char *config_file;
2504 char *config_file_tmp = NULL;
2505 char *config_file_sav = NULL;
2506 struct vty *file_vty;
2507
2508 /* Check and see if we are operating under vtysh configuration */
2509 if (host.config == NULL)
2510 {
2511 vty_out (vty, "Can't save to configuration file, using vtysh.%s",
2512 VTY_NEWLINE);
2513 return CMD_WARNING;
2514 }
2515
2516 /* Get filename. */
2517 config_file = host.config;
2518
2519 config_file_sav = malloc (strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1);
2520 strcpy (config_file_sav, config_file);
2521 strcat (config_file_sav, CONF_BACKUP_EXT);
2522
2523
2524 config_file_tmp = malloc (strlen (config_file) + 8);
2525 sprintf (config_file_tmp, "%s.XXXXXX", config_file);
2526
2527 /* Open file to configuration write. */
2528 fd = mkstemp (config_file_tmp);
2529 if (fd < 0)
2530 {
2531 vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp,
2532 VTY_NEWLINE);
2533 free (config_file_tmp);
2534 free (config_file_sav);
2535 return CMD_WARNING;
2536 }
2537
2538 /* Make vty for configuration file. */
2539 file_vty = vty_new ();
2540 file_vty->fd = fd;
2541 file_vty->type = VTY_FILE;
2542
2543 /* Config file header print. */
2544 vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! ");
2545 vty_time_print (file_vty, 1);
2546 vty_out (file_vty, "!\n");
2547
2548 for (i = 0; i < vector_max (cmdvec); i++)
2549 if ((node = vector_slot (cmdvec, i)) && node->func)
2550 {
2551 if ((*node->func) (file_vty))
2552 vty_out (file_vty, "!\n");
2553 }
2554 vty_close (file_vty);
2555
2556 if (unlink (config_file_sav) != 0)
2557 if (errno != ENOENT)
2558 {
2559 vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav,
2560 VTY_NEWLINE);
2561 free (config_file_sav);
2562 free (config_file_tmp);
2563 unlink (config_file_tmp);
2564 return CMD_WARNING;
2565 }
2566 if (link (config_file, config_file_sav) != 0)
2567 {
2568 vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
2569 VTY_NEWLINE);
2570 free (config_file_sav);
2571 free (config_file_tmp);
2572 unlink (config_file_tmp);
2573 return CMD_WARNING;
2574 }
2575 sync ();
2576 if (unlink (config_file) != 0)
2577 {
2578 vty_out (vty, "Can't unlink configuration file %s.%s", config_file,
2579 VTY_NEWLINE);
2580 free (config_file_sav);
2581 free (config_file_tmp);
2582 unlink (config_file_tmp);
2583 return CMD_WARNING;
2584 }
2585 if (link (config_file_tmp, config_file) != 0)
2586 {
2587 vty_out (vty, "Can't save configuration file %s.%s", config_file,
2588 VTY_NEWLINE);
2589 free (config_file_sav);
2590 free (config_file_tmp);
2591 unlink (config_file_tmp);
2592 return CMD_WARNING;
2593 }
2594 unlink (config_file_tmp);
2595 sync ();
2596
2597 free (config_file_sav);
2598 free (config_file_tmp);
gdtaa593d52003-12-22 20:15:53 +00002599
2600 if (chmod (config_file, CONFIGFILE_MASK) != 0)
2601 {
2602 vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s",
ajs6099b3b2004-11-20 02:06:59 +00002603 config_file, safe_strerror(errno), errno, VTY_NEWLINE);
gdtaa593d52003-12-22 20:15:53 +00002604 return CMD_WARNING;
2605 }
2606
paul718e3742002-12-13 20:15:29 +00002607 vty_out (vty, "Configuration saved to %s%s", config_file,
2608 VTY_NEWLINE);
2609 return CMD_SUCCESS;
2610}
2611
2612ALIAS (config_write_file,
2613 config_write_cmd,
2614 "write",
2615 "Write running configuration to memory, network, or terminal\n")
2616
2617ALIAS (config_write_file,
2618 config_write_memory_cmd,
2619 "write memory",
2620 "Write running configuration to memory, network, or terminal\n"
2621 "Write configuration to the file (same as write file)\n")
2622
2623ALIAS (config_write_file,
2624 copy_runningconfig_startupconfig_cmd,
2625 "copy running-config startup-config",
2626 "Copy configuration\n"
2627 "Copy running config to... \n"
2628 "Copy running config to startup config (same as write file)\n")
2629
2630/* Write current configuration into the terminal. */
2631DEFUN (config_write_terminal,
2632 config_write_terminal_cmd,
2633 "write terminal",
2634 "Write running configuration to memory, network, or terminal\n"
2635 "Write to terminal\n")
2636{
hasso8c328f12004-10-05 21:01:23 +00002637 unsigned int i;
paul718e3742002-12-13 20:15:29 +00002638 struct cmd_node *node;
2639
2640 if (vty->type == VTY_SHELL_SERV)
2641 {
2642 for (i = 0; i < vector_max (cmdvec); i++)
2643 if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
2644 {
2645 if ((*node->func) (vty))
2646 vty_out (vty, "!%s", VTY_NEWLINE);
2647 }
2648 }
2649 else
2650 {
2651 vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
2652 VTY_NEWLINE);
2653 vty_out (vty, "!%s", VTY_NEWLINE);
2654
2655 for (i = 0; i < vector_max (cmdvec); i++)
2656 if ((node = vector_slot (cmdvec, i)) && node->func)
2657 {
2658 if ((*node->func) (vty))
2659 vty_out (vty, "!%s", VTY_NEWLINE);
2660 }
2661 vty_out (vty, "end%s",VTY_NEWLINE);
2662 }
2663 return CMD_SUCCESS;
2664}
2665
2666/* Write current configuration into the terminal. */
2667ALIAS (config_write_terminal,
2668 show_running_config_cmd,
2669 "show running-config",
2670 SHOW_STR
2671 "running configuration\n")
2672
2673/* Write startup configuration into the terminal. */
2674DEFUN (show_startup_config,
2675 show_startup_config_cmd,
2676 "show startup-config",
2677 SHOW_STR
2678 "Contentes of startup configuration\n")
2679{
2680 char buf[BUFSIZ];
2681 FILE *confp;
2682
2683 confp = fopen (host.config, "r");
2684 if (confp == NULL)
2685 {
2686 vty_out (vty, "Can't open configuration file [%s]%s",
2687 host.config, VTY_NEWLINE);
2688 return CMD_WARNING;
2689 }
2690
2691 while (fgets (buf, BUFSIZ, confp))
2692 {
2693 char *cp = buf;
2694
2695 while (*cp != '\r' && *cp != '\n' && *cp != '\0')
2696 cp++;
2697 *cp = '\0';
2698
2699 vty_out (vty, "%s%s", buf, VTY_NEWLINE);
2700 }
2701
2702 fclose (confp);
2703
2704 return CMD_SUCCESS;
2705}
2706
2707/* Hostname configuration */
2708DEFUN (config_hostname,
2709 hostname_cmd,
2710 "hostname WORD",
2711 "Set system's network name\n"
2712 "This system's network name\n")
2713{
2714 if (!isalpha((int) *argv[0]))
2715 {
2716 vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE);
2717 return CMD_WARNING;
2718 }
2719
2720 if (host.name)
2721 XFREE (0, host.name);
2722
2723 host.name = strdup (argv[0]);
2724 return CMD_SUCCESS;
2725}
2726
2727DEFUN (config_no_hostname,
2728 no_hostname_cmd,
2729 "no hostname [HOSTNAME]",
2730 NO_STR
2731 "Reset system's network name\n"
2732 "Host name of this router\n")
2733{
2734 if (host.name)
2735 XFREE (0, host.name);
2736 host.name = NULL;
2737 return CMD_SUCCESS;
2738}
2739
2740/* VTY interface password set. */
2741DEFUN (config_password, password_cmd,
2742 "password (8|) WORD",
2743 "Assign the terminal connection password\n"
2744 "Specifies a HIDDEN password will follow\n"
2745 "dummy string \n"
2746 "The HIDDEN line password string\n")
2747{
2748 /* Argument check. */
2749 if (argc == 0)
2750 {
2751 vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
2752 return CMD_WARNING;
2753 }
2754
2755 if (argc == 2)
2756 {
2757 if (*argv[0] == '8')
2758 {
2759 if (host.password)
2760 XFREE (0, host.password);
2761 host.password = NULL;
2762 if (host.password_encrypt)
2763 XFREE (0, host.password_encrypt);
2764 host.password_encrypt = XSTRDUP (0, strdup (argv[1]));
2765 return CMD_SUCCESS;
2766 }
2767 else
2768 {
2769 vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
2770 return CMD_WARNING;
2771 }
2772 }
2773
2774 if (!isalnum ((int) *argv[0]))
2775 {
2776 vty_out (vty,
2777 "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
2778 return CMD_WARNING;
2779 }
2780
2781 if (host.password)
2782 XFREE (0, host.password);
2783 host.password = NULL;
2784
2785 if (host.encrypt)
2786 {
2787 if (host.password_encrypt)
2788 XFREE (0, host.password_encrypt);
2789 host.password_encrypt = XSTRDUP (0, zencrypt (argv[0]));
2790 }
2791 else
2792 host.password = XSTRDUP (0, argv[0]);
2793
2794 return CMD_SUCCESS;
2795}
2796
2797ALIAS (config_password, password_text_cmd,
2798 "password LINE",
2799 "Assign the terminal connection password\n"
2800 "The UNENCRYPTED (cleartext) line password\n")
2801
2802/* VTY enable password set. */
2803DEFUN (config_enable_password, enable_password_cmd,
2804 "enable password (8|) WORD",
2805 "Modify enable password parameters\n"
2806 "Assign the privileged level password\n"
2807 "Specifies a HIDDEN password will follow\n"
2808 "dummy string \n"
2809 "The HIDDEN 'enable' password string\n")
2810{
2811 /* Argument check. */
2812 if (argc == 0)
2813 {
2814 vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
2815 return CMD_WARNING;
2816 }
2817
2818 /* Crypt type is specified. */
2819 if (argc == 2)
2820 {
2821 if (*argv[0] == '8')
2822 {
2823 if (host.enable)
2824 XFREE (0, host.enable);
2825 host.enable = NULL;
2826
2827 if (host.enable_encrypt)
2828 XFREE (0, host.enable_encrypt);
2829 host.enable_encrypt = XSTRDUP (0, argv[1]);
2830
2831 return CMD_SUCCESS;
2832 }
2833 else
2834 {
2835 vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
2836 return CMD_WARNING;
2837 }
2838 }
2839
2840 if (!isalnum ((int) *argv[0]))
2841 {
2842 vty_out (vty,
2843 "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
2844 return CMD_WARNING;
2845 }
2846
2847 if (host.enable)
2848 XFREE (0, host.enable);
2849 host.enable = NULL;
2850
2851 /* Plain password input. */
2852 if (host.encrypt)
2853 {
2854 if (host.enable_encrypt)
2855 XFREE (0, host.enable_encrypt);
2856 host.enable_encrypt = XSTRDUP (0, zencrypt (argv[0]));
2857 }
2858 else
2859 host.enable = XSTRDUP (0, argv[0]);
2860
2861 return CMD_SUCCESS;
2862}
2863
2864ALIAS (config_enable_password,
2865 enable_password_text_cmd,
2866 "enable password LINE",
2867 "Modify enable password parameters\n"
2868 "Assign the privileged level password\n"
2869 "The UNENCRYPTED (cleartext) 'enable' password\n")
2870
2871/* VTY enable password delete. */
2872DEFUN (no_config_enable_password, no_enable_password_cmd,
2873 "no enable password",
2874 NO_STR
2875 "Modify enable password parameters\n"
2876 "Assign the privileged level password\n")
2877{
2878 if (host.enable)
2879 XFREE (0, host.enable);
2880 host.enable = NULL;
2881
2882 if (host.enable_encrypt)
2883 XFREE (0, host.enable_encrypt);
2884 host.enable_encrypt = NULL;
2885
2886 return CMD_SUCCESS;
2887}
2888
2889DEFUN (service_password_encrypt,
2890 service_password_encrypt_cmd,
2891 "service password-encryption",
2892 "Set up miscellaneous service\n"
2893 "Enable encrypted passwords\n")
2894{
2895 if (host.encrypt)
2896 return CMD_SUCCESS;
2897
2898 host.encrypt = 1;
2899
2900 if (host.password)
2901 {
2902 if (host.password_encrypt)
2903 XFREE (0, host.password_encrypt);
2904 host.password_encrypt = XSTRDUP (0, zencrypt (host.password));
2905 }
2906 if (host.enable)
2907 {
2908 if (host.enable_encrypt)
2909 XFREE (0, host.enable_encrypt);
2910 host.enable_encrypt = XSTRDUP (0, zencrypt (host.enable));
2911 }
2912
2913 return CMD_SUCCESS;
2914}
2915
2916DEFUN (no_service_password_encrypt,
2917 no_service_password_encrypt_cmd,
2918 "no service password-encryption",
2919 NO_STR
2920 "Set up miscellaneous service\n"
2921 "Enable encrypted passwords\n")
2922{
2923 if (! host.encrypt)
2924 return CMD_SUCCESS;
2925
2926 host.encrypt = 0;
2927
2928 if (host.password_encrypt)
2929 XFREE (0, host.password_encrypt);
2930 host.password_encrypt = NULL;
2931
2932 if (host.enable_encrypt)
2933 XFREE (0, host.enable_encrypt);
2934 host.enable_encrypt = NULL;
2935
2936 return CMD_SUCCESS;
2937}
2938
2939DEFUN (config_terminal_length, config_terminal_length_cmd,
2940 "terminal length <0-512>",
2941 "Set terminal line parameters\n"
2942 "Set number of lines on a screen\n"
2943 "Number of lines on screen (0 for no pausing)\n")
2944{
2945 int lines;
2946 char *endptr = NULL;
2947
2948 lines = strtol (argv[0], &endptr, 10);
2949 if (lines < 0 || lines > 512 || *endptr != '\0')
2950 {
2951 vty_out (vty, "length is malformed%s", VTY_NEWLINE);
2952 return CMD_WARNING;
2953 }
2954 vty->lines = lines;
2955
2956 return CMD_SUCCESS;
2957}
2958
2959DEFUN (config_terminal_no_length, config_terminal_no_length_cmd,
2960 "terminal no length",
2961 "Set terminal line parameters\n"
2962 NO_STR
2963 "Set number of lines on a screen\n")
2964{
2965 vty->lines = -1;
2966 return CMD_SUCCESS;
2967}
2968
2969DEFUN (service_terminal_length, service_terminal_length_cmd,
2970 "service terminal-length <0-512>",
2971 "Set up miscellaneous service\n"
2972 "System wide terminal length configuration\n"
2973 "Number of lines of VTY (0 means no line control)\n")
2974{
2975 int lines;
2976 char *endptr = NULL;
2977
2978 lines = strtol (argv[0], &endptr, 10);
2979 if (lines < 0 || lines > 512 || *endptr != '\0')
2980 {
2981 vty_out (vty, "length is malformed%s", VTY_NEWLINE);
2982 return CMD_WARNING;
2983 }
2984 host.lines = lines;
2985
2986 return CMD_SUCCESS;
2987}
2988
2989DEFUN (no_service_terminal_length, no_service_terminal_length_cmd,
2990 "no service terminal-length [<0-512>]",
2991 NO_STR
2992 "Set up miscellaneous service\n"
2993 "System wide terminal length configuration\n"
2994 "Number of lines of VTY (0 means no line control)\n")
2995{
2996 host.lines = -1;
2997 return CMD_SUCCESS;
2998}
2999
ajs2885f722004-12-17 23:16:33 +00003000DEFUN_HIDDEN (do_echo,
3001 echo_cmd,
3002 "echo .MESSAGE",
3003 "Echo a message back to the vty\n"
3004 "The message to echo\n")
3005{
3006 char *message;
3007
3008 vty_out (vty, "%s%s",(message = argv_concat(argv, argc, 0)), VTY_NEWLINE);
3009 XFREE(MTYPE_TMP, message);
3010 return CMD_SUCCESS;
3011}
3012
ajs274a4a42004-12-07 15:39:31 +00003013DEFUN (config_logmsg,
3014 config_logmsg_cmd,
3015 "logmsg "LOG_LEVELS" .MESSAGE",
3016 "Send a message to enabled logging destinations\n"
3017 LOG_LEVEL_DESC
3018 "The message to send\n")
3019{
3020 int level;
3021 char *message;
3022
3023 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3024 return CMD_ERR_NO_MATCH;
3025
3026 zlog(NULL, level, (message = argv_concat(argv, argc, 1)));
3027 XFREE(MTYPE_TMP, message);
3028 return CMD_SUCCESS;
3029}
3030
3031DEFUN (show_logging,
3032 show_logging_cmd,
3033 "show logging",
3034 SHOW_STR
3035 "Show current logging configuration\n")
3036{
3037 struct zlog *zl = zlog_default;
3038
3039 vty_out (vty, "Syslog logging: ");
3040 if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED)
3041 vty_out (vty, "disabled");
3042 else
3043 vty_out (vty, "level %s, facility %s, ident %s",
3044 zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]],
3045 facility_name(zl->facility), zl->ident);
3046 vty_out (vty, "%s", VTY_NEWLINE);
3047
3048 vty_out (vty, "Stdout logging: ");
3049 if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED)
3050 vty_out (vty, "disabled");
3051 else
3052 vty_out (vty, "level %s",
3053 zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]);
3054 vty_out (vty, "%s", VTY_NEWLINE);
3055
3056 vty_out (vty, "Monitor logging: ");
3057 if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
3058 vty_out (vty, "disabled");
3059 else
3060 vty_out (vty, "level %s",
3061 zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]);
3062 vty_out (vty, "%s", VTY_NEWLINE);
3063
3064 vty_out (vty, "File logging: ");
3065 if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) ||
3066 !zl->fp)
3067 vty_out (vty, "disabled");
3068 else
3069 vty_out (vty, "level %s, filename %s",
3070 zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]],
3071 zl->filename);
3072 vty_out (vty, "%s", VTY_NEWLINE);
3073
3074 vty_out (vty, "Protocol name: %s%s",
3075 zlog_proto_names[zl->protocol], VTY_NEWLINE);
3076 vty_out (vty, "Record priority: %s%s",
3077 (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE);
3078
3079 return CMD_SUCCESS;
3080}
3081
paul718e3742002-12-13 20:15:29 +00003082DEFUN (config_log_stdout,
3083 config_log_stdout_cmd,
3084 "log stdout",
3085 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003086 "Set stdout logging level\n")
paul718e3742002-12-13 20:15:29 +00003087{
ajs274a4a42004-12-07 15:39:31 +00003088 zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl);
3089 return CMD_SUCCESS;
3090}
3091
3092DEFUN (config_log_stdout_level,
3093 config_log_stdout_level_cmd,
3094 "log stdout "LOG_LEVELS,
3095 "Logging control\n"
3096 "Set stdout logging level\n"
3097 LOG_LEVEL_DESC)
3098{
3099 int level;
3100
3101 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3102 return CMD_ERR_NO_MATCH;
3103 zlog_set_level (NULL, ZLOG_DEST_STDOUT, level);
paul718e3742002-12-13 20:15:29 +00003104 return CMD_SUCCESS;
3105}
3106
3107DEFUN (no_config_log_stdout,
3108 no_config_log_stdout_cmd,
ajs274a4a42004-12-07 15:39:31 +00003109 "no log stdout [LEVEL]",
paul718e3742002-12-13 20:15:29 +00003110 NO_STR
3111 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003112 "Cancel logging to stdout\n"
3113 "Logging level\n")
paul718e3742002-12-13 20:15:29 +00003114{
ajs274a4a42004-12-07 15:39:31 +00003115 zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
paul718e3742002-12-13 20:15:29 +00003116 return CMD_SUCCESS;
3117}
3118
ajs274a4a42004-12-07 15:39:31 +00003119DEFUN (config_log_monitor,
3120 config_log_monitor_cmd,
3121 "log monitor",
paul718e3742002-12-13 20:15:29 +00003122 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003123 "Set terminal line (monitor) logging level\n")
3124{
3125 zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl);
3126 return CMD_SUCCESS;
3127}
3128
3129DEFUN (config_log_monitor_level,
3130 config_log_monitor_level_cmd,
3131 "log monitor "LOG_LEVELS,
3132 "Logging control\n"
3133 "Set terminal line (monitor) logging level\n"
3134 LOG_LEVEL_DESC)
3135{
3136 int level;
3137
3138 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3139 return CMD_ERR_NO_MATCH;
3140 zlog_set_level (NULL, ZLOG_DEST_MONITOR, level);
3141 return CMD_SUCCESS;
3142}
3143
3144DEFUN (no_config_log_monitor,
3145 no_config_log_monitor_cmd,
3146 "no log monitor [LEVEL]",
3147 NO_STR
3148 "Logging control\n"
3149 "Disable terminal line (monitor) logging\n"
3150 "Logging level\n")
3151{
3152 zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
3153 return CMD_SUCCESS;
3154}
3155
3156static int
3157set_log_file(struct vty *vty, const char *fname, int loglevel)
paul718e3742002-12-13 20:15:29 +00003158{
3159 int ret;
paul9035efa2004-10-10 11:56:56 +00003160 char *p = NULL;
3161 const char *fullpath;
3162
paul718e3742002-12-13 20:15:29 +00003163 /* Path detection. */
ajs274a4a42004-12-07 15:39:31 +00003164 if (! IS_DIRECTORY_SEP (*fname))
paul718e3742002-12-13 20:15:29 +00003165 {
paul9035efa2004-10-10 11:56:56 +00003166 char cwd[MAXPATHLEN+1];
3167 cwd[MAXPATHLEN] = '\0';
3168
3169 if (getcwd (cwd, MAXPATHLEN) == NULL)
3170 {
3171 zlog_err ("config_log_file: Unable to alloc mem!");
3172 return CMD_WARNING;
3173 }
3174
ajs274a4a42004-12-07 15:39:31 +00003175 if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2))
paul9035efa2004-10-10 11:56:56 +00003176 == NULL)
3177 {
3178 zlog_err ("config_log_file: Unable to alloc mem!");
3179 return CMD_WARNING;
3180 }
ajs274a4a42004-12-07 15:39:31 +00003181 sprintf (p, "%s/%s", cwd, fname);
paul9035efa2004-10-10 11:56:56 +00003182 fullpath = p;
paul718e3742002-12-13 20:15:29 +00003183 }
3184 else
ajs274a4a42004-12-07 15:39:31 +00003185 fullpath = fname;
paul718e3742002-12-13 20:15:29 +00003186
ajs274a4a42004-12-07 15:39:31 +00003187 ret = zlog_set_file (NULL, fullpath, loglevel);
paul718e3742002-12-13 20:15:29 +00003188
paul9035efa2004-10-10 11:56:56 +00003189 if (p)
3190 XFREE (MTYPE_TMP, p);
3191
paul718e3742002-12-13 20:15:29 +00003192 if (!ret)
3193 {
ajs274a4a42004-12-07 15:39:31 +00003194 vty_out (vty, "can't open logfile %s\n", fname);
paul718e3742002-12-13 20:15:29 +00003195 return CMD_WARNING;
3196 }
3197
3198 if (host.logfile)
3199 XFREE (MTYPE_TMP, host.logfile);
3200
ajs274a4a42004-12-07 15:39:31 +00003201 host.logfile = XSTRDUP (MTYPE_TMP, fname);
paul718e3742002-12-13 20:15:29 +00003202
3203 return CMD_SUCCESS;
3204}
3205
ajs274a4a42004-12-07 15:39:31 +00003206DEFUN (config_log_file,
3207 config_log_file_cmd,
3208 "log file FILENAME",
3209 "Logging control\n"
3210 "Logging to file\n"
3211 "Logging filename\n")
3212{
3213 return set_log_file(vty, argv[0], zlog_default->default_lvl);
3214}
3215
3216DEFUN (config_log_file_level,
3217 config_log_file_level_cmd,
3218 "log file FILENAME "LOG_LEVELS,
3219 "Logging control\n"
3220 "Logging to file\n"
3221 "Logging filename\n"
3222 LOG_LEVEL_DESC)
3223{
3224 int level;
3225
3226 if ((level = level_match(argv[1])) == ZLOG_DISABLED)
3227 return CMD_ERR_NO_MATCH;
3228 return set_log_file(vty, argv[0], level);
3229}
3230
paul718e3742002-12-13 20:15:29 +00003231DEFUN (no_config_log_file,
3232 no_config_log_file_cmd,
3233 "no log file [FILENAME]",
3234 NO_STR
3235 "Logging control\n"
3236 "Cancel logging to file\n"
3237 "Logging file name\n")
3238{
3239 zlog_reset_file (NULL);
3240
3241 if (host.logfile)
3242 XFREE (MTYPE_TMP, host.logfile);
3243
3244 host.logfile = NULL;
3245
3246 return CMD_SUCCESS;
3247}
3248
ajs274a4a42004-12-07 15:39:31 +00003249ALIAS (no_config_log_file,
3250 no_config_log_file_level_cmd,
3251 "no log file FILENAME LEVEL",
3252 NO_STR
3253 "Logging control\n"
3254 "Cancel logging to file\n"
3255 "Logging file name\n"
3256 "Logging level\n")
3257
paul718e3742002-12-13 20:15:29 +00003258DEFUN (config_log_syslog,
3259 config_log_syslog_cmd,
3260 "log syslog",
3261 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003262 "Set syslog logging level\n")
paul718e3742002-12-13 20:15:29 +00003263{
ajs274a4a42004-12-07 15:39:31 +00003264 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
paul12ab19f2003-07-26 06:14:55 +00003265 return CMD_SUCCESS;
3266}
3267
ajs274a4a42004-12-07 15:39:31 +00003268DEFUN (config_log_syslog_level,
3269 config_log_syslog_level_cmd,
3270 "log syslog "LOG_LEVELS,
paul12ab19f2003-07-26 06:14:55 +00003271 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003272 "Set syslog logging level\n"
3273 LOG_LEVEL_DESC)
paul12ab19f2003-07-26 06:14:55 +00003274{
ajs274a4a42004-12-07 15:39:31 +00003275 int level;
paul12ab19f2003-07-26 06:14:55 +00003276
ajs274a4a42004-12-07 15:39:31 +00003277 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3278 return CMD_ERR_NO_MATCH;
3279 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, level);
3280 return CMD_SUCCESS;
3281}
paul12ab19f2003-07-26 06:14:55 +00003282
ajs274a4a42004-12-07 15:39:31 +00003283DEFUN_DEPRECATED (config_log_syslog_facility,
3284 config_log_syslog_facility_cmd,
3285 "log syslog facility "LOG_FACILITIES,
3286 "Logging control\n"
3287 "Logging goes to syslog\n"
3288 "(Deprecated) Facility parameter for syslog messages\n"
3289 LOG_FACILITY_DESC)
3290{
3291 int facility;
paul12ab19f2003-07-26 06:14:55 +00003292
ajs274a4a42004-12-07 15:39:31 +00003293 if ((facility = facility_match(argv[0])) < 0)
3294 return CMD_ERR_NO_MATCH;
3295
3296 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
paul12ab19f2003-07-26 06:14:55 +00003297 zlog_default->facility = facility;
paul718e3742002-12-13 20:15:29 +00003298 return CMD_SUCCESS;
3299}
3300
3301DEFUN (no_config_log_syslog,
3302 no_config_log_syslog_cmd,
ajs274a4a42004-12-07 15:39:31 +00003303 "no log syslog [LEVEL]",
paul718e3742002-12-13 20:15:29 +00003304 NO_STR
3305 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003306 "Cancel logging to syslog\n"
3307 "Logging level\n")
paul718e3742002-12-13 20:15:29 +00003308{
ajs274a4a42004-12-07 15:39:31 +00003309 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
paul718e3742002-12-13 20:15:29 +00003310 return CMD_SUCCESS;
3311}
3312
paul12ab19f2003-07-26 06:14:55 +00003313ALIAS (no_config_log_syslog,
3314 no_config_log_syslog_facility_cmd,
ajs274a4a42004-12-07 15:39:31 +00003315 "no log syslog facility "LOG_FACILITIES,
paul12ab19f2003-07-26 06:14:55 +00003316 NO_STR
3317 "Logging control\n"
3318 "Logging goes to syslog\n"
3319 "Facility parameter for syslog messages\n"
ajs274a4a42004-12-07 15:39:31 +00003320 LOG_FACILITY_DESC)
paul12ab19f2003-07-26 06:14:55 +00003321
ajs274a4a42004-12-07 15:39:31 +00003322DEFUN (config_log_facility,
3323 config_log_facility_cmd,
3324 "log facility "LOG_FACILITIES,
paul718e3742002-12-13 20:15:29 +00003325 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003326 "Facility parameter for syslog messages\n"
3327 LOG_FACILITY_DESC)
paul718e3742002-12-13 20:15:29 +00003328{
ajs274a4a42004-12-07 15:39:31 +00003329 int facility;
3330
3331 if ((facility = facility_match(argv[0])) < 0)
3332 return CMD_ERR_NO_MATCH;
3333 zlog_default->facility = facility;
3334 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +00003335}
3336
ajs274a4a42004-12-07 15:39:31 +00003337DEFUN (no_config_log_facility,
3338 no_config_log_facility_cmd,
3339 "no log facility [FACILITY]",
paul718e3742002-12-13 20:15:29 +00003340 NO_STR
3341 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003342 "Reset syslog facility to default (daemon)\n"
3343 "Syslog facility\n")
paul718e3742002-12-13 20:15:29 +00003344{
ajs274a4a42004-12-07 15:39:31 +00003345 zlog_default->facility = LOG_DAEMON;
3346 return CMD_SUCCESS;
3347}
3348
3349DEFUN_DEPRECATED (config_log_trap,
3350 config_log_trap_cmd,
3351 "log trap "LOG_LEVELS,
3352 "Logging control\n"
3353 "(Deprecated) Set logging level and default for all destinations\n"
3354 LOG_LEVEL_DESC)
3355{
3356 int new_level ;
3357 int i;
3358
3359 if ((new_level = level_match(argv[0])) == ZLOG_DISABLED)
3360 return CMD_ERR_NO_MATCH;
3361
3362 zlog_default->default_lvl = new_level;
3363 for (i = 0; i < ZLOG_NUM_DESTS; i++)
3364 if (zlog_default->maxlvl[i] != ZLOG_DISABLED)
3365 zlog_default->maxlvl[i] = new_level;
3366 return CMD_SUCCESS;
3367}
3368
3369DEFUN_DEPRECATED (no_config_log_trap,
3370 no_config_log_trap_cmd,
3371 "no log trap [LEVEL]",
3372 NO_STR
3373 "Logging control\n"
3374 "Permit all logging information\n"
3375 "Logging level\n")
3376{
3377 zlog_default->default_lvl = LOG_DEBUG;
paul718e3742002-12-13 20:15:29 +00003378 return CMD_SUCCESS;
3379}
3380
3381DEFUN (config_log_record_priority,
3382 config_log_record_priority_cmd,
3383 "log record-priority",
3384 "Logging control\n"
3385 "Log the priority of the message within the message\n")
3386{
3387 zlog_default->record_priority = 1 ;
3388 return CMD_SUCCESS;
3389}
3390
3391DEFUN (no_config_log_record_priority,
3392 no_config_log_record_priority_cmd,
3393 "no log record-priority",
3394 NO_STR
3395 "Logging control\n"
3396 "Do not log the priority of the message within the message\n")
3397{
3398 zlog_default->record_priority = 0 ;
3399 return CMD_SUCCESS;
3400}
3401
3402
3403DEFUN (banner_motd_default,
3404 banner_motd_default_cmd,
3405 "banner motd default",
3406 "Set banner string\n"
3407 "Strings for motd\n"
3408 "Default string\n")
3409{
3410 host.motd = default_motd;
3411 return CMD_SUCCESS;
3412}
3413
3414DEFUN (no_banner_motd,
3415 no_banner_motd_cmd,
3416 "no banner motd",
3417 NO_STR
3418 "Set banner string\n"
3419 "Strings for motd\n")
3420{
3421 host.motd = NULL;
3422 return CMD_SUCCESS;
3423}
3424
3425/* Set config filename. Called from vty.c */
3426void
3427host_config_set (char *filename)
3428{
3429 host.config = strdup (filename);
3430}
3431
3432void
3433install_default (enum node_type node)
3434{
3435 install_element (node, &config_exit_cmd);
3436 install_element (node, &config_quit_cmd);
3437 install_element (node, &config_end_cmd);
3438 install_element (node, &config_help_cmd);
3439 install_element (node, &config_list_cmd);
3440
3441 install_element (node, &config_write_terminal_cmd);
3442 install_element (node, &config_write_file_cmd);
3443 install_element (node, &config_write_memory_cmd);
3444 install_element (node, &config_write_cmd);
3445 install_element (node, &show_running_config_cmd);
3446}
3447
3448/* Initialize command interface. Install basic nodes and commands. */
3449void
3450cmd_init (int terminal)
3451{
3452 /* Allocate initial top vector of commands. */
3453 cmdvec = vector_init (VECTOR_MIN_SIZE);
3454
3455 /* Default host value settings. */
3456 host.name = NULL;
3457 host.password = NULL;
3458 host.enable = NULL;
3459 host.logfile = NULL;
3460 host.config = NULL;
3461 host.lines = -1;
3462 host.motd = default_motd;
3463
3464 /* Install top nodes. */
3465 install_node (&view_node, NULL);
3466 install_node (&enable_node, NULL);
3467 install_node (&auth_node, NULL);
3468 install_node (&auth_enable_node, NULL);
3469 install_node (&config_node, config_write_host);
3470
3471 /* Each node's basic commands. */
3472 install_element (VIEW_NODE, &show_version_cmd);
3473 if (terminal)
3474 {
3475 install_element (VIEW_NODE, &config_list_cmd);
3476 install_element (VIEW_NODE, &config_exit_cmd);
3477 install_element (VIEW_NODE, &config_quit_cmd);
3478 install_element (VIEW_NODE, &config_help_cmd);
3479 install_element (VIEW_NODE, &config_enable_cmd);
3480 install_element (VIEW_NODE, &config_terminal_length_cmd);
3481 install_element (VIEW_NODE, &config_terminal_no_length_cmd);
ajs274a4a42004-12-07 15:39:31 +00003482 install_element (VIEW_NODE, &show_logging_cmd);
ajs2885f722004-12-17 23:16:33 +00003483 install_element (VIEW_NODE, &echo_cmd);
paul718e3742002-12-13 20:15:29 +00003484 }
3485
3486 if (terminal)
3487 {
3488 install_default (ENABLE_NODE);
3489 install_element (ENABLE_NODE, &config_disable_cmd);
3490 install_element (ENABLE_NODE, &config_terminal_cmd);
3491 install_element (ENABLE_NODE, &copy_runningconfig_startupconfig_cmd);
3492 }
3493 install_element (ENABLE_NODE, &show_startup_config_cmd);
3494 install_element (ENABLE_NODE, &show_version_cmd);
paul718e3742002-12-13 20:15:29 +00003495
3496 if (terminal)
paul718e3742002-12-13 20:15:29 +00003497 {
hassoe7168df2004-10-03 20:11:32 +00003498 install_element (ENABLE_NODE, &config_terminal_length_cmd);
3499 install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
ajs274a4a42004-12-07 15:39:31 +00003500 install_element (ENABLE_NODE, &show_logging_cmd);
ajs2885f722004-12-17 23:16:33 +00003501 install_element (ENABLE_NODE, &echo_cmd);
ajs274a4a42004-12-07 15:39:31 +00003502 install_element (ENABLE_NODE, &config_logmsg_cmd);
hassoe7168df2004-10-03 20:11:32 +00003503
3504 install_default (CONFIG_NODE);
hassoea8e9d92004-10-07 21:32:14 +00003505 }
3506
3507 install_element (CONFIG_NODE, &hostname_cmd);
3508 install_element (CONFIG_NODE, &no_hostname_cmd);
hassoe7168df2004-10-03 20:11:32 +00003509
hassoea8e9d92004-10-07 21:32:14 +00003510 if (terminal)
3511 {
hassoe7168df2004-10-03 20:11:32 +00003512 install_element (CONFIG_NODE, &password_cmd);
3513 install_element (CONFIG_NODE, &password_text_cmd);
3514 install_element (CONFIG_NODE, &enable_password_cmd);
3515 install_element (CONFIG_NODE, &enable_password_text_cmd);
3516 install_element (CONFIG_NODE, &no_enable_password_cmd);
3517
paul718e3742002-12-13 20:15:29 +00003518 install_element (CONFIG_NODE, &config_log_stdout_cmd);
ajs274a4a42004-12-07 15:39:31 +00003519 install_element (CONFIG_NODE, &config_log_stdout_level_cmd);
paul718e3742002-12-13 20:15:29 +00003520 install_element (CONFIG_NODE, &no_config_log_stdout_cmd);
ajs274a4a42004-12-07 15:39:31 +00003521 install_element (CONFIG_NODE, &config_log_monitor_cmd);
3522 install_element (CONFIG_NODE, &config_log_monitor_level_cmd);
3523 install_element (CONFIG_NODE, &no_config_log_monitor_cmd);
paul718e3742002-12-13 20:15:29 +00003524 install_element (CONFIG_NODE, &config_log_file_cmd);
ajs274a4a42004-12-07 15:39:31 +00003525 install_element (CONFIG_NODE, &config_log_file_level_cmd);
paul718e3742002-12-13 20:15:29 +00003526 install_element (CONFIG_NODE, &no_config_log_file_cmd);
ajs274a4a42004-12-07 15:39:31 +00003527 install_element (CONFIG_NODE, &no_config_log_file_level_cmd);
paul718e3742002-12-13 20:15:29 +00003528 install_element (CONFIG_NODE, &config_log_syslog_cmd);
ajs274a4a42004-12-07 15:39:31 +00003529 install_element (CONFIG_NODE, &config_log_syslog_level_cmd);
paul12ab19f2003-07-26 06:14:55 +00003530 install_element (CONFIG_NODE, &config_log_syslog_facility_cmd);
paul718e3742002-12-13 20:15:29 +00003531 install_element (CONFIG_NODE, &no_config_log_syslog_cmd);
paul12ab19f2003-07-26 06:14:55 +00003532 install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd);
ajs274a4a42004-12-07 15:39:31 +00003533 install_element (CONFIG_NODE, &config_log_facility_cmd);
3534 install_element (CONFIG_NODE, &no_config_log_facility_cmd);
paul718e3742002-12-13 20:15:29 +00003535 install_element (CONFIG_NODE, &config_log_trap_cmd);
3536 install_element (CONFIG_NODE, &no_config_log_trap_cmd);
3537 install_element (CONFIG_NODE, &config_log_record_priority_cmd);
3538 install_element (CONFIG_NODE, &no_config_log_record_priority_cmd);
3539 install_element (CONFIG_NODE, &service_password_encrypt_cmd);
3540 install_element (CONFIG_NODE, &no_service_password_encrypt_cmd);
3541 install_element (CONFIG_NODE, &banner_motd_default_cmd);
3542 install_element (CONFIG_NODE, &no_banner_motd_cmd);
3543 install_element (CONFIG_NODE, &service_terminal_length_cmd);
3544 install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
paul718e3742002-12-13 20:15:29 +00003545
paul9ab68122003-01-18 01:16:20 +00003546 install_element(VIEW_NODE, &show_thread_cpu_cmd);
3547 install_element(ENABLE_NODE, &show_thread_cpu_cmd);
3548 }
paul718e3742002-12-13 20:15:29 +00003549 srand(time(NULL));
3550}