blob: 188296722e650c2a20fcf53e31ab533e6f152195 [file] [log] [blame]
ajs274a4a42004-12-07 15:39:31 +00001/*
2 $Id: command.c,v 1.28 2004/12/07 15:39:32 ajs Exp $
3
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{
148 printf ("%s version %s (%s)\n", progname, QUAGGA_VERSION, host.name);
149 printf ("%s\n", QUAGGA_COPYRIGHT);
150}
151
paul718e3742002-12-13 20:15:29 +0000152
153/* Utility function to concatenate argv argument into a single string
154 with inserting ' ' character between each argument. */
155char *
paul42d49862004-10-13 05:22:18 +0000156argv_concat (const char **argv, int argc, int shift)
paul718e3742002-12-13 20:15:29 +0000157{
158 int i;
159 int len;
160 int index;
161 char *str;
162
163 str = NULL;
164 index = 0;
165
166 for (i = shift; i < argc; i++)
167 {
168 len = strlen (argv[i]);
169
170 if (i == shift)
171 {
172 str = XSTRDUP (MTYPE_TMP, argv[i]);
173 index = len;
174 }
175 else
176 {
177 str = XREALLOC (MTYPE_TMP, str, (index + len + 2));
178 str[index++] = ' ';
179 memcpy (str + index, argv[i], len);
180 index += len;
181 str[index] = '\0';
182 }
183 }
184 return str;
185}
186
187/* Install top node of command vector. */
188void
189install_node (struct cmd_node *node,
190 int (*func) (struct vty *))
191{
192 vector_set_index (cmdvec, node->node, node);
193 node->func = func;
194 node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
195}
196
197/* Compare two command's string. Used in sort_node (). */
ajs274a4a42004-12-07 15:39:31 +0000198static int
paul718e3742002-12-13 20:15:29 +0000199cmp_node (const void *p, const void *q)
200{
201 struct cmd_element *a = *(struct cmd_element **)p;
202 struct cmd_element *b = *(struct cmd_element **)q;
203
204 return strcmp (a->string, b->string);
205}
206
ajs274a4a42004-12-07 15:39:31 +0000207static int
paul718e3742002-12-13 20:15:29 +0000208cmp_desc (const void *p, const void *q)
209{
210 struct desc *a = *(struct desc **)p;
211 struct desc *b = *(struct desc **)q;
212
213 return strcmp (a->cmd, b->cmd);
214}
215
216/* Sort each node's command element according to command string. */
217void
218sort_node ()
219{
hasso8c328f12004-10-05 21:01:23 +0000220 unsigned int i, j;
paul718e3742002-12-13 20:15:29 +0000221 struct cmd_node *cnode;
222 vector descvec;
223 struct cmd_element *cmd_element;
224
225 for (i = 0; i < vector_max (cmdvec); i++)
226 if ((cnode = vector_slot (cmdvec, i)) != NULL)
227 {
228 vector cmd_vector = cnode->cmd_vector;
229 qsort (cmd_vector->index, cmd_vector->max, sizeof (void *), cmp_node);
230
231 for (j = 0; j < vector_max (cmd_vector); j++)
232 if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
233 {
234 descvec = vector_slot (cmd_element->strvec,
235 vector_max (cmd_element->strvec) - 1);
236 qsort (descvec->index, descvec->max, sizeof (void *), cmp_desc);
237 }
238 }
239}
240
241/* Breaking up string into each command piece. I assume given
242 character is separated by a space character. Return value is a
243 vector which includes char ** data element. */
244vector
hassoea8e9d92004-10-07 21:32:14 +0000245cmd_make_strvec (const char *string)
paul718e3742002-12-13 20:15:29 +0000246{
hassoea8e9d92004-10-07 21:32:14 +0000247 const char *cp, *start;
248 char *token;
paul718e3742002-12-13 20:15:29 +0000249 int strlen;
250 vector strvec;
251
252 if (string == NULL)
253 return NULL;
254
255 cp = string;
256
257 /* Skip white spaces. */
258 while (isspace ((int) *cp) && *cp != '\0')
259 cp++;
260
261 /* Return if there is only white spaces */
262 if (*cp == '\0')
263 return NULL;
264
265 if (*cp == '!' || *cp == '#')
266 return NULL;
267
268 /* Prepare return vector. */
269 strvec = vector_init (VECTOR_MIN_SIZE);
270
271 /* Copy each command piece and set into vector. */
272 while (1)
273 {
274 start = cp;
275 while (!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') &&
276 *cp != '\0')
277 cp++;
278 strlen = cp - start;
279 token = XMALLOC (MTYPE_STRVEC, strlen + 1);
280 memcpy (token, start, strlen);
281 *(token + strlen) = '\0';
282 vector_set (strvec, token);
283
284 while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r') &&
285 *cp != '\0')
286 cp++;
287
288 if (*cp == '\0')
289 return strvec;
290 }
291}
292
293/* Free allocated string vector. */
294void
295cmd_free_strvec (vector v)
296{
hasso8c328f12004-10-05 21:01:23 +0000297 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000298 char *cp;
299
300 if (!v)
301 return;
302
303 for (i = 0; i < vector_max (v); i++)
304 if ((cp = vector_slot (v, i)) != NULL)
305 XFREE (MTYPE_STRVEC, cp);
306
307 vector_free (v);
308}
309
310/* Fetch next description. Used in cmd_make_descvec(). */
ajs274a4a42004-12-07 15:39:31 +0000311static char *
hasso6ad96ea2004-10-07 19:33:46 +0000312cmd_desc_str (const char **string)
paul718e3742002-12-13 20:15:29 +0000313{
hasso6ad96ea2004-10-07 19:33:46 +0000314 const char *cp, *start;
315 char *token;
paul718e3742002-12-13 20:15:29 +0000316 int strlen;
317
318 cp = *string;
319
320 if (cp == NULL)
321 return NULL;
322
323 /* Skip white spaces. */
324 while (isspace ((int) *cp) && *cp != '\0')
325 cp++;
326
327 /* Return if there is only white spaces */
328 if (*cp == '\0')
329 return NULL;
330
331 start = cp;
332
333 while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
334 cp++;
335
336 strlen = cp - start;
337 token = XMALLOC (MTYPE_STRVEC, strlen + 1);
338 memcpy (token, start, strlen);
339 *(token + strlen) = '\0';
340
341 *string = cp;
342
343 return token;
344}
345
346/* New string vector. */
ajs274a4a42004-12-07 15:39:31 +0000347static vector
hasso8c328f12004-10-05 21:01:23 +0000348cmd_make_descvec (const char *string, const char *descstr)
paul718e3742002-12-13 20:15:29 +0000349{
350 int multiple = 0;
hasso8c328f12004-10-05 21:01:23 +0000351 const char *sp;
paul718e3742002-12-13 20:15:29 +0000352 char *token;
353 int len;
hasso8c328f12004-10-05 21:01:23 +0000354 const char *cp;
355 const char *dp;
paul718e3742002-12-13 20:15:29 +0000356 vector allvec;
357 vector strvec = NULL;
358 struct desc *desc;
359
360 cp = string;
361 dp = descstr;
362
363 if (cp == NULL)
364 return NULL;
365
366 allvec = vector_init (VECTOR_MIN_SIZE);
367
368 while (1)
369 {
370 while (isspace ((int) *cp) && *cp != '\0')
371 cp++;
372
373 if (*cp == '(')
374 {
375 multiple = 1;
376 cp++;
377 }
378 if (*cp == ')')
379 {
380 multiple = 0;
381 cp++;
382 }
383 if (*cp == '|')
384 {
385 if (! multiple)
386 {
387 fprintf (stderr, "Command parse error!: %s\n", string);
388 exit (1);
389 }
390 cp++;
391 }
392
393 while (isspace ((int) *cp) && *cp != '\0')
394 cp++;
395
396 if (*cp == '(')
397 {
398 multiple = 1;
399 cp++;
400 }
401
402 if (*cp == '\0')
403 return allvec;
404
405 sp = cp;
406
407 while (! (isspace ((int) *cp) || *cp == '\r' || *cp == '\n' || *cp == ')' || *cp == '|') && *cp != '\0')
408 cp++;
409
410 len = cp - sp;
411
412 token = XMALLOC (MTYPE_STRVEC, len + 1);
413 memcpy (token, sp, len);
414 *(token + len) = '\0';
415
416 desc = XCALLOC (MTYPE_DESC, sizeof (struct desc));
417 desc->cmd = token;
418 desc->str = cmd_desc_str (&dp);
419
420 if (multiple)
421 {
422 if (multiple == 1)
423 {
424 strvec = vector_init (VECTOR_MIN_SIZE);
425 vector_set (allvec, strvec);
426 }
427 multiple++;
428 }
429 else
430 {
431 strvec = vector_init (VECTOR_MIN_SIZE);
432 vector_set (allvec, strvec);
433 }
434 vector_set (strvec, desc);
435 }
436}
437
438/* Count mandantory string vector size. This is to determine inputed
439 command has enough command length. */
ajs274a4a42004-12-07 15:39:31 +0000440static int
paul718e3742002-12-13 20:15:29 +0000441cmd_cmdsize (vector strvec)
442{
hasso8c328f12004-10-05 21:01:23 +0000443 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000444 int size = 0;
445 vector descvec;
446
447 for (i = 0; i < vector_max (strvec); i++)
448 {
449 descvec = vector_slot (strvec, i);
450
451 if (vector_max (descvec) == 1)
452 {
453 struct desc *desc = vector_slot (descvec, 0);
454
hasso8c328f12004-10-05 21:01:23 +0000455 if (desc->cmd == NULL || CMD_OPTION (desc->cmd))
paul718e3742002-12-13 20:15:29 +0000456 return size;
457 else
458 size++;
459 }
460 else
461 size++;
462 }
463 return size;
464}
465
466/* Return prompt character of specified node. */
hasso8c328f12004-10-05 21:01:23 +0000467const char *
paul718e3742002-12-13 20:15:29 +0000468cmd_prompt (enum node_type node)
469{
470 struct cmd_node *cnode;
471
472 cnode = vector_slot (cmdvec, node);
473 return cnode->prompt;
474}
475
476/* Install a command into a node. */
477void
478install_element (enum node_type ntype, struct cmd_element *cmd)
479{
480 struct cmd_node *cnode;
481
482 cnode = vector_slot (cmdvec, ntype);
483
484 if (cnode == NULL)
485 {
486 fprintf (stderr, "Command node %d doesn't exist, please check it\n",
487 ntype);
488 exit (1);
489 }
490
491 vector_set (cnode->cmd_vector, cmd);
492
493 cmd->strvec = cmd_make_descvec (cmd->string, cmd->doc);
494 cmd->cmdsize = cmd_cmdsize (cmd->strvec);
495}
496
497static unsigned char itoa64[] =
498"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
499
ajs274a4a42004-12-07 15:39:31 +0000500static void
paul718e3742002-12-13 20:15:29 +0000501to64(char *s, long v, int n)
502{
503 while (--n >= 0)
504 {
505 *s++ = itoa64[v&0x3f];
506 v >>= 6;
507 }
508}
509
ajs274a4a42004-12-07 15:39:31 +0000510static char *
511zencrypt (const char *passwd)
paul718e3742002-12-13 20:15:29 +0000512{
513 char salt[6];
514 struct timeval tv;
515 char *crypt (const char *, const char *);
516
517 gettimeofday(&tv,0);
518
519 to64(&salt[0], random(), 3);
520 to64(&salt[3], tv.tv_usec, 3);
521 salt[5] = '\0';
522
523 return crypt (passwd, salt);
524}
525
526/* This function write configuration of this host. */
ajs274a4a42004-12-07 15:39:31 +0000527static int
paul718e3742002-12-13 20:15:29 +0000528config_write_host (struct vty *vty)
529{
530 if (host.name)
531 vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE);
532
533 if (host.encrypt)
534 {
535 if (host.password_encrypt)
536 vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE);
537 if (host.enable_encrypt)
538 vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE);
539 }
540 else
541 {
542 if (host.password)
543 vty_out (vty, "password %s%s", host.password, VTY_NEWLINE);
544 if (host.enable)
545 vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE);
546 }
547
ajs274a4a42004-12-07 15:39:31 +0000548 if (zlog_default->default_lvl != LOG_DEBUG)
549 vty_out (vty, "log trap %s%s",
550 zlog_priority[zlog_default->default_lvl], VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000551
ajs274a4a42004-12-07 15:39:31 +0000552 if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED))
paul12ab19f2003-07-26 06:14:55 +0000553 {
ajs274a4a42004-12-07 15:39:31 +0000554 vty_out (vty, "log file %s", host.logfile);
555 if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl)
556 vty_out (vty, " %s",
557 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]);
paul12ab19f2003-07-26 06:14:55 +0000558 vty_out (vty, "%s", VTY_NEWLINE);
559 }
ajs274a4a42004-12-07 15:39:31 +0000560
561 if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED)
562 {
563 vty_out (vty, "log stdout");
564 if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl)
565 vty_out (vty, " %s",
566 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]);
567 vty_out (vty, "%s", VTY_NEWLINE);
568 }
569
570 if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
571 vty_out(vty,"no log monitor%s",VTY_NEWLINE);
572 else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl)
573 vty_out(vty,"log monitor %s%s",
574 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE);
575
576 if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED)
577 {
578 vty_out (vty, "log syslog");
579 if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl)
580 vty_out (vty, " %s",
581 zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]);
582 vty_out (vty, "%s", VTY_NEWLINE);
583 }
584
585 if (zlog_default->facility != LOG_DAEMON)
586 vty_out (vty, "log facility %s%s",
587 facility_name(zlog_default->facility), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000588
589 if (zlog_default->record_priority == 1)
590 vty_out (vty, "log record-priority%s", VTY_NEWLINE);
591
592 if (host.advanced)
593 vty_out (vty, "service advanced-vty%s", VTY_NEWLINE);
594
595 if (host.encrypt)
596 vty_out (vty, "service password-encryption%s", VTY_NEWLINE);
597
598 if (host.lines >= 0)
599 vty_out (vty, "service terminal-length %d%s", host.lines,
600 VTY_NEWLINE);
601
602 if (! host.motd)
603 vty_out (vty, "no banner motd%s", VTY_NEWLINE);
604
605 return 1;
606}
607
608/* Utility function for getting command vector. */
ajs274a4a42004-12-07 15:39:31 +0000609static vector
paul718e3742002-12-13 20:15:29 +0000610cmd_node_vector (vector v, enum node_type ntype)
611{
612 struct cmd_node *cnode = vector_slot (v, ntype);
613 return cnode->cmd_vector;
614}
615
ajs274a4a42004-12-07 15:39:31 +0000616#if 0
617/* Filter command vector by symbol. This function is not actually used;
618 * should it be deleted? */
619static int
paul718e3742002-12-13 20:15:29 +0000620cmd_filter_by_symbol (char *command, char *symbol)
621{
622 int i, lim;
623
624 if (strcmp (symbol, "IPV4_ADDRESS") == 0)
625 {
626 i = 0;
627 lim = strlen (command);
628 while (i < lim)
629 {
630 if (! (isdigit ((int) command[i]) || command[i] == '.' || command[i] == '/'))
631 return 1;
632 i++;
633 }
634 return 0;
635 }
636 if (strcmp (symbol, "STRING") == 0)
637 {
638 i = 0;
639 lim = strlen (command);
640 while (i < lim)
641 {
642 if (! (isalpha ((int) command[i]) || command[i] == '_' || command[i] == '-'))
643 return 1;
644 i++;
645 }
646 return 0;
647 }
648 if (strcmp (symbol, "IFNAME") == 0)
649 {
650 i = 0;
651 lim = strlen (command);
652 while (i < lim)
653 {
654 if (! isalnum ((int) command[i]))
655 return 1;
656 i++;
657 }
658 return 0;
659 }
660 return 0;
661}
ajs274a4a42004-12-07 15:39:31 +0000662#endif
paul718e3742002-12-13 20:15:29 +0000663
664/* Completion match types. */
665enum match_type
666{
667 no_match,
668 extend_match,
669 ipv4_prefix_match,
670 ipv4_match,
671 ipv6_prefix_match,
672 ipv6_match,
673 range_match,
674 vararg_match,
675 partly_match,
676 exact_match
677};
678
ajs274a4a42004-12-07 15:39:31 +0000679static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000680cmd_ipv4_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000681{
hasso8c328f12004-10-05 21:01:23 +0000682 const char *sp;
paul718e3742002-12-13 20:15:29 +0000683 int dots = 0, nums = 0;
684 char buf[4];
685
686 if (str == NULL)
687 return partly_match;
688
689 for (;;)
690 {
691 memset (buf, 0, sizeof (buf));
692 sp = str;
693 while (*str != '\0')
694 {
695 if (*str == '.')
696 {
697 if (dots >= 3)
698 return no_match;
699
700 if (*(str + 1) == '.')
701 return no_match;
702
703 if (*(str + 1) == '\0')
704 return partly_match;
705
706 dots++;
707 break;
708 }
709 if (!isdigit ((int) *str))
710 return no_match;
711
712 str++;
713 }
714
715 if (str - sp > 3)
716 return no_match;
717
718 strncpy (buf, sp, str - sp);
719 if (atoi (buf) > 255)
720 return no_match;
721
722 nums++;
723
724 if (*str == '\0')
725 break;
726
727 str++;
728 }
729
730 if (nums < 4)
731 return partly_match;
732
733 return exact_match;
734}
735
ajs274a4a42004-12-07 15:39:31 +0000736static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000737cmd_ipv4_prefix_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000738{
hasso8c328f12004-10-05 21:01:23 +0000739 const char *sp;
paul718e3742002-12-13 20:15:29 +0000740 int dots = 0;
741 char buf[4];
742
743 if (str == NULL)
744 return partly_match;
745
746 for (;;)
747 {
748 memset (buf, 0, sizeof (buf));
749 sp = str;
750 while (*str != '\0' && *str != '/')
751 {
752 if (*str == '.')
753 {
754 if (dots == 3)
755 return no_match;
756
757 if (*(str + 1) == '.' || *(str + 1) == '/')
758 return no_match;
759
760 if (*(str + 1) == '\0')
761 return partly_match;
762
763 dots++;
764 break;
765 }
766
767 if (!isdigit ((int) *str))
768 return no_match;
769
770 str++;
771 }
772
773 if (str - sp > 3)
774 return no_match;
775
776 strncpy (buf, sp, str - sp);
777 if (atoi (buf) > 255)
778 return no_match;
779
780 if (dots == 3)
781 {
782 if (*str == '/')
783 {
784 if (*(str + 1) == '\0')
785 return partly_match;
786
787 str++;
788 break;
789 }
790 else if (*str == '\0')
791 return partly_match;
792 }
793
794 if (*str == '\0')
795 return partly_match;
796
797 str++;
798 }
799
800 sp = str;
801 while (*str != '\0')
802 {
803 if (!isdigit ((int) *str))
804 return no_match;
805
806 str++;
807 }
808
809 if (atoi (sp) > 32)
810 return no_match;
811
812 return exact_match;
813}
814
815#define IPV6_ADDR_STR "0123456789abcdefABCDEF:.%"
816#define IPV6_PREFIX_STR "0123456789abcdefABCDEF:.%/"
817#define STATE_START 1
818#define STATE_COLON 2
819#define STATE_DOUBLE 3
820#define STATE_ADDR 4
821#define STATE_DOT 5
822#define STATE_SLASH 6
823#define STATE_MASK 7
824
paul22e0a9e2003-07-11 17:55:46 +0000825#ifdef HAVE_IPV6
826
ajs274a4a42004-12-07 15:39:31 +0000827static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000828cmd_ipv6_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000829{
830 int state = STATE_START;
831 int colons = 0, nums = 0, double_colon = 0;
hasso8c328f12004-10-05 21:01:23 +0000832 const char *sp = NULL;
hasso726f9b22003-05-25 21:04:54 +0000833 struct sockaddr_in6 sin6_dummy;
834 int ret;
paul718e3742002-12-13 20:15:29 +0000835
836 if (str == NULL)
837 return partly_match;
838
839 if (strspn (str, IPV6_ADDR_STR) != strlen (str))
840 return no_match;
841
hasso726f9b22003-05-25 21:04:54 +0000842 /* use inet_pton that has a better support,
843 * for example inet_pton can support the automatic addresses:
844 * ::1.2.3.4
845 */
846 ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
847
848 if (ret == 1)
849 return exact_match;
850
paul718e3742002-12-13 20:15:29 +0000851 while (*str != '\0')
852 {
853 switch (state)
854 {
855 case STATE_START:
856 if (*str == ':')
857 {
858 if (*(str + 1) != ':' && *(str + 1) != '\0')
859 return no_match;
860 colons--;
861 state = STATE_COLON;
862 }
863 else
864 {
865 sp = str;
866 state = STATE_ADDR;
867 }
868
869 continue;
870 case STATE_COLON:
871 colons++;
872 if (*(str + 1) == ':')
873 state = STATE_DOUBLE;
874 else
875 {
876 sp = str + 1;
877 state = STATE_ADDR;
878 }
879 break;
880 case STATE_DOUBLE:
881 if (double_colon)
882 return no_match;
883
884 if (*(str + 1) == ':')
885 return no_match;
886 else
887 {
888 if (*(str + 1) != '\0')
889 colons++;
890 sp = str + 1;
891 state = STATE_ADDR;
892 }
893
894 double_colon++;
895 nums++;
896 break;
897 case STATE_ADDR:
898 if (*(str + 1) == ':' || *(str + 1) == '\0')
899 {
900 if (str - sp > 3)
901 return no_match;
902
903 nums++;
904 state = STATE_COLON;
905 }
906 if (*(str + 1) == '.')
907 state = STATE_DOT;
908 break;
909 case STATE_DOT:
910 state = STATE_ADDR;
911 break;
912 default:
913 break;
914 }
915
916 if (nums > 8)
917 return no_match;
918
919 if (colons > 7)
920 return no_match;
921
922 str++;
923 }
924
925#if 0
926 if (nums < 11)
927 return partly_match;
928#endif /* 0 */
929
930 return exact_match;
931}
932
ajs274a4a42004-12-07 15:39:31 +0000933static enum match_type
hasso8c328f12004-10-05 21:01:23 +0000934cmd_ipv6_prefix_match (const char *str)
paul718e3742002-12-13 20:15:29 +0000935{
936 int state = STATE_START;
937 int colons = 0, nums = 0, double_colon = 0;
938 int mask;
hasso8c328f12004-10-05 21:01:23 +0000939 const char *sp = NULL;
paul718e3742002-12-13 20:15:29 +0000940 char *endptr = NULL;
941
942 if (str == NULL)
943 return partly_match;
944
945 if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
946 return no_match;
947
948 while (*str != '\0' && state != STATE_MASK)
949 {
950 switch (state)
951 {
952 case STATE_START:
953 if (*str == ':')
954 {
955 if (*(str + 1) != ':' && *(str + 1) != '\0')
956 return no_match;
957 colons--;
958 state = STATE_COLON;
959 }
960 else
961 {
962 sp = str;
963 state = STATE_ADDR;
964 }
965
966 continue;
967 case STATE_COLON:
968 colons++;
969 if (*(str + 1) == '/')
970 return no_match;
971 else if (*(str + 1) == ':')
972 state = STATE_DOUBLE;
973 else
974 {
975 sp = str + 1;
976 state = STATE_ADDR;
977 }
978 break;
979 case STATE_DOUBLE:
980 if (double_colon)
981 return no_match;
982
983 if (*(str + 1) == ':')
984 return no_match;
985 else
986 {
987 if (*(str + 1) != '\0' && *(str + 1) != '/')
988 colons++;
989 sp = str + 1;
990
991 if (*(str + 1) == '/')
992 state = STATE_SLASH;
993 else
994 state = STATE_ADDR;
995 }
996
997 double_colon++;
998 nums += 1;
999 break;
1000 case STATE_ADDR:
1001 if (*(str + 1) == ':' || *(str + 1) == '.'
1002 || *(str + 1) == '\0' || *(str + 1) == '/')
1003 {
1004 if (str - sp > 3)
1005 return no_match;
1006
1007 for (; sp <= str; sp++)
1008 if (*sp == '/')
1009 return no_match;
1010
1011 nums++;
1012
1013 if (*(str + 1) == ':')
1014 state = STATE_COLON;
1015 else if (*(str + 1) == '.')
1016 state = STATE_DOT;
1017 else if (*(str + 1) == '/')
1018 state = STATE_SLASH;
1019 }
1020 break;
1021 case STATE_DOT:
1022 state = STATE_ADDR;
1023 break;
1024 case STATE_SLASH:
1025 if (*(str + 1) == '\0')
1026 return partly_match;
1027
1028 state = STATE_MASK;
1029 break;
1030 default:
1031 break;
1032 }
1033
1034 if (nums > 11)
1035 return no_match;
1036
1037 if (colons > 7)
1038 return no_match;
1039
1040 str++;
1041 }
1042
1043 if (state < STATE_MASK)
1044 return partly_match;
1045
1046 mask = strtol (str, &endptr, 10);
1047 if (*endptr != '\0')
1048 return no_match;
1049
1050 if (mask < 0 || mask > 128)
1051 return no_match;
1052
1053/* I don't know why mask < 13 makes command match partly.
1054 Forgive me to make this comments. I Want to set static default route
1055 because of lack of function to originate default in ospf6d; sorry
1056 yasu
1057 if (mask < 13)
1058 return partly_match;
1059*/
1060
1061 return exact_match;
1062}
1063
paul22e0a9e2003-07-11 17:55:46 +00001064#endif /* HAVE_IPV6 */
1065
paul718e3742002-12-13 20:15:29 +00001066#define DECIMAL_STRLEN_MAX 10
1067
ajs274a4a42004-12-07 15:39:31 +00001068static int
hasso8c328f12004-10-05 21:01:23 +00001069cmd_range_match (const char *range, const char *str)
paul718e3742002-12-13 20:15:29 +00001070{
1071 char *p;
1072 char buf[DECIMAL_STRLEN_MAX + 1];
1073 char *endptr = NULL;
1074 unsigned long min, max, val;
1075
1076 if (str == NULL)
1077 return 1;
1078
1079 val = strtoul (str, &endptr, 10);
1080 if (*endptr != '\0')
1081 return 0;
1082
1083 range++;
1084 p = strchr (range, '-');
1085 if (p == NULL)
1086 return 0;
1087 if (p - range > DECIMAL_STRLEN_MAX)
1088 return 0;
1089 strncpy (buf, range, p - range);
1090 buf[p - range] = '\0';
1091 min = strtoul (buf, &endptr, 10);
1092 if (*endptr != '\0')
1093 return 0;
1094
1095 range = p + 1;
1096 p = strchr (range, '>');
1097 if (p == NULL)
1098 return 0;
1099 if (p - range > DECIMAL_STRLEN_MAX)
1100 return 0;
1101 strncpy (buf, range, p - range);
1102 buf[p - range] = '\0';
1103 max = strtoul (buf, &endptr, 10);
1104 if (*endptr != '\0')
1105 return 0;
1106
1107 if (val < min || val > max)
1108 return 0;
1109
1110 return 1;
1111}
1112
1113/* Make completion match and return match type flag. */
ajs274a4a42004-12-07 15:39:31 +00001114static enum match_type
hasso8c328f12004-10-05 21:01:23 +00001115cmd_filter_by_completion (char *command, vector v, unsigned int index)
paul718e3742002-12-13 20:15:29 +00001116{
hasso8c328f12004-10-05 21:01:23 +00001117 unsigned int i;
1118 const char *str;
paul718e3742002-12-13 20:15:29 +00001119 struct cmd_element *cmd_element;
1120 enum match_type match_type;
1121 vector descvec;
1122 struct desc *desc;
1123
1124 match_type = no_match;
1125
1126 /* If command and cmd_element string does not match set NULL to vector */
1127 for (i = 0; i < vector_max (v); i++)
1128 if ((cmd_element = vector_slot (v, i)) != NULL)
1129 {
1130 if (index >= vector_max (cmd_element->strvec))
1131 vector_slot (v, i) = NULL;
1132 else
1133 {
hasso8c328f12004-10-05 21:01:23 +00001134 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001135 int matched = 0;
1136
1137 descvec = vector_slot (cmd_element->strvec, index);
1138
1139 for (j = 0; j < vector_max (descvec); j++)
1140 {
1141 desc = vector_slot (descvec, j);
1142 str = desc->cmd;
1143
1144 if (CMD_VARARG (str))
1145 {
1146 if (match_type < vararg_match)
1147 match_type = vararg_match;
1148 matched++;
1149 }
1150 else if (CMD_RANGE (str))
1151 {
1152 if (cmd_range_match (str, command))
1153 {
1154 if (match_type < range_match)
1155 match_type = range_match;
1156
1157 matched++;
1158 }
1159 }
paul22e0a9e2003-07-11 17:55:46 +00001160#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001161 else if (CMD_IPV6 (str))
1162 {
1163 if (cmd_ipv6_match (command))
1164 {
1165 if (match_type < ipv6_match)
1166 match_type = ipv6_match;
1167
1168 matched++;
1169 }
1170 }
1171 else if (CMD_IPV6_PREFIX (str))
1172 {
1173 if (cmd_ipv6_prefix_match (command))
1174 {
1175 if (match_type < ipv6_prefix_match)
1176 match_type = ipv6_prefix_match;
1177
1178 matched++;
1179 }
1180 }
paul22e0a9e2003-07-11 17:55:46 +00001181#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001182 else if (CMD_IPV4 (str))
1183 {
1184 if (cmd_ipv4_match (command))
1185 {
1186 if (match_type < ipv4_match)
1187 match_type = ipv4_match;
1188
1189 matched++;
1190 }
1191 }
1192 else if (CMD_IPV4_PREFIX (str))
1193 {
1194 if (cmd_ipv4_prefix_match (command))
1195 {
1196 if (match_type < ipv4_prefix_match)
1197 match_type = ipv4_prefix_match;
1198 matched++;
1199 }
1200 }
1201 else
1202 /* Check is this point's argument optional ? */
1203 if (CMD_OPTION (str) || CMD_VARIABLE (str))
1204 {
1205 if (match_type < extend_match)
1206 match_type = extend_match;
1207 matched++;
1208 }
1209 else if (strncmp (command, str, strlen (command)) == 0)
1210 {
1211 if (strcmp (command, str) == 0)
1212 match_type = exact_match;
1213 else
1214 {
1215 if (match_type < partly_match)
1216 match_type = partly_match;
1217 }
1218 matched++;
1219 }
1220 }
1221 if (! matched)
1222 vector_slot (v, i) = NULL;
1223 }
1224 }
1225 return match_type;
1226}
1227
1228/* Filter vector by command character with index. */
ajs274a4a42004-12-07 15:39:31 +00001229static enum match_type
hasso8c328f12004-10-05 21:01:23 +00001230cmd_filter_by_string (char *command, vector v, unsigned int index)
paul718e3742002-12-13 20:15:29 +00001231{
hasso8c328f12004-10-05 21:01:23 +00001232 unsigned int i;
1233 const char *str;
paul718e3742002-12-13 20:15:29 +00001234 struct cmd_element *cmd_element;
1235 enum match_type match_type;
1236 vector descvec;
1237 struct desc *desc;
1238
1239 match_type = no_match;
1240
1241 /* If command and cmd_element string does not match set NULL to vector */
1242 for (i = 0; i < vector_max (v); i++)
1243 if ((cmd_element = vector_slot (v, i)) != NULL)
1244 {
1245 /* If given index is bigger than max string vector of command,
1246 set NULL*/
1247 if (index >= vector_max (cmd_element->strvec))
1248 vector_slot (v, i) = NULL;
1249 else
1250 {
hasso8c328f12004-10-05 21:01:23 +00001251 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001252 int matched = 0;
1253
1254 descvec = vector_slot (cmd_element->strvec, index);
1255
1256 for (j = 0; j < vector_max (descvec); j++)
1257 {
1258 desc = vector_slot (descvec, j);
1259 str = desc->cmd;
1260
1261 if (CMD_VARARG (str))
1262 {
1263 if (match_type < vararg_match)
1264 match_type = vararg_match;
1265 matched++;
1266 }
1267 else if (CMD_RANGE (str))
1268 {
1269 if (cmd_range_match (str, command))
1270 {
1271 if (match_type < range_match)
1272 match_type = range_match;
1273 matched++;
1274 }
1275 }
paul22e0a9e2003-07-11 17:55:46 +00001276#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001277 else if (CMD_IPV6 (str))
1278 {
1279 if (cmd_ipv6_match (command) == exact_match)
1280 {
1281 if (match_type < ipv6_match)
1282 match_type = ipv6_match;
1283 matched++;
1284 }
1285 }
1286 else if (CMD_IPV6_PREFIX (str))
1287 {
1288 if (cmd_ipv6_prefix_match (command) == exact_match)
1289 {
1290 if (match_type < ipv6_prefix_match)
1291 match_type = ipv6_prefix_match;
1292 matched++;
1293 }
1294 }
paul22e0a9e2003-07-11 17:55:46 +00001295#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001296 else if (CMD_IPV4 (str))
1297 {
1298 if (cmd_ipv4_match (command) == exact_match)
1299 {
1300 if (match_type < ipv4_match)
1301 match_type = ipv4_match;
1302 matched++;
1303 }
1304 }
1305 else if (CMD_IPV4_PREFIX (str))
1306 {
1307 if (cmd_ipv4_prefix_match (command) == exact_match)
1308 {
1309 if (match_type < ipv4_prefix_match)
1310 match_type = ipv4_prefix_match;
1311 matched++;
1312 }
1313 }
1314 else if (CMD_OPTION (str) || CMD_VARIABLE (str))
1315 {
1316 if (match_type < extend_match)
1317 match_type = extend_match;
1318 matched++;
1319 }
1320 else
1321 {
1322 if (strcmp (command, str) == 0)
1323 {
1324 match_type = exact_match;
1325 matched++;
1326 }
1327 }
1328 }
1329 if (! matched)
1330 vector_slot (v, i) = NULL;
1331 }
1332 }
1333 return match_type;
1334}
1335
1336/* Check ambiguous match */
ajs274a4a42004-12-07 15:39:31 +00001337static int
paul718e3742002-12-13 20:15:29 +00001338is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
1339{
hasso8c328f12004-10-05 21:01:23 +00001340 unsigned int i;
1341 unsigned int j;
1342 const char *str = NULL;
paul718e3742002-12-13 20:15:29 +00001343 struct cmd_element *cmd_element;
hasso8c328f12004-10-05 21:01:23 +00001344 const char *matched = NULL;
paul718e3742002-12-13 20:15:29 +00001345 vector descvec;
1346 struct desc *desc;
1347
1348 for (i = 0; i < vector_max (v); i++)
1349 if ((cmd_element = vector_slot (v, i)) != NULL)
1350 {
1351 int match = 0;
1352
1353 descvec = vector_slot (cmd_element->strvec, index);
1354
1355 for (j = 0; j < vector_max (descvec); j++)
1356 {
1357 enum match_type ret;
1358
1359 desc = vector_slot (descvec, j);
1360 str = desc->cmd;
1361
1362 switch (type)
1363 {
1364 case exact_match:
1365 if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
1366 && strcmp (command, str) == 0)
1367 match++;
1368 break;
1369 case partly_match:
1370 if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
1371 && strncmp (command, str, strlen (command)) == 0)
1372 {
1373 if (matched && strcmp (matched, str) != 0)
1374 return 1; /* There is ambiguous match. */
1375 else
1376 matched = str;
1377 match++;
1378 }
1379 break;
1380 case range_match:
1381 if (cmd_range_match (str, command))
1382 {
1383 if (matched && strcmp (matched, str) != 0)
1384 return 1;
1385 else
1386 matched = str;
1387 match++;
1388 }
1389 break;
paul22e0a9e2003-07-11 17:55:46 +00001390#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001391 case ipv6_match:
1392 if (CMD_IPV6 (str))
1393 match++;
1394 break;
1395 case ipv6_prefix_match:
1396 if ((ret = cmd_ipv6_prefix_match (command)) != no_match)
1397 {
1398 if (ret == partly_match)
1399 return 2; /* There is incomplete match. */
1400
1401 match++;
1402 }
1403 break;
paul22e0a9e2003-07-11 17:55:46 +00001404#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001405 case ipv4_match:
1406 if (CMD_IPV4 (str))
1407 match++;
1408 break;
1409 case ipv4_prefix_match:
1410 if ((ret = cmd_ipv4_prefix_match (command)) != no_match)
1411 {
1412 if (ret == partly_match)
1413 return 2; /* There is incomplete match. */
1414
1415 match++;
1416 }
1417 break;
1418 case extend_match:
1419 if (CMD_OPTION (str) || CMD_VARIABLE (str))
1420 match++;
1421 break;
1422 case no_match:
1423 default:
1424 break;
1425 }
1426 }
1427 if (! match)
1428 vector_slot (v, i) = NULL;
1429 }
1430 return 0;
1431}
1432
1433/* If src matches dst return dst string, otherwise return NULL */
ajs274a4a42004-12-07 15:39:31 +00001434static const char *
hasso8c328f12004-10-05 21:01:23 +00001435cmd_entry_function (const char *src, const char *dst)
paul718e3742002-12-13 20:15:29 +00001436{
1437 /* Skip variable arguments. */
1438 if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) ||
1439 CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst))
1440 return NULL;
1441
1442 /* In case of 'command \t', given src is NULL string. */
1443 if (src == NULL)
1444 return dst;
1445
1446 /* Matched with input string. */
1447 if (strncmp (src, dst, strlen (src)) == 0)
1448 return dst;
1449
1450 return NULL;
1451}
1452
1453/* If src matches dst return dst string, otherwise return NULL */
1454/* This version will return the dst string always if it is
1455 CMD_VARIABLE for '?' key processing */
ajs274a4a42004-12-07 15:39:31 +00001456static const char *
hasso8c328f12004-10-05 21:01:23 +00001457cmd_entry_function_desc (const char *src, const char *dst)
paul718e3742002-12-13 20:15:29 +00001458{
1459 if (CMD_VARARG (dst))
1460 return dst;
1461
1462 if (CMD_RANGE (dst))
1463 {
1464 if (cmd_range_match (dst, src))
1465 return dst;
1466 else
1467 return NULL;
1468 }
1469
paul22e0a9e2003-07-11 17:55:46 +00001470#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +00001471 if (CMD_IPV6 (dst))
1472 {
1473 if (cmd_ipv6_match (src))
1474 return dst;
1475 else
1476 return NULL;
1477 }
1478
1479 if (CMD_IPV6_PREFIX (dst))
1480 {
1481 if (cmd_ipv6_prefix_match (src))
1482 return dst;
1483 else
1484 return NULL;
1485 }
paul22e0a9e2003-07-11 17:55:46 +00001486#endif /* HAVE_IPV6 */
paul718e3742002-12-13 20:15:29 +00001487
1488 if (CMD_IPV4 (dst))
1489 {
1490 if (cmd_ipv4_match (src))
1491 return dst;
1492 else
1493 return NULL;
1494 }
1495
1496 if (CMD_IPV4_PREFIX (dst))
1497 {
1498 if (cmd_ipv4_prefix_match (src))
1499 return dst;
1500 else
1501 return NULL;
1502 }
1503
1504 /* Optional or variable commands always match on '?' */
1505 if (CMD_OPTION (dst) || CMD_VARIABLE (dst))
1506 return dst;
1507
1508 /* In case of 'command \t', given src is NULL string. */
1509 if (src == NULL)
1510 return dst;
1511
1512 if (strncmp (src, dst, strlen (src)) == 0)
1513 return dst;
1514 else
1515 return NULL;
1516}
1517
1518/* Check same string element existence. If it isn't there return
1519 1. */
ajs274a4a42004-12-07 15:39:31 +00001520static int
hasso8c328f12004-10-05 21:01:23 +00001521cmd_unique_string (vector v, const char *str)
paul718e3742002-12-13 20:15:29 +00001522{
hasso8c328f12004-10-05 21:01:23 +00001523 unsigned int i;
paul718e3742002-12-13 20:15:29 +00001524 char *match;
1525
1526 for (i = 0; i < vector_max (v); i++)
1527 if ((match = vector_slot (v, i)) != NULL)
1528 if (strcmp (match, str) == 0)
1529 return 0;
1530 return 1;
1531}
1532
1533/* Compare string to description vector. If there is same string
1534 return 1 else return 0. */
ajs274a4a42004-12-07 15:39:31 +00001535static int
hasso8c328f12004-10-05 21:01:23 +00001536desc_unique_string (vector v, const char *str)
paul718e3742002-12-13 20:15:29 +00001537{
hasso8c328f12004-10-05 21:01:23 +00001538 unsigned int i;
paul718e3742002-12-13 20:15:29 +00001539 struct desc *desc;
1540
1541 for (i = 0; i < vector_max (v); i++)
1542 if ((desc = vector_slot (v, i)) != NULL)
1543 if (strcmp (desc->cmd, str) == 0)
1544 return 1;
1545 return 0;
1546}
1547
ajs274a4a42004-12-07 15:39:31 +00001548static int
paulb92938a2002-12-13 21:20:42 +00001549cmd_try_do_shortcut (enum node_type node, char* first_word) {
1550 if ( first_word != NULL &&
1551 node != AUTH_NODE &&
1552 node != VIEW_NODE &&
1553 node != AUTH_ENABLE_NODE &&
1554 node != ENABLE_NODE &&
1555 0 == strcmp( "do", first_word ) )
1556 return 1;
1557 return 0;
1558}
1559
paul718e3742002-12-13 20:15:29 +00001560/* '?' describe command support. */
ajs274a4a42004-12-07 15:39:31 +00001561static vector
paulb92938a2002-12-13 21:20:42 +00001562cmd_describe_command_real (vector vline, struct vty *vty, int *status)
paul718e3742002-12-13 20:15:29 +00001563{
hasso8c328f12004-10-05 21:01:23 +00001564 unsigned int i;
paul718e3742002-12-13 20:15:29 +00001565 vector cmd_vector;
1566#define INIT_MATCHVEC_SIZE 10
1567 vector matchvec;
1568 struct cmd_element *cmd_element;
hasso8c328f12004-10-05 21:01:23 +00001569 unsigned int index;
paul54aba542003-08-21 20:28:24 +00001570 int ret;
1571 enum match_type match;
1572 char *command;
paul718e3742002-12-13 20:15:29 +00001573 static struct desc desc_cr = { "<cr>", "" };
1574
1575 /* Set index. */
1576 index = vector_max (vline) - 1;
1577
1578 /* Make copy vector of current node's command vector. */
1579 cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1580
1581 /* Prepare match vector */
1582 matchvec = vector_init (INIT_MATCHVEC_SIZE);
1583
1584 /* Filter commands. */
paul54aba542003-08-21 20:28:24 +00001585 /* Only words precedes current word will be checked in this loop. */
paul718e3742002-12-13 20:15:29 +00001586 for (i = 0; i < index; i++)
1587 {
paul718e3742002-12-13 20:15:29 +00001588 command = vector_slot (vline, i);
paul718e3742002-12-13 20:15:29 +00001589 match = cmd_filter_by_completion (command, cmd_vector, i);
1590
1591 if (match == vararg_match)
1592 {
1593 struct cmd_element *cmd_element;
1594 vector descvec;
hasso8c328f12004-10-05 21:01:23 +00001595 unsigned int j, k;
paul718e3742002-12-13 20:15:29 +00001596
1597 for (j = 0; j < vector_max (cmd_vector); j++)
1598 if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
1599 {
1600 descvec = vector_slot (cmd_element->strvec,
1601 vector_max (cmd_element->strvec) - 1);
1602 for (k = 0; k < vector_max (descvec); k++)
1603 {
1604 struct desc *desc = vector_slot (descvec, k);
1605 vector_set (matchvec, desc);
1606 }
1607 }
1608
1609 vector_set (matchvec, &desc_cr);
paul718e3742002-12-13 20:15:29 +00001610 vector_free (cmd_vector);
1611
1612 return matchvec;
1613 }
1614
1615 if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
1616 {
1617 vector_free (cmd_vector);
1618 *status = CMD_ERR_AMBIGUOUS;
1619 return NULL;
1620 }
1621 else if (ret == 2)
1622 {
1623 vector_free (cmd_vector);
1624 *status = CMD_ERR_NO_MATCH;
1625 return NULL;
1626 }
1627 }
1628
1629 /* Prepare match vector */
1630 /* matchvec = vector_init (INIT_MATCHVEC_SIZE); */
1631
paul54aba542003-08-21 20:28:24 +00001632 /* Make sure that cmd_vector is filtered based on current word */
1633 command = vector_slot (vline, index);
1634 if (command)
1635 match = cmd_filter_by_completion (command, cmd_vector, index);
1636
paul718e3742002-12-13 20:15:29 +00001637 /* Make description vector. */
1638 for (i = 0; i < vector_max (cmd_vector); i++)
1639 if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
1640 {
hasso8c328f12004-10-05 21:01:23 +00001641 const char *string = NULL;
paul718e3742002-12-13 20:15:29 +00001642 vector strvec = cmd_element->strvec;
1643
paul54aba542003-08-21 20:28:24 +00001644 /* if command is NULL, index may be equal to vector_max */
1645 if (command && index >= vector_max (strvec))
paul718e3742002-12-13 20:15:29 +00001646 vector_slot (cmd_vector, i) = NULL;
1647 else
1648 {
paul54aba542003-08-21 20:28:24 +00001649 /* Check if command is completed. */
1650 if (command == NULL && index == vector_max (strvec))
paul718e3742002-12-13 20:15:29 +00001651 {
1652 string = "<cr>";
1653 if (! desc_unique_string (matchvec, string))
1654 vector_set (matchvec, &desc_cr);
1655 }
1656 else
1657 {
hasso8c328f12004-10-05 21:01:23 +00001658 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001659 vector descvec = vector_slot (strvec, index);
1660 struct desc *desc;
1661
1662 for (j = 0; j < vector_max (descvec); j++)
1663 {
1664 desc = vector_slot (descvec, j);
paul54aba542003-08-21 20:28:24 +00001665 string = cmd_entry_function_desc (command, desc->cmd);
paul718e3742002-12-13 20:15:29 +00001666 if (string)
1667 {
1668 /* Uniqueness check */
1669 if (! desc_unique_string (matchvec, string))
1670 vector_set (matchvec, desc);
1671 }
1672 }
1673 }
1674 }
1675 }
1676 vector_free (cmd_vector);
1677
1678 if (vector_slot (matchvec, 0) == NULL)
1679 {
1680 vector_free (matchvec);
1681 *status= CMD_ERR_NO_MATCH;
1682 }
1683 else
1684 *status = CMD_SUCCESS;
1685
1686 return matchvec;
1687}
1688
paulb92938a2002-12-13 21:20:42 +00001689vector
1690cmd_describe_command (vector vline, struct vty *vty, int *status)
1691{
1692 vector ret;
1693
1694 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
1695 {
1696 enum node_type onode;
1697 vector shifted_vline;
hasso8c328f12004-10-05 21:01:23 +00001698 unsigned int index;
paulb92938a2002-12-13 21:20:42 +00001699
1700 onode = vty->node;
1701 vty->node = ENABLE_NODE;
1702 /* We can try it on enable node, cos' the vty is authenticated */
1703
1704 shifted_vline = vector_init (vector_count(vline));
1705 /* use memcpy? */
1706 for (index = 1; index < vector_max (vline); index++)
1707 {
1708 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
1709 }
1710
1711 ret = cmd_describe_command_real (shifted_vline, vty, status);
1712
1713 vector_free(shifted_vline);
1714 vty->node = onode;
1715 return ret;
1716 }
1717
1718
1719 return cmd_describe_command_real (vline, vty, status);
1720}
1721
1722
paul718e3742002-12-13 20:15:29 +00001723/* Check LCD of matched command. */
ajs274a4a42004-12-07 15:39:31 +00001724static int
paul718e3742002-12-13 20:15:29 +00001725cmd_lcd (char **matched)
1726{
1727 int i;
1728 int j;
1729 int lcd = -1;
1730 char *s1, *s2;
1731 char c1, c2;
1732
1733 if (matched[0] == NULL || matched[1] == NULL)
1734 return 0;
1735
1736 for (i = 1; matched[i] != NULL; i++)
1737 {
1738 s1 = matched[i - 1];
1739 s2 = matched[i];
1740
1741 for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
1742 if (c1 != c2)
1743 break;
1744
1745 if (lcd < 0)
1746 lcd = j;
1747 else
1748 {
1749 if (lcd > j)
1750 lcd = j;
1751 }
1752 }
1753 return lcd;
1754}
1755
1756/* Command line completion support. */
ajs274a4a42004-12-07 15:39:31 +00001757static char **
paulb92938a2002-12-13 21:20:42 +00001758cmd_complete_command_real (vector vline, struct vty *vty, int *status)
paul718e3742002-12-13 20:15:29 +00001759{
hasso8c328f12004-10-05 21:01:23 +00001760 unsigned int i;
paul718e3742002-12-13 20:15:29 +00001761 vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1762#define INIT_MATCHVEC_SIZE 10
1763 vector matchvec;
1764 struct cmd_element *cmd_element;
hasso8c328f12004-10-05 21:01:23 +00001765 unsigned int index = vector_max (vline) - 1;
paul718e3742002-12-13 20:15:29 +00001766 char **match_str;
1767 struct desc *desc;
1768 vector descvec;
1769 char *command;
1770 int lcd;
1771
1772 /* First, filter by preceeding command string */
1773 for (i = 0; i < index; i++)
1774 {
1775 enum match_type match;
1776 int ret;
1777
1778 command = vector_slot (vline, i);
1779
1780 /* First try completion match, if there is exactly match return 1 */
1781 match = cmd_filter_by_completion (command, cmd_vector, i);
1782
1783 /* If there is exact match then filter ambiguous match else check
1784 ambiguousness. */
1785 if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
1786 {
1787 vector_free (cmd_vector);
1788 *status = CMD_ERR_AMBIGUOUS;
1789 return NULL;
1790 }
1791 /*
1792 else if (ret == 2)
1793 {
1794 vector_free (cmd_vector);
1795 *status = CMD_ERR_NO_MATCH;
1796 return NULL;
1797 }
1798 */
1799 }
1800
1801 /* Prepare match vector. */
1802 matchvec = vector_init (INIT_MATCHVEC_SIZE);
1803
1804 /* Now we got into completion */
1805 for (i = 0; i < vector_max (cmd_vector); i++)
1806 if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
1807 {
hasso8c328f12004-10-05 21:01:23 +00001808 const char *string;
paul718e3742002-12-13 20:15:29 +00001809 vector strvec = cmd_element->strvec;
1810
1811 /* Check field length */
1812 if (index >= vector_max (strvec))
1813 vector_slot (cmd_vector, i) = NULL;
1814 else
1815 {
hasso8c328f12004-10-05 21:01:23 +00001816 unsigned int j;
paul718e3742002-12-13 20:15:29 +00001817
1818 descvec = vector_slot (strvec, index);
1819 for (j = 0; j < vector_max (descvec); j++)
1820 {
1821 desc = vector_slot (descvec, j);
1822
1823 if ((string = cmd_entry_function (vector_slot (vline, index),
1824 desc->cmd)))
1825 if (cmd_unique_string (matchvec, string))
1826 vector_set (matchvec, XSTRDUP (MTYPE_TMP, string));
1827 }
1828 }
1829 }
1830
1831 /* We don't need cmd_vector any more. */
1832 vector_free (cmd_vector);
1833
1834 /* No matched command */
1835 if (vector_slot (matchvec, 0) == NULL)
1836 {
1837 vector_free (matchvec);
1838
1839 /* In case of 'command \t' pattern. Do you need '?' command at
1840 the end of the line. */
1841 if (vector_slot (vline, index) == '\0')
1842 *status = CMD_ERR_NOTHING_TODO;
1843 else
1844 *status = CMD_ERR_NO_MATCH;
1845 return NULL;
1846 }
1847
1848 /* Only one matched */
1849 if (vector_slot (matchvec, 1) == NULL)
1850 {
1851 match_str = (char **) matchvec->index;
1852 vector_only_wrapper_free (matchvec);
1853 *status = CMD_COMPLETE_FULL_MATCH;
1854 return match_str;
1855 }
1856 /* Make it sure last element is NULL. */
1857 vector_set (matchvec, NULL);
1858
1859 /* Check LCD of matched strings. */
1860 if (vector_slot (vline, index) != NULL)
1861 {
1862 lcd = cmd_lcd ((char **) matchvec->index);
1863
1864 if (lcd)
1865 {
1866 int len = strlen (vector_slot (vline, index));
1867
1868 if (len < lcd)
1869 {
1870 char *lcdstr;
1871
1872 lcdstr = XMALLOC (MTYPE_TMP, lcd + 1);
1873 memcpy (lcdstr, matchvec->index[0], lcd);
1874 lcdstr[lcd] = '\0';
1875
1876 /* match_str = (char **) &lcdstr; */
1877
1878 /* Free matchvec. */
1879 for (i = 0; i < vector_max (matchvec); i++)
1880 {
1881 if (vector_slot (matchvec, i))
1882 XFREE (MTYPE_TMP, vector_slot (matchvec, i));
1883 }
1884 vector_free (matchvec);
1885
1886 /* Make new matchvec. */
1887 matchvec = vector_init (INIT_MATCHVEC_SIZE);
1888 vector_set (matchvec, lcdstr);
1889 match_str = (char **) matchvec->index;
1890 vector_only_wrapper_free (matchvec);
1891
1892 *status = CMD_COMPLETE_MATCH;
1893 return match_str;
1894 }
1895 }
1896 }
1897
1898 match_str = (char **) matchvec->index;
1899 vector_only_wrapper_free (matchvec);
1900 *status = CMD_COMPLETE_LIST_MATCH;
1901 return match_str;
1902}
1903
paulb92938a2002-12-13 21:20:42 +00001904char **
paul9ab68122003-01-18 01:16:20 +00001905cmd_complete_command (vector vline, struct vty *vty, int *status)
paulb92938a2002-12-13 21:20:42 +00001906{
1907 char **ret;
1908
1909 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
1910 {
1911 enum node_type onode;
1912 vector shifted_vline;
hasso8c328f12004-10-05 21:01:23 +00001913 unsigned int index;
paulb92938a2002-12-13 21:20:42 +00001914
1915 onode = vty->node;
1916 vty->node = ENABLE_NODE;
1917 /* We can try it on enable node, cos' the vty is authenticated */
1918
1919 shifted_vline = vector_init (vector_count(vline));
1920 /* use memcpy? */
1921 for (index = 1; index < vector_max (vline); index++)
1922 {
1923 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
1924 }
1925
1926 ret = cmd_complete_command_real (shifted_vline, vty, status);
1927
1928 vector_free(shifted_vline);
1929 vty->node = onode;
1930 return ret;
1931 }
1932
1933
1934 return cmd_complete_command_real (vline, vty, status);
1935}
1936
1937/* return parent node */
1938/* MUST eventually converge on CONFIG_NODE */
ajs274a4a42004-12-07 15:39:31 +00001939static enum node_type
1940node_parent ( enum node_type node )
paulb92938a2002-12-13 21:20:42 +00001941{
1942 enum node_type ret;
1943
paul9ab68122003-01-18 01:16:20 +00001944 assert (node > CONFIG_NODE);
1945
1946 switch (node)
1947 {
1948 case BGP_VPNV4_NODE:
1949 case BGP_IPV4_NODE:
1950 case BGP_IPV4M_NODE:
1951 case BGP_IPV6_NODE:
1952 ret = BGP_NODE;
1953 break;
1954 case KEYCHAIN_KEY_NODE:
1955 ret = KEYCHAIN_NODE;
1956 break;
1957 default:
1958 ret = CONFIG_NODE;
paulb92938a2002-12-13 21:20:42 +00001959 }
1960
1961 return ret;
1962}
1963
paul718e3742002-12-13 20:15:29 +00001964/* Execute command by argument vline vector. */
ajs274a4a42004-12-07 15:39:31 +00001965static int
paulb92938a2002-12-13 21:20:42 +00001966cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd)
paul718e3742002-12-13 20:15:29 +00001967{
hasso8c328f12004-10-05 21:01:23 +00001968 unsigned int i;
1969 unsigned int index;
paul718e3742002-12-13 20:15:29 +00001970 vector cmd_vector;
1971 struct cmd_element *cmd_element;
1972 struct cmd_element *matched_element;
1973 unsigned int matched_count, incomplete_count;
1974 int argc;
paul9035efa2004-10-10 11:56:56 +00001975 const char *argv[CMD_ARGC_MAX];
paul718e3742002-12-13 20:15:29 +00001976 enum match_type match = 0;
1977 int varflag;
1978 char *command;
1979
1980 /* Make copy of command elements. */
1981 cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
1982
1983 for (index = 0; index < vector_max (vline); index++)
1984 {
1985 int ret;
1986
1987 command = vector_slot (vline, index);
1988
1989 match = cmd_filter_by_completion (command, cmd_vector, index);
1990
1991 if (match == vararg_match)
1992 break;
1993
1994 ret = is_cmd_ambiguous (command, cmd_vector, index, match);
1995
1996 if (ret == 1)
1997 {
1998 vector_free (cmd_vector);
1999 return CMD_ERR_AMBIGUOUS;
2000 }
2001 else if (ret == 2)
2002 {
2003 vector_free (cmd_vector);
2004 return CMD_ERR_NO_MATCH;
2005 }
2006 }
2007
2008 /* Check matched count. */
2009 matched_element = NULL;
2010 matched_count = 0;
2011 incomplete_count = 0;
2012
2013 for (i = 0; i < vector_max (cmd_vector); i++)
2014 if (vector_slot (cmd_vector,i) != NULL)
2015 {
2016 cmd_element = vector_slot (cmd_vector,i);
2017
2018 if (match == vararg_match || index >= cmd_element->cmdsize)
2019 {
2020 matched_element = cmd_element;
2021#if 0
2022 printf ("DEBUG: %s\n", cmd_element->string);
2023#endif
2024 matched_count++;
2025 }
2026 else
2027 {
2028 incomplete_count++;
2029 }
2030 }
2031
2032 /* Finish of using cmd_vector. */
2033 vector_free (cmd_vector);
2034
2035 /* To execute command, matched_count must be 1.*/
2036 if (matched_count == 0)
2037 {
2038 if (incomplete_count)
2039 return CMD_ERR_INCOMPLETE;
2040 else
2041 return CMD_ERR_NO_MATCH;
2042 }
2043
2044 if (matched_count > 1)
2045 return CMD_ERR_AMBIGUOUS;
2046
2047 /* Argument treatment */
2048 varflag = 0;
2049 argc = 0;
2050
2051 for (i = 0; i < vector_max (vline); i++)
2052 {
2053 if (varflag)
2054 argv[argc++] = vector_slot (vline, i);
2055 else
2056 {
2057 vector descvec = vector_slot (matched_element->strvec, i);
2058
2059 if (vector_max (descvec) == 1)
2060 {
2061 struct desc *desc = vector_slot (descvec, 0);
paul718e3742002-12-13 20:15:29 +00002062
hasso8c328f12004-10-05 21:01:23 +00002063 if (CMD_VARARG (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002064 varflag = 1;
2065
hasso8c328f12004-10-05 21:01:23 +00002066 if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002067 argv[argc++] = vector_slot (vline, i);
2068 }
2069 else
2070 argv[argc++] = vector_slot (vline, i);
2071 }
2072
2073 if (argc >= CMD_ARGC_MAX)
2074 return CMD_ERR_EXEED_ARGC_MAX;
2075 }
2076
2077 /* For vtysh execution. */
2078 if (cmd)
2079 *cmd = matched_element;
2080
2081 if (matched_element->daemon)
2082 return CMD_SUCCESS_DAEMON;
2083
2084 /* Execute matched command. */
2085 return (*matched_element->func) (matched_element, vty, argc, argv);
2086}
2087
paulb92938a2002-12-13 21:20:42 +00002088
2089int
2090cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) {
paul9ab68122003-01-18 01:16:20 +00002091 int ret, saved_ret, tried = 0;
2092 enum node_type onode, try_node;
2093
2094 onode = try_node = vty->node;
paulb92938a2002-12-13 21:20:42 +00002095
2096 if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
2097 {
2098 vector shifted_vline;
hasso8c328f12004-10-05 21:01:23 +00002099 unsigned int index;
paulb92938a2002-12-13 21:20:42 +00002100
2101 vty->node = ENABLE_NODE;
2102 /* We can try it on enable node, cos' the vty is authenticated */
2103
2104 shifted_vline = vector_init (vector_count(vline));
2105 /* use memcpy? */
2106 for (index = 1; index < vector_max (vline); index++)
2107 {
2108 vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
2109 }
2110
2111 ret = cmd_execute_command_real (shifted_vline, vty, cmd);
2112
2113 vector_free(shifted_vline);
2114 vty->node = onode;
2115 return ret;
2116 }
2117
2118
paul9ab68122003-01-18 01:16:20 +00002119 saved_ret = ret = cmd_execute_command_real (vline, vty, cmd);
paulb92938a2002-12-13 21:20:42 +00002120
2121 /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
paul9ab68122003-01-18 01:16:20 +00002122 while ( ret != CMD_SUCCESS && ret != CMD_WARNING
paulb92938a2002-12-13 21:20:42 +00002123 && vty->node > CONFIG_NODE )
2124 {
paul9ab68122003-01-18 01:16:20 +00002125 try_node = node_parent(try_node);
2126 vty->node = try_node;
paulb92938a2002-12-13 21:20:42 +00002127 ret = cmd_execute_command_real (vline, vty, cmd);
paul9ab68122003-01-18 01:16:20 +00002128 tried = 1;
2129 if (ret == CMD_SUCCESS || ret == CMD_WARNING)
paulb92938a2002-12-13 21:20:42 +00002130 {
paul9ab68122003-01-18 01:16:20 +00002131 /* succesfull command, leave the node as is */
paulb92938a2002-12-13 21:20:42 +00002132 return ret;
2133 }
paulb92938a2002-12-13 21:20:42 +00002134 }
paul9ab68122003-01-18 01:16:20 +00002135 /* no command succeeded, reset the vty to the original node and
2136 return the error for this node */
2137 if ( tried )
2138 vty->node = onode;
2139 return saved_ret;
pauleda031f2003-01-18 00:39:19 +00002140}
2141
paul718e3742002-12-13 20:15:29 +00002142/* Execute command by argument readline. */
2143int
2144cmd_execute_command_strict (vector vline, struct vty *vty,
2145 struct cmd_element **cmd)
2146{
hasso8c328f12004-10-05 21:01:23 +00002147 unsigned int i;
2148 unsigned int index;
paul718e3742002-12-13 20:15:29 +00002149 vector cmd_vector;
2150 struct cmd_element *cmd_element;
2151 struct cmd_element *matched_element;
2152 unsigned int matched_count, incomplete_count;
2153 int argc;
paul9035efa2004-10-10 11:56:56 +00002154 const char *argv[CMD_ARGC_MAX];
paul718e3742002-12-13 20:15:29 +00002155 int varflag;
2156 enum match_type match = 0;
2157 char *command;
2158
2159 /* Make copy of command element */
2160 cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
2161
2162 for (index = 0; index < vector_max (vline); index++)
2163 {
2164 int ret;
2165
2166 command = vector_slot (vline, index);
2167
2168 match = cmd_filter_by_string (vector_slot (vline, index),
2169 cmd_vector, index);
2170
2171 /* If command meets '.VARARG' then finish matching. */
2172 if (match == vararg_match)
2173 break;
2174
2175 ret = is_cmd_ambiguous (command, cmd_vector, index, match);
2176 if (ret == 1)
2177 {
2178 vector_free (cmd_vector);
2179 return CMD_ERR_AMBIGUOUS;
2180 }
2181 if (ret == 2)
2182 {
2183 vector_free (cmd_vector);
2184 return CMD_ERR_NO_MATCH;
2185 }
2186 }
2187
2188 /* Check matched count. */
2189 matched_element = NULL;
2190 matched_count = 0;
2191 incomplete_count = 0;
2192 for (i = 0; i < vector_max (cmd_vector); i++)
2193 if (vector_slot (cmd_vector,i) != NULL)
2194 {
2195 cmd_element = vector_slot (cmd_vector,i);
2196
2197 if (match == vararg_match || index >= cmd_element->cmdsize)
2198 {
2199 matched_element = cmd_element;
2200 matched_count++;
2201 }
2202 else
2203 incomplete_count++;
2204 }
2205
2206 /* Finish of using cmd_vector. */
2207 vector_free (cmd_vector);
2208
2209 /* To execute command, matched_count must be 1.*/
2210 if (matched_count == 0)
2211 {
2212 if (incomplete_count)
2213 return CMD_ERR_INCOMPLETE;
2214 else
2215 return CMD_ERR_NO_MATCH;
2216 }
2217
2218 if (matched_count > 1)
2219 return CMD_ERR_AMBIGUOUS;
2220
2221 /* Argument treatment */
2222 varflag = 0;
2223 argc = 0;
2224
2225 for (i = 0; i < vector_max (vline); i++)
2226 {
2227 if (varflag)
2228 argv[argc++] = vector_slot (vline, i);
2229 else
2230 {
2231 vector descvec = vector_slot (matched_element->strvec, i);
2232
2233 if (vector_max (descvec) == 1)
2234 {
2235 struct desc *desc = vector_slot (descvec, 0);
paul718e3742002-12-13 20:15:29 +00002236
hasso8c328f12004-10-05 21:01:23 +00002237 if (CMD_VARARG (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002238 varflag = 1;
2239
hasso8c328f12004-10-05 21:01:23 +00002240 if (varflag || CMD_VARIABLE (desc->cmd) || CMD_OPTION (desc->cmd))
paul718e3742002-12-13 20:15:29 +00002241 argv[argc++] = vector_slot (vline, i);
2242 }
2243 else
2244 argv[argc++] = vector_slot (vline, i);
2245 }
2246
2247 if (argc >= CMD_ARGC_MAX)
2248 return CMD_ERR_EXEED_ARGC_MAX;
2249 }
2250
2251 /* For vtysh execution. */
2252 if (cmd)
2253 *cmd = matched_element;
2254
2255 if (matched_element->daemon)
2256 return CMD_SUCCESS_DAEMON;
2257
2258 /* Now execute matched command */
2259 return (*matched_element->func) (matched_element, vty, argc, argv);
2260}
2261
2262/* Configration make from file. */
2263int
2264config_from_file (struct vty *vty, FILE *fp)
2265{
2266 int ret;
2267 vector vline;
2268
2269 while (fgets (vty->buf, VTY_BUFSIZ, fp))
2270 {
2271 vline = cmd_make_strvec (vty->buf);
2272
2273 /* In case of comment line */
2274 if (vline == NULL)
2275 continue;
2276 /* Execute configuration command : this is strict match */
2277 ret = cmd_execute_command_strict (vline, vty, NULL);
2278
2279 /* Try again with setting node to CONFIG_NODE */
paulb92938a2002-12-13 21:20:42 +00002280 while (ret != CMD_SUCCESS && ret != CMD_WARNING
hassoddd85ed2004-10-13 08:18:07 +00002281 && ret != CMD_ERR_NOTHING_TODO && vty->node != CONFIG_NODE)
2282 {
paulb92938a2002-12-13 21:20:42 +00002283 vty->node = node_parent(vty->node);
hassoddd85ed2004-10-13 08:18:07 +00002284 ret = cmd_execute_command_strict (vline, vty, NULL);
2285 }
paul9ab68122003-01-18 01:16:20 +00002286
paul718e3742002-12-13 20:15:29 +00002287 cmd_free_strvec (vline);
2288
hassoddd85ed2004-10-13 08:18:07 +00002289 if (ret != CMD_SUCCESS && ret != CMD_WARNING
2290 && ret != CMD_ERR_NOTHING_TODO)
paul718e3742002-12-13 20:15:29 +00002291 return ret;
2292 }
2293 return CMD_SUCCESS;
2294}
2295
2296/* Configration from terminal */
2297DEFUN (config_terminal,
2298 config_terminal_cmd,
2299 "configure terminal",
2300 "Configuration from vty interface\n"
2301 "Configuration terminal\n")
2302{
2303 if (vty_config_lock (vty))
2304 vty->node = CONFIG_NODE;
2305 else
2306 {
2307 vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
2308 return CMD_WARNING;
2309 }
2310 return CMD_SUCCESS;
2311}
2312
2313/* Enable command */
2314DEFUN (enable,
2315 config_enable_cmd,
2316 "enable",
2317 "Turn on privileged mode command\n")
2318{
2319 /* If enable password is NULL, change to ENABLE_NODE */
2320 if ((host.enable == NULL && host.enable_encrypt == NULL) ||
2321 vty->type == VTY_SHELL_SERV)
2322 vty->node = ENABLE_NODE;
2323 else
2324 vty->node = AUTH_ENABLE_NODE;
2325
2326 return CMD_SUCCESS;
2327}
2328
2329/* Disable command */
2330DEFUN (disable,
2331 config_disable_cmd,
2332 "disable",
2333 "Turn off privileged mode command\n")
2334{
2335 if (vty->node == ENABLE_NODE)
2336 vty->node = VIEW_NODE;
2337 return CMD_SUCCESS;
2338}
2339
2340/* Down vty node level. */
2341DEFUN (config_exit,
2342 config_exit_cmd,
2343 "exit",
2344 "Exit current mode and down to previous mode\n")
2345{
2346 switch (vty->node)
2347 {
2348 case VIEW_NODE:
2349 case ENABLE_NODE:
2350 if (vty_shell (vty))
2351 exit (0);
2352 else
2353 vty->status = VTY_CLOSE;
2354 break;
2355 case CONFIG_NODE:
2356 vty->node = ENABLE_NODE;
2357 vty_config_unlock (vty);
2358 break;
2359 case INTERFACE_NODE:
2360 case ZEBRA_NODE:
2361 case BGP_NODE:
2362 case RIP_NODE:
2363 case RIPNG_NODE:
2364 case OSPF_NODE:
2365 case OSPF6_NODE:
jardin9e867fe2003-12-23 08:56:18 +00002366 case ISIS_NODE:
paul718e3742002-12-13 20:15:29 +00002367 case KEYCHAIN_NODE:
2368 case MASC_NODE:
2369 case RMAP_NODE:
2370 case VTY_NODE:
2371 vty->node = CONFIG_NODE;
2372 break;
2373 case BGP_VPNV4_NODE:
2374 case BGP_IPV4_NODE:
2375 case BGP_IPV4M_NODE:
2376 case BGP_IPV6_NODE:
2377 vty->node = BGP_NODE;
2378 break;
2379 case KEYCHAIN_KEY_NODE:
2380 vty->node = KEYCHAIN_NODE;
2381 break;
2382 default:
2383 break;
2384 }
2385 return CMD_SUCCESS;
2386}
2387
2388/* quit is alias of exit. */
2389ALIAS (config_exit,
2390 config_quit_cmd,
2391 "quit",
2392 "Exit current mode and down to previous mode\n")
2393
2394/* End of configuration. */
2395DEFUN (config_end,
2396 config_end_cmd,
2397 "end",
2398 "End current mode and change to enable mode.")
2399{
2400 switch (vty->node)
2401 {
2402 case VIEW_NODE:
2403 case ENABLE_NODE:
2404 /* Nothing to do. */
2405 break;
2406 case CONFIG_NODE:
2407 case INTERFACE_NODE:
2408 case ZEBRA_NODE:
2409 case RIP_NODE:
2410 case RIPNG_NODE:
2411 case BGP_NODE:
2412 case BGP_VPNV4_NODE:
2413 case BGP_IPV4_NODE:
2414 case BGP_IPV4M_NODE:
2415 case BGP_IPV6_NODE:
2416 case RMAP_NODE:
2417 case OSPF_NODE:
2418 case OSPF6_NODE:
jardin9e867fe2003-12-23 08:56:18 +00002419 case ISIS_NODE:
paul718e3742002-12-13 20:15:29 +00002420 case KEYCHAIN_NODE:
2421 case KEYCHAIN_KEY_NODE:
2422 case MASC_NODE:
2423 case VTY_NODE:
2424 vty_config_unlock (vty);
2425 vty->node = ENABLE_NODE;
2426 break;
2427 default:
2428 break;
2429 }
2430 return CMD_SUCCESS;
2431}
2432
2433/* Show version. */
2434DEFUN (show_version,
2435 show_version_cmd,
2436 "show version",
2437 SHOW_STR
2438 "Displays zebra version\n")
2439{
hasso6590f2c2004-10-19 20:40:08 +00002440 vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name, VTY_NEWLINE);
2441 vty_out (vty, "%s%s", QUAGGA_COPYRIGHT, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00002442
2443 return CMD_SUCCESS;
2444}
2445
2446/* Help display function for all node. */
2447DEFUN (config_help,
2448 config_help_cmd,
2449 "help",
2450 "Description of the interactive help system\n")
2451{
2452 vty_out (vty,
hasso6590f2c2004-10-19 20:40:08 +00002453 "Quagga VTY provides advanced help feature. When you need help,%s\
paul718e3742002-12-13 20:15:29 +00002454anytime at the command line please press '?'.%s\
2455%s\
2456If nothing matches, the help list will be empty and you must backup%s\
2457 until entering a '?' shows the available options.%s\
2458Two styles of help are provided:%s\
24591. Full help is available when you are ready to enter a%s\
2460command argument (e.g. 'show ?') and describes each possible%s\
2461argument.%s\
24622. Partial help is provided when an abbreviated argument is entered%s\
2463 and you want to know what arguments match the input%s\
2464 (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2465 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
2466 VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
2467 return CMD_SUCCESS;
2468}
2469
2470/* Help display function for all node. */
2471DEFUN (config_list,
2472 config_list_cmd,
2473 "list",
2474 "Print command list\n")
2475{
hasso8c328f12004-10-05 21:01:23 +00002476 unsigned int i;
paul718e3742002-12-13 20:15:29 +00002477 struct cmd_node *cnode = vector_slot (cmdvec, vty->node);
2478 struct cmd_element *cmd;
2479
2480 for (i = 0; i < vector_max (cnode->cmd_vector); i++)
2481 if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL)
2482 vty_out (vty, " %s%s", cmd->string,
2483 VTY_NEWLINE);
2484 return CMD_SUCCESS;
2485}
2486
2487/* Write current configuration into file. */
2488DEFUN (config_write_file,
2489 config_write_file_cmd,
2490 "write file",
2491 "Write running configuration to memory, network, or terminal\n"
2492 "Write to configuration file\n")
2493{
hasso8c328f12004-10-05 21:01:23 +00002494 unsigned int i;
paul718e3742002-12-13 20:15:29 +00002495 int fd;
2496 struct cmd_node *node;
2497 char *config_file;
2498 char *config_file_tmp = NULL;
2499 char *config_file_sav = NULL;
2500 struct vty *file_vty;
2501
2502 /* Check and see if we are operating under vtysh configuration */
2503 if (host.config == NULL)
2504 {
2505 vty_out (vty, "Can't save to configuration file, using vtysh.%s",
2506 VTY_NEWLINE);
2507 return CMD_WARNING;
2508 }
2509
2510 /* Get filename. */
2511 config_file = host.config;
2512
2513 config_file_sav = malloc (strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1);
2514 strcpy (config_file_sav, config_file);
2515 strcat (config_file_sav, CONF_BACKUP_EXT);
2516
2517
2518 config_file_tmp = malloc (strlen (config_file) + 8);
2519 sprintf (config_file_tmp, "%s.XXXXXX", config_file);
2520
2521 /* Open file to configuration write. */
2522 fd = mkstemp (config_file_tmp);
2523 if (fd < 0)
2524 {
2525 vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp,
2526 VTY_NEWLINE);
2527 free (config_file_tmp);
2528 free (config_file_sav);
2529 return CMD_WARNING;
2530 }
2531
2532 /* Make vty for configuration file. */
2533 file_vty = vty_new ();
2534 file_vty->fd = fd;
2535 file_vty->type = VTY_FILE;
2536
2537 /* Config file header print. */
2538 vty_out (file_vty, "!\n! Zebra configuration saved from vty\n! ");
2539 vty_time_print (file_vty, 1);
2540 vty_out (file_vty, "!\n");
2541
2542 for (i = 0; i < vector_max (cmdvec); i++)
2543 if ((node = vector_slot (cmdvec, i)) && node->func)
2544 {
2545 if ((*node->func) (file_vty))
2546 vty_out (file_vty, "!\n");
2547 }
2548 vty_close (file_vty);
2549
2550 if (unlink (config_file_sav) != 0)
2551 if (errno != ENOENT)
2552 {
2553 vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav,
2554 VTY_NEWLINE);
2555 free (config_file_sav);
2556 free (config_file_tmp);
2557 unlink (config_file_tmp);
2558 return CMD_WARNING;
2559 }
2560 if (link (config_file, config_file_sav) != 0)
2561 {
2562 vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
2563 VTY_NEWLINE);
2564 free (config_file_sav);
2565 free (config_file_tmp);
2566 unlink (config_file_tmp);
2567 return CMD_WARNING;
2568 }
2569 sync ();
2570 if (unlink (config_file) != 0)
2571 {
2572 vty_out (vty, "Can't unlink configuration file %s.%s", config_file,
2573 VTY_NEWLINE);
2574 free (config_file_sav);
2575 free (config_file_tmp);
2576 unlink (config_file_tmp);
2577 return CMD_WARNING;
2578 }
2579 if (link (config_file_tmp, config_file) != 0)
2580 {
2581 vty_out (vty, "Can't save configuration file %s.%s", config_file,
2582 VTY_NEWLINE);
2583 free (config_file_sav);
2584 free (config_file_tmp);
2585 unlink (config_file_tmp);
2586 return CMD_WARNING;
2587 }
2588 unlink (config_file_tmp);
2589 sync ();
2590
2591 free (config_file_sav);
2592 free (config_file_tmp);
gdtaa593d52003-12-22 20:15:53 +00002593
2594 if (chmod (config_file, CONFIGFILE_MASK) != 0)
2595 {
2596 vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s",
ajs6099b3b2004-11-20 02:06:59 +00002597 config_file, safe_strerror(errno), errno, VTY_NEWLINE);
gdtaa593d52003-12-22 20:15:53 +00002598 return CMD_WARNING;
2599 }
2600
paul718e3742002-12-13 20:15:29 +00002601 vty_out (vty, "Configuration saved to %s%s", config_file,
2602 VTY_NEWLINE);
2603 return CMD_SUCCESS;
2604}
2605
2606ALIAS (config_write_file,
2607 config_write_cmd,
2608 "write",
2609 "Write running configuration to memory, network, or terminal\n")
2610
2611ALIAS (config_write_file,
2612 config_write_memory_cmd,
2613 "write memory",
2614 "Write running configuration to memory, network, or terminal\n"
2615 "Write configuration to the file (same as write file)\n")
2616
2617ALIAS (config_write_file,
2618 copy_runningconfig_startupconfig_cmd,
2619 "copy running-config startup-config",
2620 "Copy configuration\n"
2621 "Copy running config to... \n"
2622 "Copy running config to startup config (same as write file)\n")
2623
2624/* Write current configuration into the terminal. */
2625DEFUN (config_write_terminal,
2626 config_write_terminal_cmd,
2627 "write terminal",
2628 "Write running configuration to memory, network, or terminal\n"
2629 "Write to terminal\n")
2630{
hasso8c328f12004-10-05 21:01:23 +00002631 unsigned int i;
paul718e3742002-12-13 20:15:29 +00002632 struct cmd_node *node;
2633
2634 if (vty->type == VTY_SHELL_SERV)
2635 {
2636 for (i = 0; i < vector_max (cmdvec); i++)
2637 if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
2638 {
2639 if ((*node->func) (vty))
2640 vty_out (vty, "!%s", VTY_NEWLINE);
2641 }
2642 }
2643 else
2644 {
2645 vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
2646 VTY_NEWLINE);
2647 vty_out (vty, "!%s", VTY_NEWLINE);
2648
2649 for (i = 0; i < vector_max (cmdvec); i++)
2650 if ((node = vector_slot (cmdvec, i)) && node->func)
2651 {
2652 if ((*node->func) (vty))
2653 vty_out (vty, "!%s", VTY_NEWLINE);
2654 }
2655 vty_out (vty, "end%s",VTY_NEWLINE);
2656 }
2657 return CMD_SUCCESS;
2658}
2659
2660/* Write current configuration into the terminal. */
2661ALIAS (config_write_terminal,
2662 show_running_config_cmd,
2663 "show running-config",
2664 SHOW_STR
2665 "running configuration\n")
2666
2667/* Write startup configuration into the terminal. */
2668DEFUN (show_startup_config,
2669 show_startup_config_cmd,
2670 "show startup-config",
2671 SHOW_STR
2672 "Contentes of startup configuration\n")
2673{
2674 char buf[BUFSIZ];
2675 FILE *confp;
2676
2677 confp = fopen (host.config, "r");
2678 if (confp == NULL)
2679 {
2680 vty_out (vty, "Can't open configuration file [%s]%s",
2681 host.config, VTY_NEWLINE);
2682 return CMD_WARNING;
2683 }
2684
2685 while (fgets (buf, BUFSIZ, confp))
2686 {
2687 char *cp = buf;
2688
2689 while (*cp != '\r' && *cp != '\n' && *cp != '\0')
2690 cp++;
2691 *cp = '\0';
2692
2693 vty_out (vty, "%s%s", buf, VTY_NEWLINE);
2694 }
2695
2696 fclose (confp);
2697
2698 return CMD_SUCCESS;
2699}
2700
2701/* Hostname configuration */
2702DEFUN (config_hostname,
2703 hostname_cmd,
2704 "hostname WORD",
2705 "Set system's network name\n"
2706 "This system's network name\n")
2707{
2708 if (!isalpha((int) *argv[0]))
2709 {
2710 vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE);
2711 return CMD_WARNING;
2712 }
2713
2714 if (host.name)
2715 XFREE (0, host.name);
2716
2717 host.name = strdup (argv[0]);
2718 return CMD_SUCCESS;
2719}
2720
2721DEFUN (config_no_hostname,
2722 no_hostname_cmd,
2723 "no hostname [HOSTNAME]",
2724 NO_STR
2725 "Reset system's network name\n"
2726 "Host name of this router\n")
2727{
2728 if (host.name)
2729 XFREE (0, host.name);
2730 host.name = NULL;
2731 return CMD_SUCCESS;
2732}
2733
2734/* VTY interface password set. */
2735DEFUN (config_password, password_cmd,
2736 "password (8|) WORD",
2737 "Assign the terminal connection password\n"
2738 "Specifies a HIDDEN password will follow\n"
2739 "dummy string \n"
2740 "The HIDDEN line password string\n")
2741{
2742 /* Argument check. */
2743 if (argc == 0)
2744 {
2745 vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
2746 return CMD_WARNING;
2747 }
2748
2749 if (argc == 2)
2750 {
2751 if (*argv[0] == '8')
2752 {
2753 if (host.password)
2754 XFREE (0, host.password);
2755 host.password = NULL;
2756 if (host.password_encrypt)
2757 XFREE (0, host.password_encrypt);
2758 host.password_encrypt = XSTRDUP (0, strdup (argv[1]));
2759 return CMD_SUCCESS;
2760 }
2761 else
2762 {
2763 vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
2764 return CMD_WARNING;
2765 }
2766 }
2767
2768 if (!isalnum ((int) *argv[0]))
2769 {
2770 vty_out (vty,
2771 "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
2772 return CMD_WARNING;
2773 }
2774
2775 if (host.password)
2776 XFREE (0, host.password);
2777 host.password = NULL;
2778
2779 if (host.encrypt)
2780 {
2781 if (host.password_encrypt)
2782 XFREE (0, host.password_encrypt);
2783 host.password_encrypt = XSTRDUP (0, zencrypt (argv[0]));
2784 }
2785 else
2786 host.password = XSTRDUP (0, argv[0]);
2787
2788 return CMD_SUCCESS;
2789}
2790
2791ALIAS (config_password, password_text_cmd,
2792 "password LINE",
2793 "Assign the terminal connection password\n"
2794 "The UNENCRYPTED (cleartext) line password\n")
2795
2796/* VTY enable password set. */
2797DEFUN (config_enable_password, enable_password_cmd,
2798 "enable password (8|) WORD",
2799 "Modify enable password parameters\n"
2800 "Assign the privileged level password\n"
2801 "Specifies a HIDDEN password will follow\n"
2802 "dummy string \n"
2803 "The HIDDEN 'enable' password string\n")
2804{
2805 /* Argument check. */
2806 if (argc == 0)
2807 {
2808 vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
2809 return CMD_WARNING;
2810 }
2811
2812 /* Crypt type is specified. */
2813 if (argc == 2)
2814 {
2815 if (*argv[0] == '8')
2816 {
2817 if (host.enable)
2818 XFREE (0, host.enable);
2819 host.enable = NULL;
2820
2821 if (host.enable_encrypt)
2822 XFREE (0, host.enable_encrypt);
2823 host.enable_encrypt = XSTRDUP (0, argv[1]);
2824
2825 return CMD_SUCCESS;
2826 }
2827 else
2828 {
2829 vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
2830 return CMD_WARNING;
2831 }
2832 }
2833
2834 if (!isalnum ((int) *argv[0]))
2835 {
2836 vty_out (vty,
2837 "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
2838 return CMD_WARNING;
2839 }
2840
2841 if (host.enable)
2842 XFREE (0, host.enable);
2843 host.enable = NULL;
2844
2845 /* Plain password input. */
2846 if (host.encrypt)
2847 {
2848 if (host.enable_encrypt)
2849 XFREE (0, host.enable_encrypt);
2850 host.enable_encrypt = XSTRDUP (0, zencrypt (argv[0]));
2851 }
2852 else
2853 host.enable = XSTRDUP (0, argv[0]);
2854
2855 return CMD_SUCCESS;
2856}
2857
2858ALIAS (config_enable_password,
2859 enable_password_text_cmd,
2860 "enable password LINE",
2861 "Modify enable password parameters\n"
2862 "Assign the privileged level password\n"
2863 "The UNENCRYPTED (cleartext) 'enable' password\n")
2864
2865/* VTY enable password delete. */
2866DEFUN (no_config_enable_password, no_enable_password_cmd,
2867 "no enable password",
2868 NO_STR
2869 "Modify enable password parameters\n"
2870 "Assign the privileged level password\n")
2871{
2872 if (host.enable)
2873 XFREE (0, host.enable);
2874 host.enable = NULL;
2875
2876 if (host.enable_encrypt)
2877 XFREE (0, host.enable_encrypt);
2878 host.enable_encrypt = NULL;
2879
2880 return CMD_SUCCESS;
2881}
2882
2883DEFUN (service_password_encrypt,
2884 service_password_encrypt_cmd,
2885 "service password-encryption",
2886 "Set up miscellaneous service\n"
2887 "Enable encrypted passwords\n")
2888{
2889 if (host.encrypt)
2890 return CMD_SUCCESS;
2891
2892 host.encrypt = 1;
2893
2894 if (host.password)
2895 {
2896 if (host.password_encrypt)
2897 XFREE (0, host.password_encrypt);
2898 host.password_encrypt = XSTRDUP (0, zencrypt (host.password));
2899 }
2900 if (host.enable)
2901 {
2902 if (host.enable_encrypt)
2903 XFREE (0, host.enable_encrypt);
2904 host.enable_encrypt = XSTRDUP (0, zencrypt (host.enable));
2905 }
2906
2907 return CMD_SUCCESS;
2908}
2909
2910DEFUN (no_service_password_encrypt,
2911 no_service_password_encrypt_cmd,
2912 "no service password-encryption",
2913 NO_STR
2914 "Set up miscellaneous service\n"
2915 "Enable encrypted passwords\n")
2916{
2917 if (! host.encrypt)
2918 return CMD_SUCCESS;
2919
2920 host.encrypt = 0;
2921
2922 if (host.password_encrypt)
2923 XFREE (0, host.password_encrypt);
2924 host.password_encrypt = NULL;
2925
2926 if (host.enable_encrypt)
2927 XFREE (0, host.enable_encrypt);
2928 host.enable_encrypt = NULL;
2929
2930 return CMD_SUCCESS;
2931}
2932
2933DEFUN (config_terminal_length, config_terminal_length_cmd,
2934 "terminal length <0-512>",
2935 "Set terminal line parameters\n"
2936 "Set number of lines on a screen\n"
2937 "Number of lines on screen (0 for no pausing)\n")
2938{
2939 int lines;
2940 char *endptr = NULL;
2941
2942 lines = strtol (argv[0], &endptr, 10);
2943 if (lines < 0 || lines > 512 || *endptr != '\0')
2944 {
2945 vty_out (vty, "length is malformed%s", VTY_NEWLINE);
2946 return CMD_WARNING;
2947 }
2948 vty->lines = lines;
2949
2950 return CMD_SUCCESS;
2951}
2952
2953DEFUN (config_terminal_no_length, config_terminal_no_length_cmd,
2954 "terminal no length",
2955 "Set terminal line parameters\n"
2956 NO_STR
2957 "Set number of lines on a screen\n")
2958{
2959 vty->lines = -1;
2960 return CMD_SUCCESS;
2961}
2962
2963DEFUN (service_terminal_length, service_terminal_length_cmd,
2964 "service terminal-length <0-512>",
2965 "Set up miscellaneous service\n"
2966 "System wide terminal length configuration\n"
2967 "Number of lines of VTY (0 means no line control)\n")
2968{
2969 int lines;
2970 char *endptr = NULL;
2971
2972 lines = strtol (argv[0], &endptr, 10);
2973 if (lines < 0 || lines > 512 || *endptr != '\0')
2974 {
2975 vty_out (vty, "length is malformed%s", VTY_NEWLINE);
2976 return CMD_WARNING;
2977 }
2978 host.lines = lines;
2979
2980 return CMD_SUCCESS;
2981}
2982
2983DEFUN (no_service_terminal_length, no_service_terminal_length_cmd,
2984 "no service terminal-length [<0-512>]",
2985 NO_STR
2986 "Set up miscellaneous service\n"
2987 "System wide terminal length configuration\n"
2988 "Number of lines of VTY (0 means no line control)\n")
2989{
2990 host.lines = -1;
2991 return CMD_SUCCESS;
2992}
2993
ajs274a4a42004-12-07 15:39:31 +00002994DEFUN (config_logmsg,
2995 config_logmsg_cmd,
2996 "logmsg "LOG_LEVELS" .MESSAGE",
2997 "Send a message to enabled logging destinations\n"
2998 LOG_LEVEL_DESC
2999 "The message to send\n")
3000{
3001 int level;
3002 char *message;
3003
3004 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3005 return CMD_ERR_NO_MATCH;
3006
3007 zlog(NULL, level, (message = argv_concat(argv, argc, 1)));
3008 XFREE(MTYPE_TMP, message);
3009 return CMD_SUCCESS;
3010}
3011
3012DEFUN (show_logging,
3013 show_logging_cmd,
3014 "show logging",
3015 SHOW_STR
3016 "Show current logging configuration\n")
3017{
3018 struct zlog *zl = zlog_default;
3019
3020 vty_out (vty, "Syslog logging: ");
3021 if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED)
3022 vty_out (vty, "disabled");
3023 else
3024 vty_out (vty, "level %s, facility %s, ident %s",
3025 zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]],
3026 facility_name(zl->facility), zl->ident);
3027 vty_out (vty, "%s", VTY_NEWLINE);
3028
3029 vty_out (vty, "Stdout logging: ");
3030 if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED)
3031 vty_out (vty, "disabled");
3032 else
3033 vty_out (vty, "level %s",
3034 zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]);
3035 vty_out (vty, "%s", VTY_NEWLINE);
3036
3037 vty_out (vty, "Monitor logging: ");
3038 if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED)
3039 vty_out (vty, "disabled");
3040 else
3041 vty_out (vty, "level %s",
3042 zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]);
3043 vty_out (vty, "%s", VTY_NEWLINE);
3044
3045 vty_out (vty, "File logging: ");
3046 if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) ||
3047 !zl->fp)
3048 vty_out (vty, "disabled");
3049 else
3050 vty_out (vty, "level %s, filename %s",
3051 zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]],
3052 zl->filename);
3053 vty_out (vty, "%s", VTY_NEWLINE);
3054
3055 vty_out (vty, "Protocol name: %s%s",
3056 zlog_proto_names[zl->protocol], VTY_NEWLINE);
3057 vty_out (vty, "Record priority: %s%s",
3058 (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE);
3059
3060 return CMD_SUCCESS;
3061}
3062
paul718e3742002-12-13 20:15:29 +00003063DEFUN (config_log_stdout,
3064 config_log_stdout_cmd,
3065 "log stdout",
3066 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003067 "Set stdout logging level\n")
paul718e3742002-12-13 20:15:29 +00003068{
ajs274a4a42004-12-07 15:39:31 +00003069 zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl);
3070 return CMD_SUCCESS;
3071}
3072
3073DEFUN (config_log_stdout_level,
3074 config_log_stdout_level_cmd,
3075 "log stdout "LOG_LEVELS,
3076 "Logging control\n"
3077 "Set stdout logging level\n"
3078 LOG_LEVEL_DESC)
3079{
3080 int level;
3081
3082 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3083 return CMD_ERR_NO_MATCH;
3084 zlog_set_level (NULL, ZLOG_DEST_STDOUT, level);
paul718e3742002-12-13 20:15:29 +00003085 return CMD_SUCCESS;
3086}
3087
3088DEFUN (no_config_log_stdout,
3089 no_config_log_stdout_cmd,
ajs274a4a42004-12-07 15:39:31 +00003090 "no log stdout [LEVEL]",
paul718e3742002-12-13 20:15:29 +00003091 NO_STR
3092 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003093 "Cancel logging to stdout\n"
3094 "Logging level\n")
paul718e3742002-12-13 20:15:29 +00003095{
ajs274a4a42004-12-07 15:39:31 +00003096 zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED);
paul718e3742002-12-13 20:15:29 +00003097 return CMD_SUCCESS;
3098}
3099
ajs274a4a42004-12-07 15:39:31 +00003100DEFUN (config_log_monitor,
3101 config_log_monitor_cmd,
3102 "log monitor",
paul718e3742002-12-13 20:15:29 +00003103 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003104 "Set terminal line (monitor) logging level\n")
3105{
3106 zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl);
3107 return CMD_SUCCESS;
3108}
3109
3110DEFUN (config_log_monitor_level,
3111 config_log_monitor_level_cmd,
3112 "log monitor "LOG_LEVELS,
3113 "Logging control\n"
3114 "Set terminal line (monitor) logging level\n"
3115 LOG_LEVEL_DESC)
3116{
3117 int level;
3118
3119 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3120 return CMD_ERR_NO_MATCH;
3121 zlog_set_level (NULL, ZLOG_DEST_MONITOR, level);
3122 return CMD_SUCCESS;
3123}
3124
3125DEFUN (no_config_log_monitor,
3126 no_config_log_monitor_cmd,
3127 "no log monitor [LEVEL]",
3128 NO_STR
3129 "Logging control\n"
3130 "Disable terminal line (monitor) logging\n"
3131 "Logging level\n")
3132{
3133 zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
3134 return CMD_SUCCESS;
3135}
3136
3137static int
3138set_log_file(struct vty *vty, const char *fname, int loglevel)
paul718e3742002-12-13 20:15:29 +00003139{
3140 int ret;
paul9035efa2004-10-10 11:56:56 +00003141 char *p = NULL;
3142 const char *fullpath;
3143
paul718e3742002-12-13 20:15:29 +00003144 /* Path detection. */
ajs274a4a42004-12-07 15:39:31 +00003145 if (! IS_DIRECTORY_SEP (*fname))
paul718e3742002-12-13 20:15:29 +00003146 {
paul9035efa2004-10-10 11:56:56 +00003147 char cwd[MAXPATHLEN+1];
3148 cwd[MAXPATHLEN] = '\0';
3149
3150 if (getcwd (cwd, MAXPATHLEN) == NULL)
3151 {
3152 zlog_err ("config_log_file: Unable to alloc mem!");
3153 return CMD_WARNING;
3154 }
3155
ajs274a4a42004-12-07 15:39:31 +00003156 if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2))
paul9035efa2004-10-10 11:56:56 +00003157 == NULL)
3158 {
3159 zlog_err ("config_log_file: Unable to alloc mem!");
3160 return CMD_WARNING;
3161 }
ajs274a4a42004-12-07 15:39:31 +00003162 sprintf (p, "%s/%s", cwd, fname);
paul9035efa2004-10-10 11:56:56 +00003163 fullpath = p;
paul718e3742002-12-13 20:15:29 +00003164 }
3165 else
ajs274a4a42004-12-07 15:39:31 +00003166 fullpath = fname;
paul718e3742002-12-13 20:15:29 +00003167
ajs274a4a42004-12-07 15:39:31 +00003168 ret = zlog_set_file (NULL, fullpath, loglevel);
paul718e3742002-12-13 20:15:29 +00003169
paul9035efa2004-10-10 11:56:56 +00003170 if (p)
3171 XFREE (MTYPE_TMP, p);
3172
paul718e3742002-12-13 20:15:29 +00003173 if (!ret)
3174 {
ajs274a4a42004-12-07 15:39:31 +00003175 vty_out (vty, "can't open logfile %s\n", fname);
paul718e3742002-12-13 20:15:29 +00003176 return CMD_WARNING;
3177 }
3178
3179 if (host.logfile)
3180 XFREE (MTYPE_TMP, host.logfile);
3181
ajs274a4a42004-12-07 15:39:31 +00003182 host.logfile = XSTRDUP (MTYPE_TMP, fname);
paul718e3742002-12-13 20:15:29 +00003183
3184 return CMD_SUCCESS;
3185}
3186
ajs274a4a42004-12-07 15:39:31 +00003187DEFUN (config_log_file,
3188 config_log_file_cmd,
3189 "log file FILENAME",
3190 "Logging control\n"
3191 "Logging to file\n"
3192 "Logging filename\n")
3193{
3194 return set_log_file(vty, argv[0], zlog_default->default_lvl);
3195}
3196
3197DEFUN (config_log_file_level,
3198 config_log_file_level_cmd,
3199 "log file FILENAME "LOG_LEVELS,
3200 "Logging control\n"
3201 "Logging to file\n"
3202 "Logging filename\n"
3203 LOG_LEVEL_DESC)
3204{
3205 int level;
3206
3207 if ((level = level_match(argv[1])) == ZLOG_DISABLED)
3208 return CMD_ERR_NO_MATCH;
3209 return set_log_file(vty, argv[0], level);
3210}
3211
paul718e3742002-12-13 20:15:29 +00003212DEFUN (no_config_log_file,
3213 no_config_log_file_cmd,
3214 "no log file [FILENAME]",
3215 NO_STR
3216 "Logging control\n"
3217 "Cancel logging to file\n"
3218 "Logging file name\n")
3219{
3220 zlog_reset_file (NULL);
3221
3222 if (host.logfile)
3223 XFREE (MTYPE_TMP, host.logfile);
3224
3225 host.logfile = NULL;
3226
3227 return CMD_SUCCESS;
3228}
3229
ajs274a4a42004-12-07 15:39:31 +00003230ALIAS (no_config_log_file,
3231 no_config_log_file_level_cmd,
3232 "no log file FILENAME LEVEL",
3233 NO_STR
3234 "Logging control\n"
3235 "Cancel logging to file\n"
3236 "Logging file name\n"
3237 "Logging level\n")
3238
paul718e3742002-12-13 20:15:29 +00003239DEFUN (config_log_syslog,
3240 config_log_syslog_cmd,
3241 "log syslog",
3242 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003243 "Set syslog logging level\n")
paul718e3742002-12-13 20:15:29 +00003244{
ajs274a4a42004-12-07 15:39:31 +00003245 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
paul12ab19f2003-07-26 06:14:55 +00003246 return CMD_SUCCESS;
3247}
3248
ajs274a4a42004-12-07 15:39:31 +00003249DEFUN (config_log_syslog_level,
3250 config_log_syslog_level_cmd,
3251 "log syslog "LOG_LEVELS,
paul12ab19f2003-07-26 06:14:55 +00003252 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003253 "Set syslog logging level\n"
3254 LOG_LEVEL_DESC)
paul12ab19f2003-07-26 06:14:55 +00003255{
ajs274a4a42004-12-07 15:39:31 +00003256 int level;
paul12ab19f2003-07-26 06:14:55 +00003257
ajs274a4a42004-12-07 15:39:31 +00003258 if ((level = level_match(argv[0])) == ZLOG_DISABLED)
3259 return CMD_ERR_NO_MATCH;
3260 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, level);
3261 return CMD_SUCCESS;
3262}
paul12ab19f2003-07-26 06:14:55 +00003263
ajs274a4a42004-12-07 15:39:31 +00003264DEFUN_DEPRECATED (config_log_syslog_facility,
3265 config_log_syslog_facility_cmd,
3266 "log syslog facility "LOG_FACILITIES,
3267 "Logging control\n"
3268 "Logging goes to syslog\n"
3269 "(Deprecated) Facility parameter for syslog messages\n"
3270 LOG_FACILITY_DESC)
3271{
3272 int facility;
paul12ab19f2003-07-26 06:14:55 +00003273
ajs274a4a42004-12-07 15:39:31 +00003274 if ((facility = facility_match(argv[0])) < 0)
3275 return CMD_ERR_NO_MATCH;
3276
3277 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl);
paul12ab19f2003-07-26 06:14:55 +00003278 zlog_default->facility = facility;
paul718e3742002-12-13 20:15:29 +00003279 return CMD_SUCCESS;
3280}
3281
3282DEFUN (no_config_log_syslog,
3283 no_config_log_syslog_cmd,
ajs274a4a42004-12-07 15:39:31 +00003284 "no log syslog [LEVEL]",
paul718e3742002-12-13 20:15:29 +00003285 NO_STR
3286 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003287 "Cancel logging to syslog\n"
3288 "Logging level\n")
paul718e3742002-12-13 20:15:29 +00003289{
ajs274a4a42004-12-07 15:39:31 +00003290 zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
paul718e3742002-12-13 20:15:29 +00003291 return CMD_SUCCESS;
3292}
3293
paul12ab19f2003-07-26 06:14:55 +00003294ALIAS (no_config_log_syslog,
3295 no_config_log_syslog_facility_cmd,
ajs274a4a42004-12-07 15:39:31 +00003296 "no log syslog facility "LOG_FACILITIES,
paul12ab19f2003-07-26 06:14:55 +00003297 NO_STR
3298 "Logging control\n"
3299 "Logging goes to syslog\n"
3300 "Facility parameter for syslog messages\n"
ajs274a4a42004-12-07 15:39:31 +00003301 LOG_FACILITY_DESC)
paul12ab19f2003-07-26 06:14:55 +00003302
ajs274a4a42004-12-07 15:39:31 +00003303DEFUN (config_log_facility,
3304 config_log_facility_cmd,
3305 "log facility "LOG_FACILITIES,
paul718e3742002-12-13 20:15:29 +00003306 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003307 "Facility parameter for syslog messages\n"
3308 LOG_FACILITY_DESC)
paul718e3742002-12-13 20:15:29 +00003309{
ajs274a4a42004-12-07 15:39:31 +00003310 int facility;
3311
3312 if ((facility = facility_match(argv[0])) < 0)
3313 return CMD_ERR_NO_MATCH;
3314 zlog_default->facility = facility;
3315 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +00003316}
3317
ajs274a4a42004-12-07 15:39:31 +00003318DEFUN (no_config_log_facility,
3319 no_config_log_facility_cmd,
3320 "no log facility [FACILITY]",
paul718e3742002-12-13 20:15:29 +00003321 NO_STR
3322 "Logging control\n"
ajs274a4a42004-12-07 15:39:31 +00003323 "Reset syslog facility to default (daemon)\n"
3324 "Syslog facility\n")
paul718e3742002-12-13 20:15:29 +00003325{
ajs274a4a42004-12-07 15:39:31 +00003326 zlog_default->facility = LOG_DAEMON;
3327 return CMD_SUCCESS;
3328}
3329
3330DEFUN_DEPRECATED (config_log_trap,
3331 config_log_trap_cmd,
3332 "log trap "LOG_LEVELS,
3333 "Logging control\n"
3334 "(Deprecated) Set logging level and default for all destinations\n"
3335 LOG_LEVEL_DESC)
3336{
3337 int new_level ;
3338 int i;
3339
3340 if ((new_level = level_match(argv[0])) == ZLOG_DISABLED)
3341 return CMD_ERR_NO_MATCH;
3342
3343 zlog_default->default_lvl = new_level;
3344 for (i = 0; i < ZLOG_NUM_DESTS; i++)
3345 if (zlog_default->maxlvl[i] != ZLOG_DISABLED)
3346 zlog_default->maxlvl[i] = new_level;
3347 return CMD_SUCCESS;
3348}
3349
3350DEFUN_DEPRECATED (no_config_log_trap,
3351 no_config_log_trap_cmd,
3352 "no log trap [LEVEL]",
3353 NO_STR
3354 "Logging control\n"
3355 "Permit all logging information\n"
3356 "Logging level\n")
3357{
3358 zlog_default->default_lvl = LOG_DEBUG;
paul718e3742002-12-13 20:15:29 +00003359 return CMD_SUCCESS;
3360}
3361
3362DEFUN (config_log_record_priority,
3363 config_log_record_priority_cmd,
3364 "log record-priority",
3365 "Logging control\n"
3366 "Log the priority of the message within the message\n")
3367{
3368 zlog_default->record_priority = 1 ;
3369 return CMD_SUCCESS;
3370}
3371
3372DEFUN (no_config_log_record_priority,
3373 no_config_log_record_priority_cmd,
3374 "no log record-priority",
3375 NO_STR
3376 "Logging control\n"
3377 "Do not log the priority of the message within the message\n")
3378{
3379 zlog_default->record_priority = 0 ;
3380 return CMD_SUCCESS;
3381}
3382
3383
3384DEFUN (banner_motd_default,
3385 banner_motd_default_cmd,
3386 "banner motd default",
3387 "Set banner string\n"
3388 "Strings for motd\n"
3389 "Default string\n")
3390{
3391 host.motd = default_motd;
3392 return CMD_SUCCESS;
3393}
3394
3395DEFUN (no_banner_motd,
3396 no_banner_motd_cmd,
3397 "no banner motd",
3398 NO_STR
3399 "Set banner string\n"
3400 "Strings for motd\n")
3401{
3402 host.motd = NULL;
3403 return CMD_SUCCESS;
3404}
3405
3406/* Set config filename. Called from vty.c */
3407void
3408host_config_set (char *filename)
3409{
3410 host.config = strdup (filename);
3411}
3412
3413void
3414install_default (enum node_type node)
3415{
3416 install_element (node, &config_exit_cmd);
3417 install_element (node, &config_quit_cmd);
3418 install_element (node, &config_end_cmd);
3419 install_element (node, &config_help_cmd);
3420 install_element (node, &config_list_cmd);
3421
3422 install_element (node, &config_write_terminal_cmd);
3423 install_element (node, &config_write_file_cmd);
3424 install_element (node, &config_write_memory_cmd);
3425 install_element (node, &config_write_cmd);
3426 install_element (node, &show_running_config_cmd);
3427}
3428
3429/* Initialize command interface. Install basic nodes and commands. */
3430void
3431cmd_init (int terminal)
3432{
3433 /* Allocate initial top vector of commands. */
3434 cmdvec = vector_init (VECTOR_MIN_SIZE);
3435
3436 /* Default host value settings. */
3437 host.name = NULL;
3438 host.password = NULL;
3439 host.enable = NULL;
3440 host.logfile = NULL;
3441 host.config = NULL;
3442 host.lines = -1;
3443 host.motd = default_motd;
3444
3445 /* Install top nodes. */
3446 install_node (&view_node, NULL);
3447 install_node (&enable_node, NULL);
3448 install_node (&auth_node, NULL);
3449 install_node (&auth_enable_node, NULL);
3450 install_node (&config_node, config_write_host);
3451
3452 /* Each node's basic commands. */
3453 install_element (VIEW_NODE, &show_version_cmd);
3454 if (terminal)
3455 {
3456 install_element (VIEW_NODE, &config_list_cmd);
3457 install_element (VIEW_NODE, &config_exit_cmd);
3458 install_element (VIEW_NODE, &config_quit_cmd);
3459 install_element (VIEW_NODE, &config_help_cmd);
3460 install_element (VIEW_NODE, &config_enable_cmd);
3461 install_element (VIEW_NODE, &config_terminal_length_cmd);
3462 install_element (VIEW_NODE, &config_terminal_no_length_cmd);
ajs274a4a42004-12-07 15:39:31 +00003463 install_element (VIEW_NODE, &show_logging_cmd);
paul718e3742002-12-13 20:15:29 +00003464 }
3465
3466 if (terminal)
3467 {
3468 install_default (ENABLE_NODE);
3469 install_element (ENABLE_NODE, &config_disable_cmd);
3470 install_element (ENABLE_NODE, &config_terminal_cmd);
3471 install_element (ENABLE_NODE, &copy_runningconfig_startupconfig_cmd);
3472 }
3473 install_element (ENABLE_NODE, &show_startup_config_cmd);
3474 install_element (ENABLE_NODE, &show_version_cmd);
paul718e3742002-12-13 20:15:29 +00003475
3476 if (terminal)
paul718e3742002-12-13 20:15:29 +00003477 {
hassoe7168df2004-10-03 20:11:32 +00003478 install_element (ENABLE_NODE, &config_terminal_length_cmd);
3479 install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
ajs274a4a42004-12-07 15:39:31 +00003480 install_element (ENABLE_NODE, &show_logging_cmd);
3481 install_element (ENABLE_NODE, &config_logmsg_cmd);
hassoe7168df2004-10-03 20:11:32 +00003482
3483 install_default (CONFIG_NODE);
hassoea8e9d92004-10-07 21:32:14 +00003484 }
3485
3486 install_element (CONFIG_NODE, &hostname_cmd);
3487 install_element (CONFIG_NODE, &no_hostname_cmd);
hassoe7168df2004-10-03 20:11:32 +00003488
hassoea8e9d92004-10-07 21:32:14 +00003489 if (terminal)
3490 {
hassoe7168df2004-10-03 20:11:32 +00003491 install_element (CONFIG_NODE, &password_cmd);
3492 install_element (CONFIG_NODE, &password_text_cmd);
3493 install_element (CONFIG_NODE, &enable_password_cmd);
3494 install_element (CONFIG_NODE, &enable_password_text_cmd);
3495 install_element (CONFIG_NODE, &no_enable_password_cmd);
3496
paul718e3742002-12-13 20:15:29 +00003497 install_element (CONFIG_NODE, &config_log_stdout_cmd);
ajs274a4a42004-12-07 15:39:31 +00003498 install_element (CONFIG_NODE, &config_log_stdout_level_cmd);
paul718e3742002-12-13 20:15:29 +00003499 install_element (CONFIG_NODE, &no_config_log_stdout_cmd);
ajs274a4a42004-12-07 15:39:31 +00003500 install_element (CONFIG_NODE, &config_log_monitor_cmd);
3501 install_element (CONFIG_NODE, &config_log_monitor_level_cmd);
3502 install_element (CONFIG_NODE, &no_config_log_monitor_cmd);
paul718e3742002-12-13 20:15:29 +00003503 install_element (CONFIG_NODE, &config_log_file_cmd);
ajs274a4a42004-12-07 15:39:31 +00003504 install_element (CONFIG_NODE, &config_log_file_level_cmd);
paul718e3742002-12-13 20:15:29 +00003505 install_element (CONFIG_NODE, &no_config_log_file_cmd);
ajs274a4a42004-12-07 15:39:31 +00003506 install_element (CONFIG_NODE, &no_config_log_file_level_cmd);
paul718e3742002-12-13 20:15:29 +00003507 install_element (CONFIG_NODE, &config_log_syslog_cmd);
ajs274a4a42004-12-07 15:39:31 +00003508 install_element (CONFIG_NODE, &config_log_syslog_level_cmd);
paul12ab19f2003-07-26 06:14:55 +00003509 install_element (CONFIG_NODE, &config_log_syslog_facility_cmd);
paul718e3742002-12-13 20:15:29 +00003510 install_element (CONFIG_NODE, &no_config_log_syslog_cmd);
paul12ab19f2003-07-26 06:14:55 +00003511 install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd);
ajs274a4a42004-12-07 15:39:31 +00003512 install_element (CONFIG_NODE, &config_log_facility_cmd);
3513 install_element (CONFIG_NODE, &no_config_log_facility_cmd);
paul718e3742002-12-13 20:15:29 +00003514 install_element (CONFIG_NODE, &config_log_trap_cmd);
3515 install_element (CONFIG_NODE, &no_config_log_trap_cmd);
3516 install_element (CONFIG_NODE, &config_log_record_priority_cmd);
3517 install_element (CONFIG_NODE, &no_config_log_record_priority_cmd);
3518 install_element (CONFIG_NODE, &service_password_encrypt_cmd);
3519 install_element (CONFIG_NODE, &no_service_password_encrypt_cmd);
3520 install_element (CONFIG_NODE, &banner_motd_default_cmd);
3521 install_element (CONFIG_NODE, &no_banner_motd_cmd);
3522 install_element (CONFIG_NODE, &service_terminal_length_cmd);
3523 install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
paul718e3742002-12-13 20:15:29 +00003524
paul9ab68122003-01-18 01:16:20 +00003525 install_element(VIEW_NODE, &show_thread_cpu_cmd);
3526 install_element(ENABLE_NODE, &show_thread_cpu_cmd);
3527 }
paul718e3742002-12-13 20:15:29 +00003528 srand(time(NULL));
3529}