~ubuntu-branches/ubuntu/warty/quagga/warty

« back to all changes in this revision

Viewing changes to lib/command.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-06-29 09:50:59 UTC
  • Revision ID: james.westby@ubuntu.com-20040629095059-px1m2m108z4qw1mr
Tags: upstream-0.96.5
ImportĀ upstreamĀ versionĀ 0.96.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Command interpreter routine for virtual terminal [aka TeletYpe]
 
2
   Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
 
3
 
 
4
This file is part of GNU Zebra.
 
5
 
 
6
GNU Zebra is free software; you can redistribute it and/or modify
 
7
it under the terms of the GNU General Public License as published
 
8
by the Free Software Foundation; either version 2, or (at your
 
9
option) any later version.
 
10
 
 
11
GNU Zebra is distributed in the hope that it will be useful, but
 
12
WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU General Public License
 
17
along with GNU Zebra; see the file COPYING.  If not, write to the
 
18
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
19
Boston, MA 02111-1307, USA.  */
 
20
 
 
21
#include <zebra.h>
 
22
 
 
23
 
 
24
#include "memory.h"
 
25
#include "log.h"
 
26
#include <lib/version.h>
 
27
#include "thread.h"
 
28
#include "vector.h"
 
29
#include "vty.h"
 
30
#include "command.h"
 
31
 
 
32
/* Command vector which includes some level of command lists. Normally
 
33
   each daemon maintains each own cmdvec. */
 
34
vector cmdvec;
 
35
 
 
36
/* Host information structure. */
 
37
struct host host;
 
38
 
 
39
/* Default motd string. */
 
40
char *default_motd = 
 
41
"\r\n\
 
42
Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\
 
43
Copyright 1996-2002 Kunihiro Ishiguro.\r\n\
 
44
\r\n";
 
45
 
 
46
/* Standard command node structures. */
 
47
struct cmd_node auth_node =
 
48
{
 
49
  AUTH_NODE,
 
50
  "Password: ",
 
51
};
 
52
 
 
53
struct cmd_node view_node =
 
54
{
 
55
  VIEW_NODE,
 
56
  "%s> ",
 
57
};
 
58
 
 
59
struct cmd_node auth_enable_node =
 
60
{
 
61
  AUTH_ENABLE_NODE,
 
62
  "Password: ",
 
63
};
 
64
 
 
65
struct cmd_node enable_node =
 
66
{
 
67
  ENABLE_NODE,
 
68
  "%s# ",
 
69
};
 
70
 
 
71
struct cmd_node config_node =
 
72
{
 
73
  CONFIG_NODE,
 
74
  "%s(config)# ",
 
75
  1
 
76
};
 
77
 
 
78
/* Utility function to concatenate argv argument into a single string
 
79
   with inserting ' ' character between each argument.  */
 
80
char *
 
81
argv_concat (char **argv, int argc, int shift)
 
82
{
 
83
  int i;
 
84
  int len;
 
85
  int index;
 
86
  char *str;
 
87
 
 
88
  str = NULL;
 
89
  index = 0;
 
90
 
 
91
  for (i = shift; i < argc; i++)
 
92
    {
 
93
      len = strlen (argv[i]);
 
94
 
 
95
      if (i == shift)
 
96
        {
 
97
          str = XSTRDUP (MTYPE_TMP, argv[i]);
 
98
          index = len;
 
99
        }
 
100
      else
 
101
        {
 
102
          str = XREALLOC (MTYPE_TMP, str, (index + len + 2));
 
103
          str[index++] = ' ';
 
104
          memcpy (str + index, argv[i], len);
 
105
          index += len;
 
106
          str[index] = '\0';
 
107
        }
 
108
    }
 
109
  return str;
 
110
}
 
111
 
 
112
/* Install top node of command vector. */
 
113
void
 
114
install_node (struct cmd_node *node, 
 
115
              int (*func) (struct vty *))
 
116
{
 
117
  vector_set_index (cmdvec, node->node, node);
 
118
  node->func = func;
 
119
  node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
 
120
}
 
121
 
 
122
/* Compare two command's string.  Used in sort_node (). */
 
123
int
 
124
cmp_node (const void *p, const void *q)
 
125
{
 
126
  struct cmd_element *a = *(struct cmd_element **)p;
 
127
  struct cmd_element *b = *(struct cmd_element **)q;
 
128
 
 
129
  return strcmp (a->string, b->string);
 
130
}
 
131
 
 
132
int
 
133
cmp_desc (const void *p, const void *q)
 
134
{
 
135
  struct desc *a = *(struct desc **)p;
 
136
  struct desc *b = *(struct desc **)q;
 
137
 
 
138
  return strcmp (a->cmd, b->cmd);
 
139
}
 
140
 
 
141
/* Sort each node's command element according to command string. */
 
142
void
 
143
sort_node ()
 
144
{
 
145
  int i, j;
 
146
  struct cmd_node *cnode;
 
147
  vector descvec;
 
148
  struct cmd_element *cmd_element;
 
149
 
 
150
  for (i = 0; i < vector_max (cmdvec); i++) 
 
151
    if ((cnode = vector_slot (cmdvec, i)) != NULL)
 
152
      { 
 
153
        vector cmd_vector = cnode->cmd_vector;
 
154
        qsort (cmd_vector->index, cmd_vector->max, sizeof (void *), cmp_node);
 
155
 
 
156
        for (j = 0; j < vector_max (cmd_vector); j++)
 
157
          if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
 
158
            {
 
159
              descvec = vector_slot (cmd_element->strvec,
 
160
                                     vector_max (cmd_element->strvec) - 1);
 
161
              qsort (descvec->index, descvec->max, sizeof (void *), cmp_desc);
 
162
            }
 
163
      }
 
164
}
 
165
 
 
166
/* Breaking up string into each command piece. I assume given
 
167
   character is separated by a space character. Return value is a
 
168
   vector which includes char ** data element. */
 
169
vector
 
170
cmd_make_strvec (char *string)
 
171
{
 
172
  char *cp, *start, *token;
 
173
  int strlen;
 
174
  vector strvec;
 
175
  
 
176
  if (string == NULL)
 
177
    return NULL;
 
178
  
 
179
  cp = string;
 
180
 
 
181
  /* Skip white spaces. */
 
182
  while (isspace ((int) *cp) && *cp != '\0')
 
183
    cp++;
 
184
 
 
185
  /* Return if there is only white spaces */
 
186
  if (*cp == '\0')
 
187
    return NULL;
 
188
 
 
189
  if (*cp == '!' || *cp == '#')
 
190
    return NULL;
 
191
 
 
192
  /* Prepare return vector. */
 
193
  strvec = vector_init (VECTOR_MIN_SIZE);
 
194
 
 
195
  /* Copy each command piece and set into vector. */
 
196
  while (1) 
 
197
    {
 
198
      start = cp;
 
199
      while (!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') &&
 
200
             *cp != '\0')
 
201
        cp++;
 
202
      strlen = cp - start;
 
203
      token = XMALLOC (MTYPE_STRVEC, strlen + 1);
 
204
      memcpy (token, start, strlen);
 
205
      *(token + strlen) = '\0';
 
206
      vector_set (strvec, token);
 
207
 
 
208
      while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r') &&
 
209
             *cp != '\0')
 
210
        cp++;
 
211
 
 
212
      if (*cp == '\0')
 
213
        return strvec;
 
214
    }
 
215
}
 
216
 
 
217
/* Free allocated string vector. */
 
218
void
 
219
cmd_free_strvec (vector v)
 
220
{
 
221
  int i;
 
222
  char *cp;
 
223
 
 
224
  if (!v)
 
225
    return;
 
226
 
 
227
  for (i = 0; i < vector_max (v); i++)
 
228
    if ((cp = vector_slot (v, i)) != NULL)
 
229
      XFREE (MTYPE_STRVEC, cp);
 
230
 
 
231
  vector_free (v);
 
232
}
 
233
 
 
234
/* Fetch next description.  Used in cmd_make_descvec(). */
 
235
char *
 
236
cmd_desc_str (char **string)
 
237
{
 
238
  char *cp, *start, *token;
 
239
  int strlen;
 
240
  
 
241
  cp = *string;
 
242
 
 
243
  if (cp == NULL)
 
244
    return NULL;
 
245
 
 
246
  /* Skip white spaces. */
 
247
  while (isspace ((int) *cp) && *cp != '\0')
 
248
    cp++;
 
249
 
 
250
  /* Return if there is only white spaces */
 
251
  if (*cp == '\0')
 
252
    return NULL;
 
253
 
 
254
  start = cp;
 
255
 
 
256
  while (!(*cp == '\r' || *cp == '\n') && *cp != '\0')
 
257
    cp++;
 
258
 
 
259
  strlen = cp - start;
 
260
  token = XMALLOC (MTYPE_STRVEC, strlen + 1);
 
261
  memcpy (token, start, strlen);
 
262
  *(token + strlen) = '\0';
 
263
 
 
264
  *string = cp;
 
265
 
 
266
  return token;
 
267
}
 
268
 
 
269
/* New string vector. */
 
270
vector
 
271
cmd_make_descvec (char *string, char *descstr)
 
272
{
 
273
  int multiple = 0;
 
274
  char *sp;
 
275
  char *token;
 
276
  int len;
 
277
  char *cp;
 
278
  char *dp;
 
279
  vector allvec;
 
280
  vector strvec = NULL;
 
281
  struct desc *desc;
 
282
 
 
283
  cp = string;
 
284
  dp = descstr;
 
285
 
 
286
  if (cp == NULL)
 
287
    return NULL;
 
288
 
 
289
  allvec = vector_init (VECTOR_MIN_SIZE);
 
290
 
 
291
  while (1)
 
292
    {
 
293
      while (isspace ((int) *cp) && *cp != '\0')
 
294
        cp++;
 
295
 
 
296
      if (*cp == '(')
 
297
        {
 
298
          multiple = 1;
 
299
          cp++;
 
300
        }
 
301
      if (*cp == ')')
 
302
        {
 
303
          multiple = 0;
 
304
          cp++;
 
305
        }
 
306
      if (*cp == '|')
 
307
        {
 
308
          if (! multiple)
 
309
            {
 
310
              fprintf (stderr, "Command parse error!: %s\n", string);
 
311
              exit (1);
 
312
            }
 
313
          cp++;
 
314
        }
 
315
      
 
316
      while (isspace ((int) *cp) && *cp != '\0')
 
317
        cp++;
 
318
 
 
319
      if (*cp == '(')
 
320
        {
 
321
          multiple = 1;
 
322
          cp++;
 
323
        }
 
324
 
 
325
      if (*cp == '\0') 
 
326
        return allvec;
 
327
 
 
328
      sp = cp;
 
329
 
 
330
      while (! (isspace ((int) *cp) || *cp == '\r' || *cp == '\n' || *cp == ')' || *cp == '|') && *cp != '\0')
 
331
        cp++;
 
332
 
 
333
      len = cp - sp;
 
334
 
 
335
      token = XMALLOC (MTYPE_STRVEC, len + 1);
 
336
      memcpy (token, sp, len);
 
337
      *(token + len) = '\0';
 
338
 
 
339
      desc = XCALLOC (MTYPE_DESC, sizeof (struct desc));
 
340
      desc->cmd = token;
 
341
      desc->str = cmd_desc_str (&dp);
 
342
 
 
343
      if (multiple)
 
344
        {
 
345
          if (multiple == 1)
 
346
            {
 
347
              strvec = vector_init (VECTOR_MIN_SIZE);
 
348
              vector_set (allvec, strvec);
 
349
            }
 
350
          multiple++;
 
351
        }
 
352
      else
 
353
        {
 
354
          strvec = vector_init (VECTOR_MIN_SIZE);
 
355
          vector_set (allvec, strvec);
 
356
        }
 
357
      vector_set (strvec, desc);
 
358
    }
 
359
}
 
360
 
 
361
/* Count mandantory string vector size.  This is to determine inputed
 
362
   command has enough command length. */
 
363
int
 
364
cmd_cmdsize (vector strvec)
 
365
{
 
366
  int i;
 
367
  char *str;
 
368
  int size = 0;
 
369
  vector descvec;
 
370
 
 
371
  for (i = 0; i < vector_max (strvec); i++)
 
372
    {
 
373
      descvec = vector_slot (strvec, i);
 
374
 
 
375
      if (vector_max (descvec) == 1)
 
376
        {
 
377
          struct desc *desc = vector_slot (descvec, 0);
 
378
 
 
379
          str = desc->cmd;
 
380
          
 
381
          if (str == NULL || CMD_OPTION (str))
 
382
            return size;
 
383
          else
 
384
            size++;
 
385
        }
 
386
      else
 
387
        size++;
 
388
    }
 
389
  return size;
 
390
}
 
391
 
 
392
/* Return prompt character of specified node. */
 
393
char *
 
394
cmd_prompt (enum node_type node)
 
395
{
 
396
  struct cmd_node *cnode;
 
397
 
 
398
  cnode = vector_slot (cmdvec, node);
 
399
  return cnode->prompt;
 
400
}
 
401
 
 
402
/* Install a command into a node. */
 
403
void
 
404
install_element (enum node_type ntype, struct cmd_element *cmd)
 
405
{
 
406
  struct cmd_node *cnode;
 
407
 
 
408
  cnode = vector_slot (cmdvec, ntype);
 
409
 
 
410
  if (cnode == NULL) 
 
411
    {
 
412
      fprintf (stderr, "Command node %d doesn't exist, please check it\n",
 
413
               ntype);
 
414
      exit (1);
 
415
    }
 
416
 
 
417
  vector_set (cnode->cmd_vector, cmd);
 
418
 
 
419
  cmd->strvec = cmd_make_descvec (cmd->string, cmd->doc);
 
420
  cmd->cmdsize = cmd_cmdsize (cmd->strvec);
 
421
}
 
422
 
 
423
static unsigned char itoa64[] = 
 
424
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
425
 
 
426
void
 
427
to64(char *s, long v, int n)
 
428
{
 
429
  while (--n >= 0) 
 
430
    {
 
431
      *s++ = itoa64[v&0x3f];
 
432
      v >>= 6;
 
433
    }
 
434
}
 
435
 
 
436
char *zencrypt (char *passwd)
 
437
{
 
438
  char salt[6];
 
439
  struct timeval tv;
 
440
  char *crypt (const char *, const char *);
 
441
 
 
442
  gettimeofday(&tv,0);
 
443
  
 
444
  to64(&salt[0], random(), 3);
 
445
  to64(&salt[3], tv.tv_usec, 3);
 
446
  salt[5] = '\0';
 
447
 
 
448
  return crypt (passwd, salt);
 
449
}
 
450
 
 
451
char *
 
452
syslog_facility_print (int facility)
 
453
{
 
454
  switch (facility)
 
455
    {
 
456
      case LOG_KERN:
 
457
        return "kern";
 
458
        break;
 
459
      case LOG_USER:
 
460
        return "user";
 
461
        break;
 
462
      case LOG_MAIL:
 
463
        return "mail";
 
464
        break;
 
465
      case LOG_DAEMON:
 
466
        return "daemon";
 
467
        break;
 
468
      case LOG_AUTH:
 
469
        return "auth";
 
470
        break;
 
471
      case LOG_SYSLOG:
 
472
        return "syslog";
 
473
        break;
 
474
      case LOG_LPR:
 
475
        return "lpr";
 
476
        break;
 
477
      case LOG_NEWS:
 
478
        return "news";
 
479
        break;
 
480
      case LOG_UUCP:
 
481
        return "uucp";
 
482
        break;
 
483
      case LOG_CRON:
 
484
        return "cron";
 
485
        break;
 
486
      case LOG_LOCAL0:
 
487
        return "local0";
 
488
        break;
 
489
      case LOG_LOCAL1:
 
490
        return "local1";
 
491
        break;
 
492
      case LOG_LOCAL2:
 
493
        return "local2";
 
494
        break;
 
495
      case LOG_LOCAL3:
 
496
        return "local3";
 
497
        break;
 
498
      case LOG_LOCAL4:
 
499
        return "local4";
 
500
        break;
 
501
      case LOG_LOCAL5:
 
502
        return "local5";
 
503
        break;
 
504
      case LOG_LOCAL6:
 
505
        return "local6";
 
506
        break;
 
507
      case LOG_LOCAL7:
 
508
        return "local7";
 
509
        break;
 
510
      default:
 
511
        break;
 
512
    }
 
513
  return "";
 
514
}
 
515
 
 
516
/* This function write configuration of this host. */
 
517
int
 
518
config_write_host (struct vty *vty)
 
519
{
 
520
  if (host.name)
 
521
    vty_out (vty, "hostname %s%s", host.name, VTY_NEWLINE);
 
522
 
 
523
  if (host.encrypt)
 
524
    {
 
525
      if (host.password_encrypt)
 
526
        vty_out (vty, "password 8 %s%s", host.password_encrypt, VTY_NEWLINE); 
 
527
      if (host.enable_encrypt)
 
528
        vty_out (vty, "enable password 8 %s%s", host.enable_encrypt, VTY_NEWLINE); 
 
529
    }
 
530
  else
 
531
    {
 
532
      if (host.password)
 
533
        vty_out (vty, "password %s%s", host.password, VTY_NEWLINE);
 
534
      if (host.enable)
 
535
        vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE);
 
536
    }
 
537
 
 
538
  if (host.logfile)
 
539
    vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE);
 
540
 
 
541
  if (host.log_stdout)
 
542
    vty_out (vty, "log stdout%s", VTY_NEWLINE);
 
543
 
 
544
  if (host.log_syslog)
 
545
    {
 
546
      vty_out (vty, "log syslog");
 
547
      if (zlog_default->facility != LOG_DAEMON)
 
548
        vty_out (vty, " facility %s", syslog_facility_print (zlog_default->facility));
 
549
      vty_out (vty, "%s", VTY_NEWLINE);
 
550
    }
 
551
  if (zlog_default->maskpri != LOG_DEBUG)
 
552
    vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], VTY_NEWLINE);
 
553
 
 
554
  if (zlog_default->record_priority == 1)
 
555
    vty_out (vty, "log record-priority%s", VTY_NEWLINE);
 
556
 
 
557
  if (host.advanced)
 
558
    vty_out (vty, "service advanced-vty%s", VTY_NEWLINE);
 
559
 
 
560
  if (host.encrypt)
 
561
    vty_out (vty, "service password-encryption%s", VTY_NEWLINE);
 
562
 
 
563
  if (host.lines >= 0)
 
564
    vty_out (vty, "service terminal-length %d%s", host.lines,
 
565
             VTY_NEWLINE);
 
566
 
 
567
  if (! host.motd)
 
568
    vty_out (vty, "no banner motd%s", VTY_NEWLINE);
 
569
 
 
570
  return 1;
 
571
}
 
572
 
 
573
/* Utility function for getting command vector. */
 
574
vector
 
575
cmd_node_vector (vector v, enum node_type ntype)
 
576
{
 
577
  struct cmd_node *cnode = vector_slot (v, ntype);
 
578
  return cnode->cmd_vector;
 
579
}
 
580
 
 
581
/* Filter command vector by symbol */
 
582
int
 
583
cmd_filter_by_symbol (char *command, char *symbol)
 
584
{
 
585
  int i, lim;
 
586
 
 
587
  if (strcmp (symbol, "IPV4_ADDRESS") == 0)
 
588
    {
 
589
      i = 0;
 
590
      lim = strlen (command);
 
591
      while (i < lim)
 
592
        {
 
593
          if (! (isdigit ((int) command[i]) || command[i] == '.' || command[i] == '/'))
 
594
            return 1;
 
595
          i++;
 
596
        }
 
597
      return 0;
 
598
    }
 
599
  if (strcmp (symbol, "STRING") == 0)
 
600
    {
 
601
      i = 0;
 
602
      lim = strlen (command);
 
603
      while (i < lim)
 
604
        {
 
605
          if (! (isalpha ((int) command[i]) || command[i] == '_' || command[i] == '-'))
 
606
            return 1;
 
607
          i++;
 
608
        }
 
609
      return 0;
 
610
    }
 
611
  if (strcmp (symbol, "IFNAME") == 0)
 
612
    {
 
613
      i = 0;
 
614
      lim = strlen (command);
 
615
      while (i < lim)
 
616
        {
 
617
          if (! isalnum ((int) command[i]))
 
618
            return 1;
 
619
          i++;
 
620
        }
 
621
      return 0;
 
622
    }
 
623
  return 0;
 
624
}
 
625
 
 
626
/* Completion match types. */
 
627
enum match_type 
 
628
{
 
629
  no_match,
 
630
  extend_match,
 
631
  ipv4_prefix_match,
 
632
  ipv4_match,
 
633
  ipv6_prefix_match,
 
634
  ipv6_match,
 
635
  range_match,
 
636
  vararg_match,
 
637
  partly_match,
 
638
  exact_match 
 
639
};
 
640
 
 
641
enum match_type
 
642
cmd_ipv4_match (char *str)
 
643
{
 
644
  char *sp;
 
645
  int dots = 0, nums = 0;
 
646
  char buf[4];
 
647
 
 
648
  if (str == NULL)
 
649
    return partly_match;
 
650
 
 
651
  for (;;)
 
652
    {
 
653
      memset (buf, 0, sizeof (buf));
 
654
      sp = str;
 
655
      while (*str != '\0')
 
656
        {
 
657
          if (*str == '.')
 
658
            {
 
659
              if (dots >= 3)
 
660
                return no_match;
 
661
 
 
662
              if (*(str + 1) == '.')
 
663
                return no_match;
 
664
 
 
665
              if (*(str + 1) == '\0')
 
666
                return partly_match;
 
667
 
 
668
              dots++;
 
669
              break;
 
670
            }
 
671
          if (!isdigit ((int) *str))
 
672
            return no_match;
 
673
 
 
674
          str++;
 
675
        }
 
676
 
 
677
      if (str - sp > 3)
 
678
        return no_match;
 
679
 
 
680
      strncpy (buf, sp, str - sp);
 
681
      if (atoi (buf) > 255)
 
682
        return no_match;
 
683
 
 
684
      nums++;
 
685
 
 
686
      if (*str == '\0')
 
687
        break;
 
688
 
 
689
      str++;
 
690
    }
 
691
 
 
692
  if (nums < 4)
 
693
    return partly_match;
 
694
 
 
695
  return exact_match;
 
696
}
 
697
 
 
698
enum match_type
 
699
cmd_ipv4_prefix_match (char *str)
 
700
{
 
701
  char *sp;
 
702
  int dots = 0;
 
703
  char buf[4];
 
704
 
 
705
  if (str == NULL)
 
706
    return partly_match;
 
707
 
 
708
  for (;;)
 
709
    {
 
710
      memset (buf, 0, sizeof (buf));
 
711
      sp = str;
 
712
      while (*str != '\0' && *str != '/')
 
713
        {
 
714
          if (*str == '.')
 
715
            {
 
716
              if (dots == 3)
 
717
                return no_match;
 
718
 
 
719
              if (*(str + 1) == '.' || *(str + 1) == '/')
 
720
                return no_match;
 
721
 
 
722
              if (*(str + 1) == '\0')
 
723
                return partly_match;
 
724
 
 
725
              dots++;
 
726
              break;
 
727
            }
 
728
 
 
729
          if (!isdigit ((int) *str))
 
730
            return no_match;
 
731
 
 
732
          str++;
 
733
        }
 
734
 
 
735
      if (str - sp > 3)
 
736
        return no_match;
 
737
 
 
738
      strncpy (buf, sp, str - sp);
 
739
      if (atoi (buf) > 255)
 
740
        return no_match;
 
741
 
 
742
      if (dots == 3)
 
743
        {
 
744
          if (*str == '/')
 
745
            {
 
746
              if (*(str + 1) == '\0')
 
747
                return partly_match;
 
748
 
 
749
              str++;
 
750
              break;
 
751
            }
 
752
          else if (*str == '\0')
 
753
            return partly_match;
 
754
        }
 
755
 
 
756
      if (*str == '\0')
 
757
        return partly_match;
 
758
 
 
759
      str++;
 
760
    }
 
761
 
 
762
  sp = str;
 
763
  while (*str != '\0')
 
764
    {
 
765
      if (!isdigit ((int) *str))
 
766
        return no_match;
 
767
 
 
768
      str++;
 
769
    }
 
770
 
 
771
  if (atoi (sp) > 32)
 
772
    return no_match;
 
773
 
 
774
  return exact_match;
 
775
}
 
776
 
 
777
#define IPV6_ADDR_STR           "0123456789abcdefABCDEF:.%"
 
778
#define IPV6_PREFIX_STR         "0123456789abcdefABCDEF:.%/"
 
779
#define STATE_START             1
 
780
#define STATE_COLON             2
 
781
#define STATE_DOUBLE            3
 
782
#define STATE_ADDR              4
 
783
#define STATE_DOT               5
 
784
#define STATE_SLASH             6
 
785
#define STATE_MASK              7
 
786
 
 
787
#ifdef HAVE_IPV6
 
788
 
 
789
enum match_type
 
790
cmd_ipv6_match (char *str)
 
791
{
 
792
  int state = STATE_START;
 
793
  int colons = 0, nums = 0, double_colon = 0;
 
794
  char *sp = NULL;
 
795
  struct sockaddr_in6 sin6_dummy;
 
796
  int ret;
 
797
 
 
798
  if (str == NULL)
 
799
    return partly_match;
 
800
 
 
801
  if (strspn (str, IPV6_ADDR_STR) != strlen (str))
 
802
    return no_match;
 
803
 
 
804
  /* use inet_pton that has a better support,
 
805
   * for example inet_pton can support the automatic addresses:
 
806
   *  ::1.2.3.4
 
807
   */
 
808
  ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
 
809
   
 
810
  if (ret == 1)
 
811
    return exact_match;
 
812
 
 
813
  while (*str != '\0')
 
814
    {
 
815
      switch (state)
 
816
        {
 
817
        case STATE_START:
 
818
          if (*str == ':')
 
819
            {
 
820
              if (*(str + 1) != ':' && *(str + 1) != '\0')
 
821
                return no_match;
 
822
              colons--;
 
823
              state = STATE_COLON;
 
824
            }
 
825
          else
 
826
            {
 
827
              sp = str;
 
828
              state = STATE_ADDR;
 
829
            }
 
830
 
 
831
          continue;
 
832
        case STATE_COLON:
 
833
          colons++;
 
834
          if (*(str + 1) == ':')
 
835
            state = STATE_DOUBLE;
 
836
          else
 
837
            {
 
838
              sp = str + 1;
 
839
              state = STATE_ADDR;
 
840
            }
 
841
          break;
 
842
        case STATE_DOUBLE:
 
843
          if (double_colon)
 
844
            return no_match;
 
845
 
 
846
          if (*(str + 1) == ':')
 
847
            return no_match;
 
848
          else
 
849
            {
 
850
              if (*(str + 1) != '\0')
 
851
                colons++;
 
852
              sp = str + 1;
 
853
              state = STATE_ADDR;
 
854
            }
 
855
 
 
856
          double_colon++;
 
857
          nums++;
 
858
          break;
 
859
        case STATE_ADDR:
 
860
          if (*(str + 1) == ':' || *(str + 1) == '\0')
 
861
            {
 
862
              if (str - sp > 3)
 
863
                return no_match;
 
864
 
 
865
              nums++;
 
866
              state = STATE_COLON;
 
867
            }
 
868
          if (*(str + 1) == '.')
 
869
            state = STATE_DOT;
 
870
          break;
 
871
        case STATE_DOT:
 
872
          state = STATE_ADDR;
 
873
          break;
 
874
        default:
 
875
          break;
 
876
        }
 
877
 
 
878
      if (nums > 8)
 
879
        return no_match;
 
880
 
 
881
      if (colons > 7)
 
882
        return no_match;
 
883
 
 
884
      str++;
 
885
    }
 
886
 
 
887
#if 0
 
888
  if (nums < 11)
 
889
    return partly_match;
 
890
#endif /* 0 */
 
891
 
 
892
  return exact_match;
 
893
}
 
894
 
 
895
enum match_type
 
896
cmd_ipv6_prefix_match (char *str)
 
897
{
 
898
  int state = STATE_START;
 
899
  int colons = 0, nums = 0, double_colon = 0;
 
900
  int mask;
 
901
  char *sp = NULL;
 
902
  char *endptr = NULL;
 
903
 
 
904
  if (str == NULL)
 
905
    return partly_match;
 
906
 
 
907
  if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
 
908
    return no_match;
 
909
 
 
910
  while (*str != '\0' && state != STATE_MASK)
 
911
    {
 
912
      switch (state)
 
913
        {
 
914
        case STATE_START:
 
915
          if (*str == ':')
 
916
            {
 
917
              if (*(str + 1) != ':' && *(str + 1) != '\0')
 
918
                return no_match;
 
919
              colons--;
 
920
              state = STATE_COLON;
 
921
            }
 
922
          else
 
923
            {
 
924
              sp = str;
 
925
              state = STATE_ADDR;
 
926
            }
 
927
 
 
928
          continue;
 
929
        case STATE_COLON:
 
930
          colons++;
 
931
          if (*(str + 1) == '/')
 
932
            return no_match;
 
933
          else if (*(str + 1) == ':')
 
934
            state = STATE_DOUBLE;
 
935
          else
 
936
            {
 
937
              sp = str + 1;
 
938
              state = STATE_ADDR;
 
939
            }
 
940
          break;
 
941
        case STATE_DOUBLE:
 
942
          if (double_colon)
 
943
            return no_match;
 
944
 
 
945
          if (*(str + 1) == ':')
 
946
            return no_match;
 
947
          else
 
948
            {
 
949
              if (*(str + 1) != '\0' && *(str + 1) != '/')
 
950
                colons++;
 
951
              sp = str + 1;
 
952
 
 
953
              if (*(str + 1) == '/')
 
954
                state = STATE_SLASH;
 
955
              else
 
956
                state = STATE_ADDR;
 
957
            }
 
958
 
 
959
          double_colon++;
 
960
          nums += 1;
 
961
          break;
 
962
        case STATE_ADDR:
 
963
          if (*(str + 1) == ':' || *(str + 1) == '.'
 
964
              || *(str + 1) == '\0' || *(str + 1) == '/')
 
965
            {
 
966
              if (str - sp > 3)
 
967
                return no_match;
 
968
 
 
969
              for (; sp <= str; sp++)
 
970
                if (*sp == '/')
 
971
                  return no_match;
 
972
 
 
973
              nums++;
 
974
 
 
975
              if (*(str + 1) == ':')
 
976
                state = STATE_COLON;
 
977
              else if (*(str + 1) == '.')
 
978
                state = STATE_DOT;
 
979
              else if (*(str + 1) == '/')
 
980
                state = STATE_SLASH;
 
981
            }
 
982
          break;
 
983
        case STATE_DOT:
 
984
          state = STATE_ADDR;
 
985
          break;
 
986
        case STATE_SLASH:
 
987
          if (*(str + 1) == '\0')
 
988
            return partly_match;
 
989
 
 
990
          state = STATE_MASK;
 
991
          break;
 
992
        default:
 
993
          break;
 
994
        }
 
995
 
 
996
      if (nums > 11)
 
997
        return no_match;
 
998
 
 
999
      if (colons > 7)
 
1000
        return no_match;
 
1001
 
 
1002
      str++;
 
1003
    }
 
1004
 
 
1005
  if (state < STATE_MASK)
 
1006
    return partly_match;
 
1007
 
 
1008
  mask = strtol (str, &endptr, 10);
 
1009
  if (*endptr != '\0')
 
1010
    return no_match;
 
1011
 
 
1012
  if (mask < 0 || mask > 128)
 
1013
    return no_match;
 
1014
  
 
1015
/* I don't know why mask < 13 makes command match partly.
 
1016
   Forgive me to make this comments. I Want to set static default route
 
1017
   because of lack of function to originate default in ospf6d; sorry
 
1018
       yasu
 
1019
  if (mask < 13)
 
1020
    return partly_match;
 
1021
*/
 
1022
 
 
1023
  return exact_match;
 
1024
}
 
1025
 
 
1026
#endif /* HAVE_IPV6  */
 
1027
 
 
1028
#define DECIMAL_STRLEN_MAX 10
 
1029
 
 
1030
int
 
1031
cmd_range_match (char *range, char *str)
 
1032
{
 
1033
  char *p;
 
1034
  char buf[DECIMAL_STRLEN_MAX + 1];
 
1035
  char *endptr = NULL;
 
1036
  unsigned long min, max, val;
 
1037
 
 
1038
  if (str == NULL)
 
1039
    return 1;
 
1040
 
 
1041
  val = strtoul (str, &endptr, 10);
 
1042
  if (*endptr != '\0')
 
1043
    return 0;
 
1044
 
 
1045
  range++;
 
1046
  p = strchr (range, '-');
 
1047
  if (p == NULL)
 
1048
    return 0;
 
1049
  if (p - range > DECIMAL_STRLEN_MAX)
 
1050
    return 0;
 
1051
  strncpy (buf, range, p - range);
 
1052
  buf[p - range] = '\0';
 
1053
  min = strtoul (buf, &endptr, 10);
 
1054
  if (*endptr != '\0')
 
1055
    return 0;
 
1056
 
 
1057
  range = p + 1;
 
1058
  p = strchr (range, '>');
 
1059
  if (p == NULL)
 
1060
    return 0;
 
1061
  if (p - range > DECIMAL_STRLEN_MAX)
 
1062
    return 0;
 
1063
  strncpy (buf, range, p - range);
 
1064
  buf[p - range] = '\0';
 
1065
  max = strtoul (buf, &endptr, 10);
 
1066
  if (*endptr != '\0')
 
1067
    return 0;
 
1068
 
 
1069
  if (val < min || val > max)
 
1070
    return 0;
 
1071
 
 
1072
  return 1;
 
1073
}
 
1074
 
 
1075
/* Make completion match and return match type flag. */
 
1076
enum match_type
 
1077
cmd_filter_by_completion (char *command, vector v, int index)
 
1078
{
 
1079
  int i;
 
1080
  char *str;
 
1081
  struct cmd_element *cmd_element;
 
1082
  enum match_type match_type;
 
1083
  vector descvec;
 
1084
  struct desc *desc;
 
1085
  
 
1086
  match_type = no_match;
 
1087
 
 
1088
  /* If command and cmd_element string does not match set NULL to vector */
 
1089
  for (i = 0; i < vector_max (v); i++) 
 
1090
    if ((cmd_element = vector_slot (v, i)) != NULL)
 
1091
      {
 
1092
        if (index >= vector_max (cmd_element->strvec))
 
1093
          vector_slot (v, i) = NULL;
 
1094
        else
 
1095
          {
 
1096
            int j;
 
1097
            int matched = 0;
 
1098
 
 
1099
            descvec = vector_slot (cmd_element->strvec, index);
 
1100
            
 
1101
            for (j = 0; j < vector_max (descvec); j++)
 
1102
              {
 
1103
                desc = vector_slot (descvec, j);
 
1104
                str = desc->cmd;
 
1105
 
 
1106
                if (CMD_VARARG (str))
 
1107
                  {
 
1108
                    if (match_type < vararg_match)
 
1109
                      match_type = vararg_match;
 
1110
                    matched++;
 
1111
                  }
 
1112
                else if (CMD_RANGE (str))
 
1113
                  {
 
1114
                    if (cmd_range_match (str, command))
 
1115
                      {
 
1116
                        if (match_type < range_match)
 
1117
                          match_type = range_match;
 
1118
 
 
1119
                        matched++;
 
1120
                      }
 
1121
                  }
 
1122
#ifdef HAVE_IPV6
 
1123
                else if (CMD_IPV6 (str))
 
1124
                  {
 
1125
                    if (cmd_ipv6_match (command))
 
1126
                      {
 
1127
                        if (match_type < ipv6_match)
 
1128
                          match_type = ipv6_match;
 
1129
 
 
1130
                        matched++;
 
1131
                      }
 
1132
                  }
 
1133
                else if (CMD_IPV6_PREFIX (str))
 
1134
                  {
 
1135
                    if (cmd_ipv6_prefix_match (command))
 
1136
                      {
 
1137
                        if (match_type < ipv6_prefix_match)
 
1138
                          match_type = ipv6_prefix_match;
 
1139
 
 
1140
                        matched++;
 
1141
                      }
 
1142
                  }
 
1143
#endif   /* HAVE_IPV6  */
 
1144
                else if (CMD_IPV4 (str))
 
1145
                  {
 
1146
                    if (cmd_ipv4_match (command))
 
1147
                      {
 
1148
                        if (match_type < ipv4_match)
 
1149
                          match_type = ipv4_match;
 
1150
 
 
1151
                        matched++;
 
1152
                      }
 
1153
                  }
 
1154
                else if (CMD_IPV4_PREFIX (str))
 
1155
                  {
 
1156
                    if (cmd_ipv4_prefix_match (command))
 
1157
                      {
 
1158
                        if (match_type < ipv4_prefix_match)
 
1159
                          match_type = ipv4_prefix_match;
 
1160
                        matched++;
 
1161
                      }
 
1162
                  }
 
1163
                else
 
1164
                /* Check is this point's argument optional ? */
 
1165
                if (CMD_OPTION (str) || CMD_VARIABLE (str))
 
1166
                  {
 
1167
                    if (match_type < extend_match)
 
1168
                      match_type = extend_match;
 
1169
                    matched++;
 
1170
                  }
 
1171
                else if (strncmp (command, str, strlen (command)) == 0)
 
1172
                  {
 
1173
                    if (strcmp (command, str) == 0) 
 
1174
                      match_type = exact_match;
 
1175
                    else
 
1176
                      {
 
1177
                        if (match_type < partly_match)
 
1178
                          match_type = partly_match;
 
1179
                      }
 
1180
                    matched++;
 
1181
                  }
 
1182
              }
 
1183
            if (! matched)
 
1184
              vector_slot (v, i) = NULL;
 
1185
          }
 
1186
      }
 
1187
  return match_type;
 
1188
}
 
1189
 
 
1190
/* Filter vector by command character with index. */
 
1191
enum match_type
 
1192
cmd_filter_by_string (char *command, vector v, int index)
 
1193
{
 
1194
  int i;
 
1195
  char *str;
 
1196
  struct cmd_element *cmd_element;
 
1197
  enum match_type match_type;
 
1198
  vector descvec;
 
1199
  struct desc *desc;
 
1200
  
 
1201
  match_type = no_match;
 
1202
 
 
1203
  /* If command and cmd_element string does not match set NULL to vector */
 
1204
  for (i = 0; i < vector_max (v); i++) 
 
1205
    if ((cmd_element = vector_slot (v, i)) != NULL)
 
1206
      {
 
1207
        /* If given index is bigger than max string vector of command,
 
1208
           set NULL*/
 
1209
        if (index >= vector_max (cmd_element->strvec))
 
1210
          vector_slot (v, i) = NULL;
 
1211
        else 
 
1212
          {
 
1213
            int j;
 
1214
            int matched = 0;
 
1215
 
 
1216
            descvec = vector_slot (cmd_element->strvec, index);
 
1217
 
 
1218
            for (j = 0; j < vector_max (descvec); j++)
 
1219
              {
 
1220
                desc = vector_slot (descvec, j);
 
1221
                str = desc->cmd;
 
1222
 
 
1223
                if (CMD_VARARG (str))
 
1224
                  {
 
1225
                    if (match_type < vararg_match)
 
1226
                      match_type = vararg_match;
 
1227
                    matched++;
 
1228
                  }
 
1229
                else if (CMD_RANGE (str))
 
1230
                  {
 
1231
                    if (cmd_range_match (str, command))
 
1232
                      {
 
1233
                        if (match_type < range_match)
 
1234
                          match_type = range_match;
 
1235
                        matched++;
 
1236
                      }
 
1237
                  }
 
1238
#ifdef HAVE_IPV6
 
1239
                else if (CMD_IPV6 (str))
 
1240
                  {
 
1241
                    if (cmd_ipv6_match (command) == exact_match)
 
1242
                      {
 
1243
                        if (match_type < ipv6_match)
 
1244
                          match_type = ipv6_match;
 
1245
                        matched++;
 
1246
                      }
 
1247
                  }
 
1248
                else if (CMD_IPV6_PREFIX (str))
 
1249
                  {
 
1250
                    if (cmd_ipv6_prefix_match (command) == exact_match)
 
1251
                      {
 
1252
                        if (match_type < ipv6_prefix_match)
 
1253
                          match_type = ipv6_prefix_match;
 
1254
                        matched++;
 
1255
                      }
 
1256
                  }
 
1257
#endif /* HAVE_IPV6  */
 
1258
                else if (CMD_IPV4 (str))
 
1259
                  {
 
1260
                    if (cmd_ipv4_match (command) == exact_match)
 
1261
                      {
 
1262
                        if (match_type < ipv4_match)
 
1263
                          match_type = ipv4_match;
 
1264
                        matched++;
 
1265
                      }
 
1266
                  }
 
1267
                else if (CMD_IPV4_PREFIX (str))
 
1268
                  {
 
1269
                    if (cmd_ipv4_prefix_match (command) == exact_match)
 
1270
                      {
 
1271
                        if (match_type < ipv4_prefix_match)
 
1272
                          match_type = ipv4_prefix_match;
 
1273
                        matched++;
 
1274
                      }
 
1275
                  }
 
1276
                else if (CMD_OPTION (str) || CMD_VARIABLE (str))
 
1277
                  {
 
1278
                    if (match_type < extend_match)
 
1279
                      match_type = extend_match;
 
1280
                    matched++;
 
1281
                  }
 
1282
                else
 
1283
                  {               
 
1284
                    if (strcmp (command, str) == 0)
 
1285
                      {
 
1286
                        match_type = exact_match;
 
1287
                        matched++;
 
1288
                      }
 
1289
                  }
 
1290
              }
 
1291
            if (! matched)
 
1292
              vector_slot (v, i) = NULL;
 
1293
          }
 
1294
      }
 
1295
  return match_type;
 
1296
}
 
1297
 
 
1298
/* Check ambiguous match */
 
1299
int
 
1300
is_cmd_ambiguous (char *command, vector v, int index, enum match_type type)
 
1301
{
 
1302
  int i;
 
1303
  int j;
 
1304
  char *str = NULL;
 
1305
  struct cmd_element *cmd_element;
 
1306
  char *matched = NULL;
 
1307
  vector descvec;
 
1308
  struct desc *desc;
 
1309
  
 
1310
  for (i = 0; i < vector_max (v); i++) 
 
1311
    if ((cmd_element = vector_slot (v, i)) != NULL)
 
1312
      {
 
1313
        int match = 0;
 
1314
 
 
1315
        descvec = vector_slot (cmd_element->strvec, index);
 
1316
 
 
1317
        for (j = 0; j < vector_max (descvec); j++)
 
1318
          {
 
1319
            enum match_type ret;
 
1320
 
 
1321
            desc = vector_slot (descvec, j);
 
1322
            str = desc->cmd;
 
1323
 
 
1324
            switch (type)
 
1325
              {
 
1326
              case exact_match:
 
1327
                if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
 
1328
                    && strcmp (command, str) == 0)
 
1329
                  match++;
 
1330
                break;
 
1331
              case partly_match:
 
1332
                if (! (CMD_OPTION (str) || CMD_VARIABLE (str))
 
1333
                    && strncmp (command, str, strlen (command)) == 0)
 
1334
                  {
 
1335
                    if (matched && strcmp (matched, str) != 0)
 
1336
                      return 1; /* There is ambiguous match. */
 
1337
                    else
 
1338
                      matched = str;
 
1339
                    match++;
 
1340
                  }
 
1341
                break;
 
1342
              case range_match:
 
1343
                if (cmd_range_match (str, command))
 
1344
                  {
 
1345
                    if (matched && strcmp (matched, str) != 0)
 
1346
                      return 1;
 
1347
                    else
 
1348
                      matched = str;
 
1349
                    match++;
 
1350
                  }
 
1351
                break;
 
1352
#ifdef HAVE_IPV6                
 
1353
              case ipv6_match:
 
1354
                if (CMD_IPV6 (str))
 
1355
                  match++;
 
1356
                break;
 
1357
              case ipv6_prefix_match:
 
1358
                if ((ret = cmd_ipv6_prefix_match (command)) != no_match)
 
1359
                  {
 
1360
                    if (ret == partly_match)
 
1361
                      return 2; /* There is incomplete match. */
 
1362
 
 
1363
                    match++;
 
1364
                  }
 
1365
                break;
 
1366
#endif  /* HAVE_IPV6 */         
 
1367
              case ipv4_match:
 
1368
                if (CMD_IPV4 (str))
 
1369
                  match++;
 
1370
                break;
 
1371
              case ipv4_prefix_match:
 
1372
                if ((ret = cmd_ipv4_prefix_match (command)) != no_match)
 
1373
                  {
 
1374
                    if (ret == partly_match)
 
1375
                      return 2; /* There is incomplete match. */
 
1376
 
 
1377
                    match++;
 
1378
                  }
 
1379
                break;
 
1380
              case extend_match:
 
1381
                if (CMD_OPTION (str) || CMD_VARIABLE (str))
 
1382
                  match++;
 
1383
                break;
 
1384
              case no_match:
 
1385
              default:
 
1386
                break;
 
1387
              }
 
1388
          }
 
1389
        if (! match)
 
1390
          vector_slot (v, i) = NULL;
 
1391
      }
 
1392
  return 0;
 
1393
}
 
1394
 
 
1395
/* If src matches dst return dst string, otherwise return NULL */
 
1396
char *
 
1397
cmd_entry_function (char *src, char *dst)
 
1398
{
 
1399
  /* Skip variable arguments. */
 
1400
  if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) ||
 
1401
      CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst))
 
1402
    return NULL;
 
1403
 
 
1404
  /* In case of 'command \t', given src is NULL string. */
 
1405
  if (src == NULL)
 
1406
    return dst;
 
1407
 
 
1408
  /* Matched with input string. */
 
1409
  if (strncmp (src, dst, strlen (src)) == 0)
 
1410
    return dst;
 
1411
 
 
1412
  return NULL;
 
1413
}
 
1414
 
 
1415
/* If src matches dst return dst string, otherwise return NULL */
 
1416
/* This version will return the dst string always if it is
 
1417
   CMD_VARIABLE for '?' key processing */
 
1418
char *
 
1419
cmd_entry_function_desc (char *src, char *dst)
 
1420
{
 
1421
  if (CMD_VARARG (dst))
 
1422
    return dst;
 
1423
 
 
1424
  if (CMD_RANGE (dst))
 
1425
    {
 
1426
      if (cmd_range_match (dst, src))
 
1427
        return dst;
 
1428
      else
 
1429
        return NULL;
 
1430
    }
 
1431
 
 
1432
#ifdef HAVE_IPV6
 
1433
  if (CMD_IPV6 (dst))
 
1434
    {
 
1435
      if (cmd_ipv6_match (src))
 
1436
        return dst;
 
1437
      else
 
1438
        return NULL;
 
1439
    }
 
1440
 
 
1441
  if (CMD_IPV6_PREFIX (dst))
 
1442
    {
 
1443
      if (cmd_ipv6_prefix_match (src))
 
1444
        return dst;
 
1445
      else
 
1446
        return NULL;
 
1447
    }
 
1448
#endif /* HAVE_IPV6 */
 
1449
 
 
1450
  if (CMD_IPV4 (dst))
 
1451
    {
 
1452
      if (cmd_ipv4_match (src))
 
1453
        return dst;
 
1454
      else
 
1455
        return NULL;
 
1456
    }
 
1457
 
 
1458
  if (CMD_IPV4_PREFIX (dst))
 
1459
    {
 
1460
      if (cmd_ipv4_prefix_match (src))
 
1461
        return dst;
 
1462
      else
 
1463
        return NULL;
 
1464
    }
 
1465
 
 
1466
  /* Optional or variable commands always match on '?' */
 
1467
  if (CMD_OPTION (dst) || CMD_VARIABLE (dst))
 
1468
    return dst;
 
1469
 
 
1470
  /* In case of 'command \t', given src is NULL string. */
 
1471
  if (src == NULL)
 
1472
    return dst;
 
1473
 
 
1474
  if (strncmp (src, dst, strlen (src)) == 0)
 
1475
    return dst;
 
1476
  else
 
1477
    return NULL;
 
1478
}
 
1479
 
 
1480
/* Check same string element existence.  If it isn't there return
 
1481
    1. */
 
1482
int
 
1483
cmd_unique_string (vector v, char *str)
 
1484
{
 
1485
  int i;
 
1486
  char *match;
 
1487
 
 
1488
  for (i = 0; i < vector_max (v); i++)
 
1489
    if ((match = vector_slot (v, i)) != NULL)
 
1490
      if (strcmp (match, str) == 0)
 
1491
        return 0;
 
1492
  return 1;
 
1493
}
 
1494
 
 
1495
/* Compare string to description vector.  If there is same string
 
1496
   return 1 else return 0. */
 
1497
int
 
1498
desc_unique_string (vector v, char *str)
 
1499
{
 
1500
  int i;
 
1501
  struct desc *desc;
 
1502
 
 
1503
  for (i = 0; i < vector_max (v); i++)
 
1504
    if ((desc = vector_slot (v, i)) != NULL)
 
1505
      if (strcmp (desc->cmd, str) == 0)
 
1506
        return 1;
 
1507
  return 0;
 
1508
}
 
1509
 
 
1510
int 
 
1511
cmd_try_do_shortcut (enum node_type node, char* first_word) {
 
1512
  if ( first_word != NULL &&
 
1513
       node != AUTH_NODE &&
 
1514
       node != VIEW_NODE &&
 
1515
       node != AUTH_ENABLE_NODE &&
 
1516
       node != ENABLE_NODE &&
 
1517
       0 == strcmp( "do", first_word ) )
 
1518
    return 1;
 
1519
  return 0;
 
1520
}
 
1521
 
 
1522
/* '?' describe command support. */
 
1523
vector
 
1524
cmd_describe_command_real (vector vline, struct vty *vty, int *status)
 
1525
{
 
1526
  int i;
 
1527
  vector cmd_vector;
 
1528
#define INIT_MATCHVEC_SIZE 10
 
1529
  vector matchvec;
 
1530
  struct cmd_element *cmd_element;
 
1531
  int index;
 
1532
  int ret;
 
1533
  enum match_type match;
 
1534
  char *command;
 
1535
  static struct desc desc_cr = { "<cr>", "" };
 
1536
 
 
1537
  /* Set index. */
 
1538
  index = vector_max (vline) - 1;
 
1539
 
 
1540
  /* Make copy vector of current node's command vector. */
 
1541
  cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
 
1542
 
 
1543
  /* Prepare match vector */
 
1544
  matchvec = vector_init (INIT_MATCHVEC_SIZE);
 
1545
 
 
1546
  /* Filter commands. */
 
1547
  /* Only words precedes current word will be checked in this loop. */
 
1548
  for (i = 0; i < index; i++)
 
1549
    {
 
1550
      command = vector_slot (vline, i);
 
1551
      match = cmd_filter_by_completion (command, cmd_vector, i);
 
1552
 
 
1553
      if (match == vararg_match)
 
1554
        {
 
1555
          struct cmd_element *cmd_element;
 
1556
          vector descvec;
 
1557
          int j, k;
 
1558
 
 
1559
          for (j = 0; j < vector_max (cmd_vector); j++)
 
1560
            if ((cmd_element = vector_slot (cmd_vector, j)) != NULL)
 
1561
              {
 
1562
                descvec = vector_slot (cmd_element->strvec,
 
1563
                                       vector_max (cmd_element->strvec) - 1);
 
1564
                for (k = 0; k < vector_max (descvec); k++)
 
1565
                  {
 
1566
                    struct desc *desc = vector_slot (descvec, k);
 
1567
                    vector_set (matchvec, desc);
 
1568
                  }
 
1569
              }
 
1570
 
 
1571
          vector_set (matchvec, &desc_cr);
 
1572
          vector_free (cmd_vector);
 
1573
 
 
1574
          return matchvec;
 
1575
        }
 
1576
 
 
1577
      if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
 
1578
        {
 
1579
          vector_free (cmd_vector);
 
1580
          *status = CMD_ERR_AMBIGUOUS;
 
1581
          return NULL;
 
1582
        }
 
1583
      else if (ret == 2)
 
1584
        {
 
1585
          vector_free (cmd_vector);
 
1586
          *status = CMD_ERR_NO_MATCH;
 
1587
          return NULL;
 
1588
        }
 
1589
    }
 
1590
 
 
1591
  /* Prepare match vector */
 
1592
  /*  matchvec = vector_init (INIT_MATCHVEC_SIZE); */
 
1593
 
 
1594
  /* Make sure that cmd_vector is filtered based on current word */
 
1595
  command = vector_slot (vline, index);
 
1596
  if (command)
 
1597
    match = cmd_filter_by_completion (command, cmd_vector, index);
 
1598
 
 
1599
  /* Make description vector. */
 
1600
  for (i = 0; i < vector_max (cmd_vector); i++)
 
1601
    if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
 
1602
      {
 
1603
        char *string = NULL;
 
1604
        vector strvec = cmd_element->strvec;
 
1605
 
 
1606
        /* if command is NULL, index may be equal to vector_max */
 
1607
        if (command && index >= vector_max (strvec))
 
1608
          vector_slot (cmd_vector, i) = NULL;
 
1609
        else
 
1610
          {
 
1611
            /* Check if command is completed. */
 
1612
            if (command == NULL && index == vector_max (strvec))
 
1613
              {
 
1614
                string = "<cr>";
 
1615
                if (! desc_unique_string (matchvec, string))
 
1616
                  vector_set (matchvec, &desc_cr);
 
1617
              }
 
1618
            else
 
1619
              {
 
1620
                int j;
 
1621
                vector descvec = vector_slot (strvec, index);
 
1622
                struct desc *desc;
 
1623
 
 
1624
                for (j = 0; j < vector_max (descvec); j++)
 
1625
                  {
 
1626
                    desc = vector_slot (descvec, j);
 
1627
                    string = cmd_entry_function_desc (command, desc->cmd);
 
1628
                    if (string)
 
1629
                      {
 
1630
                        /* Uniqueness check */
 
1631
                        if (! desc_unique_string (matchvec, string))
 
1632
                          vector_set (matchvec, desc);
 
1633
                      }
 
1634
                  }
 
1635
              }
 
1636
          }
 
1637
      }
 
1638
  vector_free (cmd_vector);
 
1639
 
 
1640
  if (vector_slot (matchvec, 0) == NULL)
 
1641
    {
 
1642
      vector_free (matchvec);
 
1643
      *status= CMD_ERR_NO_MATCH;
 
1644
    }
 
1645
  else
 
1646
    *status = CMD_SUCCESS;
 
1647
 
 
1648
  return matchvec;
 
1649
}
 
1650
 
 
1651
vector
 
1652
cmd_describe_command (vector vline, struct vty *vty, int *status)
 
1653
{
 
1654
  vector ret;
 
1655
 
 
1656
  if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
 
1657
    {
 
1658
      enum node_type onode;
 
1659
      vector shifted_vline;
 
1660
      int index;
 
1661
 
 
1662
      onode = vty->node;
 
1663
      vty->node = ENABLE_NODE;
 
1664
      /* We can try it on enable node, cos' the vty is authenticated */
 
1665
 
 
1666
      shifted_vline = vector_init (vector_count(vline));
 
1667
      /* use memcpy? */
 
1668
      for (index = 1; index < vector_max (vline); index++) 
 
1669
        {
 
1670
          vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
 
1671
        }
 
1672
 
 
1673
      ret = cmd_describe_command_real (shifted_vline, vty, status);
 
1674
 
 
1675
      vector_free(shifted_vline);
 
1676
      vty->node = onode;
 
1677
      return ret;
 
1678
  }
 
1679
 
 
1680
 
 
1681
  return cmd_describe_command_real (vline, vty, status);
 
1682
}
 
1683
 
 
1684
 
 
1685
/* Check LCD of matched command. */
 
1686
int
 
1687
cmd_lcd (char **matched)
 
1688
{
 
1689
  int i;
 
1690
  int j;
 
1691
  int lcd = -1;
 
1692
  char *s1, *s2;
 
1693
  char c1, c2;
 
1694
 
 
1695
  if (matched[0] == NULL || matched[1] == NULL)
 
1696
    return 0;
 
1697
 
 
1698
  for (i = 1; matched[i] != NULL; i++)
 
1699
    {
 
1700
      s1 = matched[i - 1];
 
1701
      s2 = matched[i];
 
1702
 
 
1703
      for (j = 0; (c1 = s1[j]) && (c2 = s2[j]); j++)
 
1704
        if (c1 != c2)
 
1705
          break;
 
1706
 
 
1707
      if (lcd < 0)
 
1708
        lcd = j;
 
1709
      else
 
1710
        {
 
1711
          if (lcd > j)
 
1712
            lcd = j;
 
1713
        }
 
1714
    }
 
1715
  return lcd;
 
1716
}
 
1717
 
 
1718
/* Command line completion support. */
 
1719
char **
 
1720
cmd_complete_command_real (vector vline, struct vty *vty, int *status)
 
1721
{
 
1722
  int i;
 
1723
  vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
 
1724
#define INIT_MATCHVEC_SIZE 10
 
1725
  vector matchvec;
 
1726
  struct cmd_element *cmd_element;
 
1727
  int index = vector_max (vline) - 1;
 
1728
  char **match_str;
 
1729
  struct desc *desc;
 
1730
  vector descvec;
 
1731
  char *command;
 
1732
  int lcd;
 
1733
 
 
1734
  /* First, filter by preceeding command string */
 
1735
  for (i = 0; i < index; i++)
 
1736
    {
 
1737
      enum match_type match;
 
1738
      int ret;
 
1739
 
 
1740
      command = vector_slot (vline, i);
 
1741
 
 
1742
      /* First try completion match, if there is exactly match return 1 */
 
1743
      match = cmd_filter_by_completion (command, cmd_vector, i);
 
1744
 
 
1745
      /* If there is exact match then filter ambiguous match else check
 
1746
         ambiguousness. */
 
1747
      if ((ret = is_cmd_ambiguous (command, cmd_vector, i, match)) == 1)
 
1748
        {
 
1749
          vector_free (cmd_vector);
 
1750
          *status = CMD_ERR_AMBIGUOUS;
 
1751
          return NULL;
 
1752
        }
 
1753
      /*
 
1754
        else if (ret == 2)
 
1755
        {
 
1756
          vector_free (cmd_vector);
 
1757
          *status = CMD_ERR_NO_MATCH;
 
1758
          return NULL;
 
1759
        }
 
1760
      */
 
1761
    }
 
1762
 
 
1763
  /* Prepare match vector. */
 
1764
  matchvec = vector_init (INIT_MATCHVEC_SIZE);
 
1765
 
 
1766
  /* Now we got into completion */
 
1767
  for (i = 0; i < vector_max (cmd_vector); i++)
 
1768
    if ((cmd_element = vector_slot (cmd_vector, i)) != NULL)
 
1769
      {
 
1770
        char *string;
 
1771
        vector strvec = cmd_element->strvec;
 
1772
        
 
1773
        /* Check field length */
 
1774
        if (index >= vector_max (strvec))
 
1775
          vector_slot (cmd_vector, i) = NULL;
 
1776
        else 
 
1777
          {
 
1778
            int j;
 
1779
 
 
1780
            descvec = vector_slot (strvec, index);
 
1781
            for (j = 0; j < vector_max (descvec); j++)
 
1782
              {
 
1783
                desc = vector_slot (descvec, j);
 
1784
 
 
1785
                if ((string = cmd_entry_function (vector_slot (vline, index),
 
1786
                                                  desc->cmd)))
 
1787
                  if (cmd_unique_string (matchvec, string))
 
1788
                    vector_set (matchvec, XSTRDUP (MTYPE_TMP, string));
 
1789
              }
 
1790
          }
 
1791
      }
 
1792
 
 
1793
  /* We don't need cmd_vector any more. */
 
1794
  vector_free (cmd_vector);
 
1795
 
 
1796
  /* No matched command */
 
1797
  if (vector_slot (matchvec, 0) == NULL)
 
1798
    {
 
1799
      vector_free (matchvec);
 
1800
 
 
1801
      /* In case of 'command \t' pattern.  Do you need '?' command at
 
1802
         the end of the line. */
 
1803
      if (vector_slot (vline, index) == '\0')
 
1804
        *status = CMD_ERR_NOTHING_TODO;
 
1805
      else
 
1806
        *status = CMD_ERR_NO_MATCH;
 
1807
      return NULL;
 
1808
    }
 
1809
 
 
1810
  /* Only one matched */
 
1811
  if (vector_slot (matchvec, 1) == NULL)
 
1812
    {
 
1813
      match_str = (char **) matchvec->index;
 
1814
      vector_only_wrapper_free (matchvec);
 
1815
      *status = CMD_COMPLETE_FULL_MATCH;
 
1816
      return match_str;
 
1817
    }
 
1818
  /* Make it sure last element is NULL. */
 
1819
  vector_set (matchvec, NULL);
 
1820
 
 
1821
  /* Check LCD of matched strings. */
 
1822
  if (vector_slot (vline, index) != NULL)
 
1823
    {
 
1824
      lcd = cmd_lcd ((char **) matchvec->index);
 
1825
 
 
1826
      if (lcd)
 
1827
        {
 
1828
          int len = strlen (vector_slot (vline, index));
 
1829
          
 
1830
          if (len < lcd)
 
1831
            {
 
1832
              char *lcdstr;
 
1833
              
 
1834
              lcdstr = XMALLOC (MTYPE_TMP, lcd + 1);
 
1835
              memcpy (lcdstr, matchvec->index[0], lcd);
 
1836
              lcdstr[lcd] = '\0';
 
1837
 
 
1838
              /* match_str = (char **) &lcdstr; */
 
1839
 
 
1840
              /* Free matchvec. */
 
1841
              for (i = 0; i < vector_max (matchvec); i++)
 
1842
                {
 
1843
                  if (vector_slot (matchvec, i))
 
1844
                    XFREE (MTYPE_TMP, vector_slot (matchvec, i));
 
1845
                }
 
1846
              vector_free (matchvec);
 
1847
 
 
1848
              /* Make new matchvec. */
 
1849
              matchvec = vector_init (INIT_MATCHVEC_SIZE);
 
1850
              vector_set (matchvec, lcdstr);
 
1851
              match_str = (char **) matchvec->index;
 
1852
              vector_only_wrapper_free (matchvec);
 
1853
 
 
1854
              *status = CMD_COMPLETE_MATCH;
 
1855
              return match_str;
 
1856
            }
 
1857
        }
 
1858
    }
 
1859
 
 
1860
  match_str = (char **) matchvec->index;
 
1861
  vector_only_wrapper_free (matchvec);
 
1862
  *status = CMD_COMPLETE_LIST_MATCH;
 
1863
  return match_str;
 
1864
}
 
1865
 
 
1866
char **
 
1867
cmd_complete_command (vector vline, struct vty *vty, int *status)
 
1868
{
 
1869
  char **ret;
 
1870
 
 
1871
  if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
 
1872
    {
 
1873
      enum node_type onode;
 
1874
      vector shifted_vline;
 
1875
      int index;
 
1876
 
 
1877
      onode = vty->node;
 
1878
      vty->node = ENABLE_NODE;
 
1879
      /* We can try it on enable node, cos' the vty is authenticated */
 
1880
 
 
1881
      shifted_vline = vector_init (vector_count(vline));
 
1882
      /* use memcpy? */
 
1883
      for (index = 1; index < vector_max (vline); index++) 
 
1884
        {
 
1885
          vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
 
1886
        }
 
1887
 
 
1888
      ret = cmd_complete_command_real (shifted_vline, vty, status);
 
1889
 
 
1890
      vector_free(shifted_vline);
 
1891
      vty->node = onode;
 
1892
      return ret;
 
1893
  }
 
1894
 
 
1895
 
 
1896
  return cmd_complete_command_real (vline, vty, status);
 
1897
}
 
1898
 
 
1899
/* return parent node */
 
1900
/* MUST eventually converge on CONFIG_NODE */
 
1901
enum node_type node_parent ( enum node_type node )
 
1902
{
 
1903
  enum node_type ret;
 
1904
 
 
1905
  assert (node > CONFIG_NODE);
 
1906
 
 
1907
  switch (node)
 
1908
    {
 
1909
    case BGP_VPNV4_NODE:
 
1910
    case BGP_IPV4_NODE:
 
1911
    case BGP_IPV4M_NODE:
 
1912
    case BGP_IPV6_NODE:
 
1913
      ret = BGP_NODE;
 
1914
      break;
 
1915
    case KEYCHAIN_KEY_NODE:
 
1916
      ret = KEYCHAIN_NODE;
 
1917
      break;
 
1918
    default:
 
1919
      ret = CONFIG_NODE;
 
1920
    }
 
1921
 
 
1922
  return ret;
 
1923
}
 
1924
 
 
1925
/* Execute command by argument vline vector. */
 
1926
int
 
1927
cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd)
 
1928
{
 
1929
  int i;
 
1930
  int index;
 
1931
  vector cmd_vector;
 
1932
  struct cmd_element *cmd_element;
 
1933
  struct cmd_element *matched_element;
 
1934
  unsigned int matched_count, incomplete_count;
 
1935
  int argc;
 
1936
  char *argv[CMD_ARGC_MAX];
 
1937
  enum match_type match = 0;
 
1938
  int varflag;
 
1939
  char *command;
 
1940
 
 
1941
  /* Make copy of command elements. */
 
1942
  cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
 
1943
 
 
1944
  for (index = 0; index < vector_max (vline); index++) 
 
1945
    {
 
1946
      int ret;
 
1947
 
 
1948
      command = vector_slot (vline, index);
 
1949
 
 
1950
      match = cmd_filter_by_completion (command, cmd_vector, index);
 
1951
 
 
1952
      if (match == vararg_match)
 
1953
        break;
 
1954
 
 
1955
      ret = is_cmd_ambiguous (command, cmd_vector, index, match);
 
1956
 
 
1957
      if (ret == 1)
 
1958
        {
 
1959
          vector_free (cmd_vector);
 
1960
          return CMD_ERR_AMBIGUOUS;
 
1961
        }
 
1962
      else if (ret == 2)
 
1963
        {
 
1964
          vector_free (cmd_vector);
 
1965
          return CMD_ERR_NO_MATCH;
 
1966
        }
 
1967
    }
 
1968
 
 
1969
  /* Check matched count. */
 
1970
  matched_element = NULL;
 
1971
  matched_count = 0;
 
1972
  incomplete_count = 0;
 
1973
 
 
1974
  for (i = 0; i < vector_max (cmd_vector); i++) 
 
1975
    if (vector_slot (cmd_vector,i) != NULL)
 
1976
      {
 
1977
        cmd_element = vector_slot (cmd_vector,i);
 
1978
 
 
1979
        if (match == vararg_match || index >= cmd_element->cmdsize)
 
1980
          {
 
1981
            matched_element = cmd_element;
 
1982
#if 0
 
1983
            printf ("DEBUG: %s\n", cmd_element->string);
 
1984
#endif
 
1985
            matched_count++;
 
1986
          }
 
1987
        else
 
1988
          {
 
1989
            incomplete_count++;
 
1990
          }
 
1991
      }
 
1992
  
 
1993
  /* Finish of using cmd_vector. */
 
1994
  vector_free (cmd_vector);
 
1995
 
 
1996
  /* To execute command, matched_count must be 1.*/
 
1997
  if (matched_count == 0) 
 
1998
    {
 
1999
      if (incomplete_count)
 
2000
        return CMD_ERR_INCOMPLETE;
 
2001
      else
 
2002
        return CMD_ERR_NO_MATCH;
 
2003
    }
 
2004
 
 
2005
  if (matched_count > 1) 
 
2006
    return CMD_ERR_AMBIGUOUS;
 
2007
 
 
2008
  /* Argument treatment */
 
2009
  varflag = 0;
 
2010
  argc = 0;
 
2011
 
 
2012
  for (i = 0; i < vector_max (vline); i++)
 
2013
    {
 
2014
      if (varflag)
 
2015
        argv[argc++] = vector_slot (vline, i);
 
2016
      else
 
2017
        {         
 
2018
          vector descvec = vector_slot (matched_element->strvec, i);
 
2019
 
 
2020
          if (vector_max (descvec) == 1)
 
2021
            {
 
2022
              struct desc *desc = vector_slot (descvec, 0);
 
2023
              char *str = desc->cmd;
 
2024
 
 
2025
              if (CMD_VARARG (str))
 
2026
                varflag = 1;
 
2027
 
 
2028
              if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str))
 
2029
                argv[argc++] = vector_slot (vline, i);
 
2030
            }
 
2031
          else
 
2032
            argv[argc++] = vector_slot (vline, i);
 
2033
        }
 
2034
 
 
2035
      if (argc >= CMD_ARGC_MAX)
 
2036
        return CMD_ERR_EXEED_ARGC_MAX;
 
2037
    }
 
2038
 
 
2039
  /* For vtysh execution. */
 
2040
  if (cmd)
 
2041
    *cmd = matched_element;
 
2042
 
 
2043
  if (matched_element->daemon)
 
2044
    return CMD_SUCCESS_DAEMON;
 
2045
 
 
2046
  /* Execute matched command. */
 
2047
  return (*matched_element->func) (matched_element, vty, argc, argv);
 
2048
}
 
2049
 
 
2050
 
 
2051
int
 
2052
cmd_execute_command (vector vline, struct vty *vty, struct cmd_element **cmd) {
 
2053
  int ret, saved_ret, tried = 0;
 
2054
  enum node_type onode, try_node;
 
2055
 
 
2056
  onode = try_node = vty->node;
 
2057
 
 
2058
  if ( cmd_try_do_shortcut(vty->node, vector_slot(vline, 0) ) )
 
2059
    {
 
2060
      vector shifted_vline;
 
2061
      int index;
 
2062
 
 
2063
      vty->node = ENABLE_NODE;
 
2064
      /* We can try it on enable node, cos' the vty is authenticated */
 
2065
 
 
2066
      shifted_vline = vector_init (vector_count(vline));
 
2067
      /* use memcpy? */
 
2068
      for (index = 1; index < vector_max (vline); index++) 
 
2069
        {
 
2070
          vector_set_index (shifted_vline, index-1, vector_lookup(vline, index));
 
2071
        }
 
2072
 
 
2073
      ret = cmd_execute_command_real (shifted_vline, vty, cmd);
 
2074
 
 
2075
      vector_free(shifted_vline);
 
2076
      vty->node = onode;
 
2077
      return ret;
 
2078
  }
 
2079
 
 
2080
 
 
2081
  saved_ret = ret = cmd_execute_command_real (vline, vty, cmd);
 
2082
 
 
2083
  /* This assumes all nodes above CONFIG_NODE are childs of CONFIG_NODE */
 
2084
  while ( ret != CMD_SUCCESS && ret != CMD_WARNING 
 
2085
          && vty->node > CONFIG_NODE )
 
2086
    {
 
2087
      try_node = node_parent(try_node);
 
2088
      vty->node = try_node;
 
2089
      ret = cmd_execute_command_real (vline, vty, cmd);
 
2090
      tried = 1;
 
2091
      if (ret == CMD_SUCCESS || ret == CMD_WARNING)
 
2092
        {
 
2093
          /* succesfull command, leave the node as is */
 
2094
          return ret;
 
2095
        }
 
2096
    }
 
2097
  /* no command succeeded, reset the vty to the original node and
 
2098
     return the error for this node */
 
2099
  if ( tried )
 
2100
    vty->node = onode;
 
2101
  return saved_ret;
 
2102
}
 
2103
 
 
2104
/* Execute command by argument readline. */
 
2105
int
 
2106
cmd_execute_command_strict (vector vline, struct vty *vty, 
 
2107
                            struct cmd_element **cmd)
 
2108
{
 
2109
  int i;
 
2110
  int index;
 
2111
  vector cmd_vector;
 
2112
  struct cmd_element *cmd_element;
 
2113
  struct cmd_element *matched_element;
 
2114
  unsigned int matched_count, incomplete_count;
 
2115
  int argc;
 
2116
  char *argv[CMD_ARGC_MAX];
 
2117
  int varflag;
 
2118
  enum match_type match = 0;
 
2119
  char *command;
 
2120
 
 
2121
  /* Make copy of command element */
 
2122
  cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node));
 
2123
 
 
2124
  for (index = 0; index < vector_max (vline); index++) 
 
2125
    {
 
2126
      int ret;
 
2127
 
 
2128
      command = vector_slot (vline, index);
 
2129
 
 
2130
      match = cmd_filter_by_string (vector_slot (vline, index), 
 
2131
                                    cmd_vector, index);
 
2132
 
 
2133
      /* If command meets '.VARARG' then finish matching. */
 
2134
      if (match == vararg_match)
 
2135
        break;
 
2136
 
 
2137
      ret = is_cmd_ambiguous (command, cmd_vector, index, match);
 
2138
      if (ret == 1)
 
2139
        {
 
2140
          vector_free (cmd_vector);
 
2141
          return CMD_ERR_AMBIGUOUS;
 
2142
        }
 
2143
      if (ret == 2)
 
2144
        {
 
2145
          vector_free (cmd_vector);
 
2146
          return CMD_ERR_NO_MATCH;
 
2147
        }
 
2148
    }
 
2149
 
 
2150
  /* Check matched count. */
 
2151
  matched_element = NULL;
 
2152
  matched_count = 0;
 
2153
  incomplete_count = 0;
 
2154
  for (i = 0; i < vector_max (cmd_vector); i++) 
 
2155
    if (vector_slot (cmd_vector,i) != NULL)
 
2156
      {
 
2157
        cmd_element = vector_slot (cmd_vector,i);
 
2158
 
 
2159
        if (match == vararg_match || index >= cmd_element->cmdsize)
 
2160
          {
 
2161
            matched_element = cmd_element;
 
2162
            matched_count++;
 
2163
          }
 
2164
        else
 
2165
          incomplete_count++;
 
2166
      }
 
2167
  
 
2168
  /* Finish of using cmd_vector. */
 
2169
  vector_free (cmd_vector);
 
2170
 
 
2171
  /* To execute command, matched_count must be 1.*/
 
2172
  if (matched_count == 0) 
 
2173
    {
 
2174
      if (incomplete_count)
 
2175
        return CMD_ERR_INCOMPLETE;
 
2176
      else
 
2177
        return CMD_ERR_NO_MATCH;
 
2178
    }
 
2179
 
 
2180
  if (matched_count > 1) 
 
2181
    return CMD_ERR_AMBIGUOUS;
 
2182
 
 
2183
  /* Argument treatment */
 
2184
  varflag = 0;
 
2185
  argc = 0;
 
2186
 
 
2187
  for (i = 0; i < vector_max (vline); i++)
 
2188
    {
 
2189
      if (varflag)
 
2190
        argv[argc++] = vector_slot (vline, i);
 
2191
      else
 
2192
        {         
 
2193
          vector descvec = vector_slot (matched_element->strvec, i);
 
2194
 
 
2195
          if (vector_max (descvec) == 1)
 
2196
            {
 
2197
              struct desc *desc = vector_slot (descvec, 0);
 
2198
              char *str = desc->cmd;
 
2199
 
 
2200
              if (CMD_VARARG (str))
 
2201
                varflag = 1;
 
2202
          
 
2203
              if (varflag || CMD_VARIABLE (str) || CMD_OPTION (str))
 
2204
                argv[argc++] = vector_slot (vline, i);
 
2205
            }
 
2206
          else
 
2207
            argv[argc++] = vector_slot (vline, i);
 
2208
        }
 
2209
 
 
2210
      if (argc >= CMD_ARGC_MAX)
 
2211
        return CMD_ERR_EXEED_ARGC_MAX;
 
2212
    }
 
2213
 
 
2214
  /* For vtysh execution. */
 
2215
  if (cmd)
 
2216
    *cmd = matched_element;
 
2217
 
 
2218
  if (matched_element->daemon)
 
2219
    return CMD_SUCCESS_DAEMON;
 
2220
 
 
2221
  /* Now execute matched command */
 
2222
  return (*matched_element->func) (matched_element, vty, argc, argv);
 
2223
}
 
2224
 
 
2225
/* Configration make from file. */
 
2226
int
 
2227
config_from_file (struct vty *vty, FILE *fp)
 
2228
{
 
2229
  int ret;
 
2230
  vector vline;
 
2231
 
 
2232
  while (fgets (vty->buf, VTY_BUFSIZ, fp))
 
2233
    {
 
2234
      vline = cmd_make_strvec (vty->buf);
 
2235
 
 
2236
      /* In case of comment line */
 
2237
      if (vline == NULL)
 
2238
        continue;
 
2239
      /* Execute configuration command : this is strict match */
 
2240
      ret = cmd_execute_command_strict (vline, vty, NULL);
 
2241
 
 
2242
      /* Try again with setting node to CONFIG_NODE */
 
2243
      while (ret != CMD_SUCCESS && ret != CMD_WARNING
 
2244
             && vty->node != CONFIG_NODE)
 
2245
                {
 
2246
          vty->node = node_parent(vty->node);
 
2247
                  ret = cmd_execute_command_strict (vline, vty, NULL);
 
2248
                }
 
2249
 
 
2250
      cmd_free_strvec (vline);
 
2251
 
 
2252
      if (ret != CMD_SUCCESS && ret != CMD_WARNING)
 
2253
        return ret;
 
2254
    }
 
2255
  return CMD_SUCCESS;
 
2256
}
 
2257
 
 
2258
/* Configration from terminal */
 
2259
DEFUN (config_terminal,
 
2260
       config_terminal_cmd,
 
2261
       "configure terminal",
 
2262
       "Configuration from vty interface\n"
 
2263
       "Configuration terminal\n")
 
2264
{
 
2265
  if (vty_config_lock (vty))
 
2266
    vty->node = CONFIG_NODE;
 
2267
  else
 
2268
    {
 
2269
      vty_out (vty, "VTY configuration is locked by other VTY%s", VTY_NEWLINE);
 
2270
      return CMD_WARNING;
 
2271
    }
 
2272
  return CMD_SUCCESS;
 
2273
}
 
2274
 
 
2275
/* Enable command */
 
2276
DEFUN (enable, 
 
2277
       config_enable_cmd,
 
2278
       "enable",
 
2279
       "Turn on privileged mode command\n")
 
2280
{
 
2281
  /* If enable password is NULL, change to ENABLE_NODE */
 
2282
  if ((host.enable == NULL && host.enable_encrypt == NULL) ||
 
2283
      vty->type == VTY_SHELL_SERV)
 
2284
    vty->node = ENABLE_NODE;
 
2285
  else
 
2286
    vty->node = AUTH_ENABLE_NODE;
 
2287
 
 
2288
  return CMD_SUCCESS;
 
2289
}
 
2290
 
 
2291
/* Disable command */
 
2292
DEFUN (disable, 
 
2293
       config_disable_cmd,
 
2294
       "disable",
 
2295
       "Turn off privileged mode command\n")
 
2296
{
 
2297
  if (vty->node == ENABLE_NODE)
 
2298
    vty->node = VIEW_NODE;
 
2299
  return CMD_SUCCESS;
 
2300
}
 
2301
 
 
2302
/* Down vty node level. */
 
2303
DEFUN (config_exit,
 
2304
       config_exit_cmd,
 
2305
       "exit",
 
2306
       "Exit current mode and down to previous mode\n")
 
2307
{
 
2308
  switch (vty->node)
 
2309
    {
 
2310
    case VIEW_NODE:
 
2311
    case ENABLE_NODE:
 
2312
      if (vty_shell (vty))
 
2313
        exit (0);
 
2314
      else
 
2315
        vty->status = VTY_CLOSE;
 
2316
      break;
 
2317
    case CONFIG_NODE:
 
2318
      vty->node = ENABLE_NODE;
 
2319
      vty_config_unlock (vty);
 
2320
      break;
 
2321
    case INTERFACE_NODE:
 
2322
    case ZEBRA_NODE:
 
2323
    case BGP_NODE:
 
2324
    case RIP_NODE:
 
2325
    case RIPNG_NODE:
 
2326
    case OSPF_NODE:
 
2327
    case OSPF6_NODE:
 
2328
    case ISIS_NODE:
 
2329
    case KEYCHAIN_NODE:
 
2330
    case MASC_NODE:
 
2331
    case RMAP_NODE:
 
2332
    case VTY_NODE:
 
2333
      vty->node = CONFIG_NODE;
 
2334
      break;
 
2335
    case BGP_VPNV4_NODE:
 
2336
    case BGP_IPV4_NODE:
 
2337
    case BGP_IPV4M_NODE:
 
2338
    case BGP_IPV6_NODE:
 
2339
      vty->node = BGP_NODE;
 
2340
      break;
 
2341
    case KEYCHAIN_KEY_NODE:
 
2342
      vty->node = KEYCHAIN_NODE;
 
2343
      break;
 
2344
    default:
 
2345
      break;
 
2346
    }
 
2347
  return CMD_SUCCESS;
 
2348
}
 
2349
 
 
2350
/* quit is alias of exit. */
 
2351
ALIAS (config_exit,
 
2352
       config_quit_cmd,
 
2353
       "quit",
 
2354
       "Exit current mode and down to previous mode\n")
 
2355
       
 
2356
/* End of configuration. */
 
2357
DEFUN (config_end,
 
2358
       config_end_cmd,
 
2359
       "end",
 
2360
       "End current mode and change to enable mode.")
 
2361
{
 
2362
  switch (vty->node)
 
2363
    {
 
2364
    case VIEW_NODE:
 
2365
    case ENABLE_NODE:
 
2366
      /* Nothing to do. */
 
2367
      break;
 
2368
    case CONFIG_NODE:
 
2369
    case INTERFACE_NODE:
 
2370
    case ZEBRA_NODE:
 
2371
    case RIP_NODE:
 
2372
    case RIPNG_NODE:
 
2373
    case BGP_NODE:
 
2374
    case BGP_VPNV4_NODE:
 
2375
    case BGP_IPV4_NODE:
 
2376
    case BGP_IPV4M_NODE:
 
2377
    case BGP_IPV6_NODE:
 
2378
    case RMAP_NODE:
 
2379
    case OSPF_NODE:
 
2380
    case OSPF6_NODE:
 
2381
    case ISIS_NODE:
 
2382
    case KEYCHAIN_NODE:
 
2383
    case KEYCHAIN_KEY_NODE:
 
2384
    case MASC_NODE:
 
2385
    case VTY_NODE:
 
2386
      vty_config_unlock (vty);
 
2387
      vty->node = ENABLE_NODE;
 
2388
      break;
 
2389
    default:
 
2390
      break;
 
2391
    }
 
2392
  return CMD_SUCCESS;
 
2393
}
 
2394
 
 
2395
/* Show version. */
 
2396
DEFUN (show_version,
 
2397
       show_version_cmd,
 
2398
       "show version",
 
2399
       SHOW_STR
 
2400
       "Displays zebra version\n")
 
2401
{
 
2402
  vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION,
 
2403
           host_name,
 
2404
           VTY_NEWLINE);
 
2405
  vty_out (vty, "Copyright 1996-2002, Kunihiro Ishiguro.%s", VTY_NEWLINE);
 
2406
 
 
2407
  return CMD_SUCCESS;
 
2408
}
 
2409
 
 
2410
/* Help display function for all node. */
 
2411
DEFUN (config_help,
 
2412
       config_help_cmd,
 
2413
       "help",
 
2414
       "Description of the interactive help system\n")
 
2415
{
 
2416
  vty_out (vty, 
 
2417
           "Zebra VTY provides advanced help feature.  When you need help,%s\
 
2418
anytime at the command line please press '?'.%s\
 
2419
%s\
 
2420
If nothing matches, the help list will be empty and you must backup%s\
 
2421
 until entering a '?' shows the available options.%s\
 
2422
Two styles of help are provided:%s\
 
2423
1. Full help is available when you are ready to enter a%s\
 
2424
command argument (e.g. 'show ?') and describes each possible%s\
 
2425
argument.%s\
 
2426
2. Partial help is provided when an abbreviated argument is entered%s\
 
2427
   and you want to know what arguments match the input%s\
 
2428
   (e.g. 'show me?'.)%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
 
2429
           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE,
 
2430
           VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
 
2431
  return CMD_SUCCESS;
 
2432
}
 
2433
 
 
2434
/* Help display function for all node. */
 
2435
DEFUN (config_list,
 
2436
       config_list_cmd,
 
2437
       "list",
 
2438
       "Print command list\n")
 
2439
{
 
2440
  int i;
 
2441
  struct cmd_node *cnode = vector_slot (cmdvec, vty->node);
 
2442
  struct cmd_element *cmd;
 
2443
 
 
2444
  for (i = 0; i < vector_max (cnode->cmd_vector); i++)
 
2445
    if ((cmd = vector_slot (cnode->cmd_vector, i)) != NULL)
 
2446
      vty_out (vty, "  %s%s", cmd->string,
 
2447
               VTY_NEWLINE);
 
2448
  return CMD_SUCCESS;
 
2449
}
 
2450
 
 
2451
/* Write current configuration into file. */
 
2452
DEFUN (config_write_file, 
 
2453
       config_write_file_cmd,
 
2454
       "write file",  
 
2455
       "Write running configuration to memory, network, or terminal\n"
 
2456
       "Write to configuration file\n")
 
2457
{
 
2458
  int i;
 
2459
  int fd;
 
2460
  struct cmd_node *node;
 
2461
  char *config_file;
 
2462
  char *config_file_tmp = NULL;
 
2463
  char *config_file_sav = NULL;
 
2464
  struct vty *file_vty;
 
2465
 
 
2466
  /* Check and see if we are operating under vtysh configuration */
 
2467
  if (host.config == NULL)
 
2468
    {
 
2469
      vty_out (vty, "Can't save to configuration file, using vtysh.%s",
 
2470
               VTY_NEWLINE);
 
2471
      return CMD_WARNING;
 
2472
    }
 
2473
 
 
2474
  /* Get filename. */
 
2475
  config_file = host.config;
 
2476
  
 
2477
  config_file_sav = malloc (strlen (config_file) + strlen (CONF_BACKUP_EXT) + 1);
 
2478
  strcpy (config_file_sav, config_file);
 
2479
  strcat (config_file_sav, CONF_BACKUP_EXT);
 
2480
 
 
2481
 
 
2482
  config_file_tmp = malloc (strlen (config_file) + 8);
 
2483
  sprintf (config_file_tmp, "%s.XXXXXX", config_file);
 
2484
  
 
2485
  /* Open file to configuration write. */
 
2486
  fd = mkstemp (config_file_tmp);
 
2487
  if (fd < 0)
 
2488
    {
 
2489
      vty_out (vty, "Can't open configuration file %s.%s", config_file_tmp,
 
2490
               VTY_NEWLINE);
 
2491
      free (config_file_tmp);
 
2492
      free (config_file_sav);
 
2493
      return CMD_WARNING;
 
2494
    }
 
2495
  
 
2496
  /* Make vty for configuration file. */
 
2497
  file_vty = vty_new ();
 
2498
  file_vty->fd = fd;
 
2499
  file_vty->type = VTY_FILE;
 
2500
 
 
2501
  /* Config file header print. */
 
2502
  vty_out (file_vty, "!\n! Zebra configuration saved from vty\n!   ");
 
2503
  vty_time_print (file_vty, 1);
 
2504
  vty_out (file_vty, "!\n");
 
2505
 
 
2506
  for (i = 0; i < vector_max (cmdvec); i++)
 
2507
    if ((node = vector_slot (cmdvec, i)) && node->func)
 
2508
      {
 
2509
        if ((*node->func) (file_vty))
 
2510
          vty_out (file_vty, "!\n");
 
2511
      }
 
2512
  vty_close (file_vty);
 
2513
 
 
2514
  if (unlink (config_file_sav) != 0)
 
2515
    if (errno != ENOENT)
 
2516
      {
 
2517
        vty_out (vty, "Can't unlink backup configuration file %s.%s", config_file_sav,
 
2518
                 VTY_NEWLINE);
 
2519
        free (config_file_sav);
 
2520
        free (config_file_tmp);
 
2521
        unlink (config_file_tmp);       
 
2522
        return CMD_WARNING;
 
2523
      }
 
2524
  if (link (config_file, config_file_sav) != 0)
 
2525
    {
 
2526
      vty_out (vty, "Can't backup old configuration file %s.%s", config_file_sav,
 
2527
                VTY_NEWLINE);
 
2528
      free (config_file_sav);
 
2529
      free (config_file_tmp);
 
2530
      unlink (config_file_tmp);
 
2531
      return CMD_WARNING;
 
2532
    }
 
2533
  sync ();
 
2534
  if (unlink (config_file) != 0)
 
2535
    {
 
2536
      vty_out (vty, "Can't unlink configuration file %s.%s", config_file,
 
2537
                VTY_NEWLINE);
 
2538
      free (config_file_sav);
 
2539
      free (config_file_tmp);
 
2540
      unlink (config_file_tmp);
 
2541
      return CMD_WARNING;      
 
2542
    }
 
2543
  if (link (config_file_tmp, config_file) != 0)
 
2544
    {
 
2545
      vty_out (vty, "Can't save configuration file %s.%s", config_file,
 
2546
               VTY_NEWLINE);
 
2547
      free (config_file_sav);
 
2548
      free (config_file_tmp);
 
2549
      unlink (config_file_tmp);
 
2550
      return CMD_WARNING;      
 
2551
    }
 
2552
  unlink (config_file_tmp);
 
2553
  sync ();
 
2554
  
 
2555
  free (config_file_sav);
 
2556
  free (config_file_tmp);
 
2557
 
 
2558
  if (chmod (config_file, CONFIGFILE_MASK) != 0)
 
2559
    {
 
2560
      vty_out (vty, "Can't chmod configuration file %s: %s (%d).%s", 
 
2561
        config_file, strerror(errno), errno, VTY_NEWLINE);
 
2562
      return CMD_WARNING;      
 
2563
    }
 
2564
 
 
2565
  vty_out (vty, "Configuration saved to %s%s", config_file,
 
2566
           VTY_NEWLINE);
 
2567
  return CMD_SUCCESS;
 
2568
}
 
2569
 
 
2570
ALIAS (config_write_file, 
 
2571
       config_write_cmd,
 
2572
       "write",  
 
2573
       "Write running configuration to memory, network, or terminal\n")
 
2574
 
 
2575
ALIAS (config_write_file, 
 
2576
       config_write_memory_cmd,
 
2577
       "write memory",  
 
2578
       "Write running configuration to memory, network, or terminal\n"
 
2579
       "Write configuration to the file (same as write file)\n")
 
2580
 
 
2581
ALIAS (config_write_file, 
 
2582
       copy_runningconfig_startupconfig_cmd,
 
2583
       "copy running-config startup-config",  
 
2584
       "Copy configuration\n"
 
2585
       "Copy running config to... \n"
 
2586
       "Copy running config to startup config (same as write file)\n")
 
2587
 
 
2588
/* Write current configuration into the terminal. */
 
2589
DEFUN (config_write_terminal,
 
2590
       config_write_terminal_cmd,
 
2591
       "write terminal",
 
2592
       "Write running configuration to memory, network, or terminal\n"
 
2593
       "Write to terminal\n")
 
2594
{
 
2595
  int i;
 
2596
  struct cmd_node *node;
 
2597
 
 
2598
  if (vty->type == VTY_SHELL_SERV)
 
2599
    {
 
2600
      for (i = 0; i < vector_max (cmdvec); i++)
 
2601
        if ((node = vector_slot (cmdvec, i)) && node->func && node->vtysh)
 
2602
          {
 
2603
            if ((*node->func) (vty))
 
2604
              vty_out (vty, "!%s", VTY_NEWLINE);
 
2605
          }
 
2606
    }
 
2607
  else
 
2608
    {
 
2609
      vty_out (vty, "%sCurrent configuration:%s", VTY_NEWLINE,
 
2610
               VTY_NEWLINE);
 
2611
      vty_out (vty, "!%s", VTY_NEWLINE);
 
2612
 
 
2613
      for (i = 0; i < vector_max (cmdvec); i++)
 
2614
        if ((node = vector_slot (cmdvec, i)) && node->func)
 
2615
          {
 
2616
            if ((*node->func) (vty))
 
2617
              vty_out (vty, "!%s", VTY_NEWLINE);
 
2618
          }
 
2619
      vty_out (vty, "end%s",VTY_NEWLINE);
 
2620
    }
 
2621
  return CMD_SUCCESS;
 
2622
}
 
2623
 
 
2624
/* Write current configuration into the terminal. */
 
2625
ALIAS (config_write_terminal,
 
2626
       show_running_config_cmd,
 
2627
       "show running-config",
 
2628
       SHOW_STR
 
2629
       "running configuration\n")
 
2630
 
 
2631
/* Write startup configuration into the terminal. */
 
2632
DEFUN (show_startup_config,
 
2633
       show_startup_config_cmd,
 
2634
       "show startup-config",
 
2635
       SHOW_STR
 
2636
       "Contentes of startup configuration\n")
 
2637
{
 
2638
  char buf[BUFSIZ];
 
2639
  FILE *confp;
 
2640
 
 
2641
  confp = fopen (host.config, "r");
 
2642
  if (confp == NULL)
 
2643
    {
 
2644
      vty_out (vty, "Can't open configuration file [%s]%s",
 
2645
               host.config, VTY_NEWLINE);
 
2646
      return CMD_WARNING;
 
2647
    }
 
2648
 
 
2649
  while (fgets (buf, BUFSIZ, confp))
 
2650
    {
 
2651
      char *cp = buf;
 
2652
 
 
2653
      while (*cp != '\r' && *cp != '\n' && *cp != '\0')
 
2654
        cp++;
 
2655
      *cp = '\0';
 
2656
 
 
2657
      vty_out (vty, "%s%s", buf, VTY_NEWLINE);
 
2658
    }
 
2659
 
 
2660
  fclose (confp);
 
2661
 
 
2662
  return CMD_SUCCESS;
 
2663
}
 
2664
 
 
2665
/* Hostname configuration */
 
2666
DEFUN (config_hostname, 
 
2667
       hostname_cmd,
 
2668
       "hostname WORD",
 
2669
       "Set system's network name\n"
 
2670
       "This system's network name\n")
 
2671
{
 
2672
  if (!isalpha((int) *argv[0]))
 
2673
    {
 
2674
      vty_out (vty, "Please specify string starting with alphabet%s", VTY_NEWLINE);
 
2675
      return CMD_WARNING;
 
2676
    }
 
2677
 
 
2678
  if (host.name)
 
2679
    XFREE (0, host.name);
 
2680
    
 
2681
  host.name = strdup (argv[0]);
 
2682
  return CMD_SUCCESS;
 
2683
}
 
2684
 
 
2685
DEFUN (config_no_hostname, 
 
2686
       no_hostname_cmd,
 
2687
       "no hostname [HOSTNAME]",
 
2688
       NO_STR
 
2689
       "Reset system's network name\n"
 
2690
       "Host name of this router\n")
 
2691
{
 
2692
  if (host.name)
 
2693
    XFREE (0, host.name);
 
2694
  host.name = NULL;
 
2695
  return CMD_SUCCESS;
 
2696
}
 
2697
 
 
2698
/* VTY interface password set. */
 
2699
DEFUN (config_password, password_cmd,
 
2700
       "password (8|) WORD",
 
2701
       "Assign the terminal connection password\n"
 
2702
       "Specifies a HIDDEN password will follow\n"
 
2703
       "dummy string \n"
 
2704
       "The HIDDEN line password string\n")
 
2705
{
 
2706
  /* Argument check. */
 
2707
  if (argc == 0)
 
2708
    {
 
2709
      vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
 
2710
      return CMD_WARNING;
 
2711
    }
 
2712
 
 
2713
  if (argc == 2)
 
2714
    {
 
2715
      if (*argv[0] == '8')
 
2716
        {
 
2717
          if (host.password)
 
2718
            XFREE (0, host.password);
 
2719
          host.password = NULL;
 
2720
          if (host.password_encrypt)
 
2721
            XFREE (0, host.password_encrypt);
 
2722
          host.password_encrypt = XSTRDUP (0, strdup (argv[1]));
 
2723
          return CMD_SUCCESS;
 
2724
        }
 
2725
      else
 
2726
        {
 
2727
          vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
 
2728
          return CMD_WARNING;
 
2729
        }
 
2730
    }
 
2731
 
 
2732
  if (!isalnum ((int) *argv[0]))
 
2733
    {
 
2734
      vty_out (vty, 
 
2735
               "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
 
2736
      return CMD_WARNING;
 
2737
    }
 
2738
 
 
2739
  if (host.password)
 
2740
    XFREE (0, host.password);
 
2741
  host.password = NULL;
 
2742
 
 
2743
  if (host.encrypt)
 
2744
    {
 
2745
      if (host.password_encrypt)
 
2746
        XFREE (0, host.password_encrypt);
 
2747
      host.password_encrypt = XSTRDUP (0, zencrypt (argv[0]));
 
2748
    }
 
2749
  else
 
2750
    host.password = XSTRDUP (0, argv[0]);
 
2751
 
 
2752
  return CMD_SUCCESS;
 
2753
}
 
2754
 
 
2755
ALIAS (config_password, password_text_cmd,
 
2756
       "password LINE",
 
2757
       "Assign the terminal connection password\n"
 
2758
       "The UNENCRYPTED (cleartext) line password\n")
 
2759
 
 
2760
/* VTY enable password set. */
 
2761
DEFUN (config_enable_password, enable_password_cmd,
 
2762
       "enable password (8|) WORD",
 
2763
       "Modify enable password parameters\n"
 
2764
       "Assign the privileged level password\n"
 
2765
       "Specifies a HIDDEN password will follow\n"
 
2766
       "dummy string \n"
 
2767
       "The HIDDEN 'enable' password string\n")
 
2768
{
 
2769
  /* Argument check. */
 
2770
  if (argc == 0)
 
2771
    {
 
2772
      vty_out (vty, "Please specify password.%s", VTY_NEWLINE);
 
2773
      return CMD_WARNING;
 
2774
    }
 
2775
 
 
2776
  /* Crypt type is specified. */
 
2777
  if (argc == 2)
 
2778
    {
 
2779
      if (*argv[0] == '8')
 
2780
        {
 
2781
          if (host.enable)
 
2782
            XFREE (0, host.enable);
 
2783
          host.enable = NULL;
 
2784
 
 
2785
          if (host.enable_encrypt)
 
2786
            XFREE (0, host.enable_encrypt);
 
2787
          host.enable_encrypt = XSTRDUP (0, argv[1]);
 
2788
 
 
2789
          return CMD_SUCCESS;
 
2790
        }
 
2791
      else
 
2792
        {
 
2793
          vty_out (vty, "Unknown encryption type.%s", VTY_NEWLINE);
 
2794
          return CMD_WARNING;
 
2795
        }
 
2796
    }
 
2797
 
 
2798
  if (!isalnum ((int) *argv[0]))
 
2799
    {
 
2800
      vty_out (vty, 
 
2801
               "Please specify string starting with alphanumeric%s", VTY_NEWLINE);
 
2802
      return CMD_WARNING;
 
2803
    }
 
2804
 
 
2805
  if (host.enable)
 
2806
    XFREE (0, host.enable);
 
2807
  host.enable = NULL;
 
2808
 
 
2809
  /* Plain password input. */
 
2810
  if (host.encrypt)
 
2811
    {
 
2812
      if (host.enable_encrypt)
 
2813
        XFREE (0, host.enable_encrypt);
 
2814
      host.enable_encrypt = XSTRDUP (0, zencrypt (argv[0]));
 
2815
    }
 
2816
  else
 
2817
    host.enable = XSTRDUP (0, argv[0]);
 
2818
 
 
2819
  return CMD_SUCCESS;
 
2820
}
 
2821
 
 
2822
ALIAS (config_enable_password,
 
2823
       enable_password_text_cmd,
 
2824
       "enable password LINE",
 
2825
       "Modify enable password parameters\n"
 
2826
       "Assign the privileged level password\n"
 
2827
       "The UNENCRYPTED (cleartext) 'enable' password\n")
 
2828
 
 
2829
/* VTY enable password delete. */
 
2830
DEFUN (no_config_enable_password, no_enable_password_cmd,
 
2831
       "no enable password",
 
2832
       NO_STR
 
2833
       "Modify enable password parameters\n"
 
2834
       "Assign the privileged level password\n")
 
2835
{
 
2836
  if (host.enable)
 
2837
    XFREE (0, host.enable);
 
2838
  host.enable = NULL;
 
2839
 
 
2840
  if (host.enable_encrypt)
 
2841
    XFREE (0, host.enable_encrypt);
 
2842
  host.enable_encrypt = NULL;
 
2843
 
 
2844
  return CMD_SUCCESS;
 
2845
}
 
2846
        
 
2847
DEFUN (service_password_encrypt,
 
2848
       service_password_encrypt_cmd,
 
2849
       "service password-encryption",
 
2850
       "Set up miscellaneous service\n"
 
2851
       "Enable encrypted passwords\n")
 
2852
{
 
2853
  if (host.encrypt)
 
2854
    return CMD_SUCCESS;
 
2855
 
 
2856
  host.encrypt = 1;
 
2857
 
 
2858
  if (host.password)
 
2859
    {
 
2860
      if (host.password_encrypt)
 
2861
        XFREE (0, host.password_encrypt);
 
2862
      host.password_encrypt = XSTRDUP (0, zencrypt (host.password));
 
2863
    }
 
2864
  if (host.enable)
 
2865
    {
 
2866
      if (host.enable_encrypt)
 
2867
        XFREE (0, host.enable_encrypt);
 
2868
      host.enable_encrypt = XSTRDUP (0, zencrypt (host.enable));
 
2869
    }
 
2870
 
 
2871
  return CMD_SUCCESS;
 
2872
}
 
2873
 
 
2874
DEFUN (no_service_password_encrypt,
 
2875
       no_service_password_encrypt_cmd,
 
2876
       "no service password-encryption",
 
2877
       NO_STR
 
2878
       "Set up miscellaneous service\n"
 
2879
       "Enable encrypted passwords\n")
 
2880
{
 
2881
  if (! host.encrypt)
 
2882
    return CMD_SUCCESS;
 
2883
 
 
2884
  host.encrypt = 0;
 
2885
 
 
2886
  if (host.password_encrypt)
 
2887
    XFREE (0, host.password_encrypt);
 
2888
  host.password_encrypt = NULL;
 
2889
 
 
2890
  if (host.enable_encrypt)
 
2891
    XFREE (0, host.enable_encrypt);
 
2892
  host.enable_encrypt = NULL;
 
2893
 
 
2894
  return CMD_SUCCESS;
 
2895
}
 
2896
 
 
2897
DEFUN (config_terminal_length, config_terminal_length_cmd,
 
2898
       "terminal length <0-512>",
 
2899
       "Set terminal line parameters\n"
 
2900
       "Set number of lines on a screen\n"
 
2901
       "Number of lines on screen (0 for no pausing)\n")
 
2902
{
 
2903
  int lines;
 
2904
  char *endptr = NULL;
 
2905
 
 
2906
  lines = strtol (argv[0], &endptr, 10);
 
2907
  if (lines < 0 || lines > 512 || *endptr != '\0')
 
2908
    {
 
2909
      vty_out (vty, "length is malformed%s", VTY_NEWLINE);
 
2910
      return CMD_WARNING;
 
2911
    }
 
2912
  vty->lines = lines;
 
2913
 
 
2914
  return CMD_SUCCESS;
 
2915
}
 
2916
 
 
2917
DEFUN (config_terminal_no_length, config_terminal_no_length_cmd,
 
2918
       "terminal no length",
 
2919
       "Set terminal line parameters\n"
 
2920
       NO_STR
 
2921
       "Set number of lines on a screen\n")
 
2922
{
 
2923
  vty->lines = -1;
 
2924
  return CMD_SUCCESS;
 
2925
}
 
2926
 
 
2927
DEFUN (service_terminal_length, service_terminal_length_cmd,
 
2928
       "service terminal-length <0-512>",
 
2929
       "Set up miscellaneous service\n"
 
2930
       "System wide terminal length configuration\n"
 
2931
       "Number of lines of VTY (0 means no line control)\n")
 
2932
{
 
2933
  int lines;
 
2934
  char *endptr = NULL;
 
2935
 
 
2936
  lines = strtol (argv[0], &endptr, 10);
 
2937
  if (lines < 0 || lines > 512 || *endptr != '\0')
 
2938
    {
 
2939
      vty_out (vty, "length is malformed%s", VTY_NEWLINE);
 
2940
      return CMD_WARNING;
 
2941
    }
 
2942
  host.lines = lines;
 
2943
 
 
2944
  return CMD_SUCCESS;
 
2945
}
 
2946
 
 
2947
DEFUN (no_service_terminal_length, no_service_terminal_length_cmd,
 
2948
       "no service terminal-length [<0-512>]",
 
2949
       NO_STR
 
2950
       "Set up miscellaneous service\n"
 
2951
       "System wide terminal length configuration\n"
 
2952
       "Number of lines of VTY (0 means no line control)\n")
 
2953
{
 
2954
  host.lines = -1;
 
2955
  return CMD_SUCCESS;
 
2956
}
 
2957
 
 
2958
DEFUN (config_log_stdout,
 
2959
       config_log_stdout_cmd,
 
2960
       "log stdout",
 
2961
       "Logging control\n"
 
2962
       "Logging goes to stdout\n")
 
2963
{
 
2964
  zlog_set_flag (NULL, ZLOG_STDOUT);
 
2965
  host.log_stdout = 1;
 
2966
  return CMD_SUCCESS;
 
2967
}
 
2968
 
 
2969
DEFUN (no_config_log_stdout,
 
2970
       no_config_log_stdout_cmd,
 
2971
       "no log stdout",
 
2972
       NO_STR
 
2973
       "Logging control\n"
 
2974
       "Cancel logging to stdout\n")
 
2975
{
 
2976
  zlog_reset_flag (NULL, ZLOG_STDOUT);
 
2977
  host.log_stdout = 0;
 
2978
  return CMD_SUCCESS;
 
2979
}
 
2980
 
 
2981
DEFUN (config_log_file,
 
2982
       config_log_file_cmd,
 
2983
       "log file FILENAME",
 
2984
       "Logging control\n"
 
2985
       "Logging to file\n"
 
2986
       "Logging filename\n")
 
2987
{
 
2988
  int ret;
 
2989
  char *cwd;
 
2990
  char *fullpath;
 
2991
 
 
2992
  /* Path detection. */
 
2993
  if (! IS_DIRECTORY_SEP (*argv[0]))
 
2994
    {
 
2995
      cwd = getcwd (NULL, MAXPATHLEN);
 
2996
      fullpath = XMALLOC (MTYPE_TMP,
 
2997
                          strlen (cwd) + strlen (argv[0]) + 2);
 
2998
      sprintf (fullpath, "%s/%s", cwd, argv[0]);
 
2999
    }
 
3000
  else
 
3001
    fullpath = argv[0];
 
3002
 
 
3003
  ret = zlog_set_file (NULL, ZLOG_FILE, fullpath);
 
3004
 
 
3005
  if (!ret)
 
3006
    {
 
3007
      vty_out (vty, "can't open logfile %s\n", argv[0]);
 
3008
      return CMD_WARNING;
 
3009
    }
 
3010
 
 
3011
  if (host.logfile)
 
3012
    XFREE (MTYPE_TMP, host.logfile);
 
3013
 
 
3014
  host.logfile = strdup (argv[0]);
 
3015
 
 
3016
  return CMD_SUCCESS;
 
3017
}
 
3018
 
 
3019
DEFUN (no_config_log_file,
 
3020
       no_config_log_file_cmd,
 
3021
       "no log file [FILENAME]",
 
3022
       NO_STR
 
3023
       "Logging control\n"
 
3024
       "Cancel logging to file\n"
 
3025
       "Logging file name\n")
 
3026
{
 
3027
  zlog_reset_file (NULL);
 
3028
 
 
3029
  if (host.logfile)
 
3030
    XFREE (MTYPE_TMP, host.logfile);
 
3031
 
 
3032
  host.logfile = NULL;
 
3033
 
 
3034
  return CMD_SUCCESS;
 
3035
}
 
3036
 
 
3037
DEFUN (config_log_syslog,
 
3038
       config_log_syslog_cmd,
 
3039
       "log syslog",
 
3040
       "Logging control\n"
 
3041
       "Logging goes to syslog\n")
 
3042
{
 
3043
  zlog_set_flag (NULL, ZLOG_SYSLOG);
 
3044
  host.log_syslog = 1;
 
3045
  zlog_default->facility = LOG_DAEMON;
 
3046
  return CMD_SUCCESS;
 
3047
}
 
3048
 
 
3049
DEFUN (config_log_syslog_facility,
 
3050
       config_log_syslog_facility_cmd,
 
3051
       "log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)",
 
3052
       "Logging control\n"
 
3053
       "Logging goes to syslog\n"
 
3054
       "Facility parameter for syslog messages\n"
 
3055
       "Kernel\n"
 
3056
       "User process\n"
 
3057
       "Mail system\n"
 
3058
       "System daemons\n"
 
3059
       "Authorization system\n"
 
3060
       "Syslog itself\n"
 
3061
       "Line printer system\n"
 
3062
       "USENET news\n"
 
3063
       "Unix-to-Unix copy system\n"
 
3064
       "Cron/at facility\n"
 
3065
       "Local use\n"
 
3066
       "Local use\n"
 
3067
       "Local use\n"
 
3068
       "Local use\n"
 
3069
       "Local use\n"
 
3070
       "Local use\n"
 
3071
       "Local use\n"
 
3072
       "Local use\n")
 
3073
{
 
3074
  int facility = LOG_DAEMON;
 
3075
 
 
3076
  zlog_set_flag (NULL, ZLOG_SYSLOG);
 
3077
  host.log_syslog = 1;
 
3078
 
 
3079
  if (strncmp (argv[0], "kern", 1) == 0)
 
3080
    facility = LOG_KERN;
 
3081
  else if (strncmp (argv[0], "user", 2) == 0)
 
3082
    facility = LOG_USER;
 
3083
  else if (strncmp (argv[0], "mail", 1) == 0)
 
3084
    facility = LOG_MAIL;
 
3085
  else if (strncmp (argv[0], "daemon", 1) == 0)
 
3086
    facility = LOG_DAEMON;
 
3087
  else if (strncmp (argv[0], "auth", 1) == 0)
 
3088
    facility = LOG_AUTH;
 
3089
  else if (strncmp (argv[0], "syslog", 1) == 0)
 
3090
    facility = LOG_SYSLOG;
 
3091
  else if (strncmp (argv[0], "lpr", 2) == 0)
 
3092
    facility = LOG_LPR;
 
3093
  else if (strncmp (argv[0], "news", 1) == 0)
 
3094
    facility = LOG_NEWS;
 
3095
  else if (strncmp (argv[0], "uucp", 2) == 0)
 
3096
    facility = LOG_UUCP;
 
3097
  else if (strncmp (argv[0], "cron", 1) == 0)
 
3098
    facility = LOG_CRON;
 
3099
  else if (strncmp (argv[0], "local0", 6) == 0)
 
3100
    facility = LOG_LOCAL0;
 
3101
  else if (strncmp (argv[0], "local1", 6) == 0)
 
3102
    facility = LOG_LOCAL1;
 
3103
  else if (strncmp (argv[0], "local2", 6) == 0)
 
3104
    facility = LOG_LOCAL2;
 
3105
  else if (strncmp (argv[0], "local3", 6) == 0)
 
3106
    facility = LOG_LOCAL3;
 
3107
  else if (strncmp (argv[0], "local4", 6) == 0)
 
3108
    facility = LOG_LOCAL4;
 
3109
  else if (strncmp (argv[0], "local5", 6) == 0)
 
3110
    facility = LOG_LOCAL5;
 
3111
  else if (strncmp (argv[0], "local6", 6) == 0)
 
3112
    facility = LOG_LOCAL6;
 
3113
  else if (strncmp (argv[0], "local7", 6) == 0)
 
3114
    facility = LOG_LOCAL7;
 
3115
 
 
3116
  zlog_default->facility = facility;
 
3117
 
 
3118
  return CMD_SUCCESS;
 
3119
}
 
3120
 
 
3121
DEFUN (no_config_log_syslog,
 
3122
       no_config_log_syslog_cmd,
 
3123
       "no log syslog",
 
3124
       NO_STR
 
3125
       "Logging control\n"
 
3126
       "Cancel logging to syslog\n")
 
3127
{
 
3128
  zlog_reset_flag (NULL, ZLOG_SYSLOG);
 
3129
  host.log_syslog = 0;
 
3130
  zlog_default->facility = LOG_DAEMON;
 
3131
  return CMD_SUCCESS;
 
3132
}
 
3133
 
 
3134
ALIAS (no_config_log_syslog,
 
3135
       no_config_log_syslog_facility_cmd,
 
3136
       "no log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)",
 
3137
       NO_STR
 
3138
       "Logging control\n"
 
3139
       "Logging goes to syslog\n"
 
3140
       "Facility parameter for syslog messages\n"
 
3141
       "Kernel\n"
 
3142
       "User process\n"
 
3143
       "Mail system\n"
 
3144
       "System daemons\n"
 
3145
       "Authorization system\n"
 
3146
       "Syslog itself\n"
 
3147
       "Line printer system\n"
 
3148
       "USENET news\n"
 
3149
       "Unix-to-Unix copy system\n"
 
3150
       "Cron/at facility\n"
 
3151
       "Local use\n"
 
3152
       "Local use\n"
 
3153
       "Local use\n"
 
3154
       "Local use\n"
 
3155
       "Local use\n"
 
3156
       "Local use\n"
 
3157
       "Local use\n"
 
3158
       "Local use\n")
 
3159
 
 
3160
DEFUN (config_log_trap,
 
3161
       config_log_trap_cmd,
 
3162
       "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)",
 
3163
       "Logging control\n"
 
3164
       "Limit logging to specifed level\n")
 
3165
{
 
3166
  int new_level ;
 
3167
  
 
3168
  for ( new_level = 0 ; zlog_priority [new_level] != NULL ; new_level ++ )
 
3169
    {
 
3170
    if ( strcmp ( argv[0], zlog_priority [new_level] ) == 0 )
 
3171
      /* found new logging level */
 
3172
      {
 
3173
      zlog_default->maskpri = new_level;
 
3174
      return CMD_SUCCESS;
 
3175
      }
 
3176
    }
 
3177
  return CMD_ERR_NO_MATCH;
 
3178
}
 
3179
 
 
3180
DEFUN (no_config_log_trap,
 
3181
       no_config_log_trap_cmd,
 
3182
       "no log trap",
 
3183
       NO_STR
 
3184
       "Logging control\n"
 
3185
       "Permit all logging information\n")
 
3186
{
 
3187
  zlog_default->maskpri = LOG_DEBUG;
 
3188
  return CMD_SUCCESS;
 
3189
}
 
3190
 
 
3191
DEFUN (config_log_record_priority,
 
3192
       config_log_record_priority_cmd,
 
3193
       "log record-priority",
 
3194
       "Logging control\n"
 
3195
       "Log the priority of the message within the message\n")
 
3196
{
 
3197
  zlog_default->record_priority = 1 ;
 
3198
  return CMD_SUCCESS;
 
3199
}
 
3200
 
 
3201
DEFUN (no_config_log_record_priority,
 
3202
       no_config_log_record_priority_cmd,
 
3203
       "no log record-priority",
 
3204
       NO_STR
 
3205
       "Logging control\n"
 
3206
       "Do not log the priority of the message within the message\n")
 
3207
{
 
3208
  zlog_default->record_priority = 0 ;
 
3209
  return CMD_SUCCESS;
 
3210
}
 
3211
 
 
3212
 
 
3213
DEFUN (banner_motd_default,
 
3214
       banner_motd_default_cmd,
 
3215
       "banner motd default",
 
3216
       "Set banner string\n"
 
3217
       "Strings for motd\n"
 
3218
       "Default string\n")
 
3219
{
 
3220
  host.motd = default_motd;
 
3221
  return CMD_SUCCESS;
 
3222
}
 
3223
 
 
3224
DEFUN (no_banner_motd,
 
3225
       no_banner_motd_cmd,
 
3226
       "no banner motd",
 
3227
       NO_STR
 
3228
       "Set banner string\n"
 
3229
       "Strings for motd\n")
 
3230
{
 
3231
  host.motd = NULL;
 
3232
  return CMD_SUCCESS;
 
3233
}
 
3234
 
 
3235
/* Set config filename.  Called from vty.c */
 
3236
void
 
3237
host_config_set (char *filename)
 
3238
{
 
3239
  host.config = strdup (filename);
 
3240
}
 
3241
 
 
3242
void
 
3243
install_default (enum node_type node)
 
3244
{
 
3245
  install_element (node, &config_exit_cmd);
 
3246
  install_element (node, &config_quit_cmd);
 
3247
  install_element (node, &config_end_cmd);
 
3248
  install_element (node, &config_help_cmd);
 
3249
  install_element (node, &config_list_cmd);
 
3250
 
 
3251
  install_element (node, &config_write_terminal_cmd);
 
3252
  install_element (node, &config_write_file_cmd);
 
3253
  install_element (node, &config_write_memory_cmd);
 
3254
  install_element (node, &config_write_cmd);
 
3255
  install_element (node, &show_running_config_cmd);
 
3256
}
 
3257
 
 
3258
/* Initialize command interface. Install basic nodes and commands. */
 
3259
void
 
3260
cmd_init (int terminal)
 
3261
{
 
3262
  /* Allocate initial top vector of commands. */
 
3263
  cmdvec = vector_init (VECTOR_MIN_SIZE);
 
3264
 
 
3265
  /* Default host value settings. */
 
3266
  host.name = NULL;
 
3267
  host.password = NULL;
 
3268
  host.enable = NULL;
 
3269
  host.logfile = NULL;
 
3270
  host.config = NULL;
 
3271
  host.lines = -1;
 
3272
  host.motd = default_motd;
 
3273
 
 
3274
  /* Install top nodes. */
 
3275
  install_node (&view_node, NULL);
 
3276
  install_node (&enable_node, NULL);
 
3277
  install_node (&auth_node, NULL);
 
3278
  install_node (&auth_enable_node, NULL);
 
3279
  install_node (&config_node, config_write_host);
 
3280
 
 
3281
  /* Each node's basic commands. */
 
3282
  install_element (VIEW_NODE, &show_version_cmd);
 
3283
  if (terminal)
 
3284
    {
 
3285
      install_element (VIEW_NODE, &config_list_cmd);
 
3286
      install_element (VIEW_NODE, &config_exit_cmd);
 
3287
      install_element (VIEW_NODE, &config_quit_cmd);
 
3288
      install_element (VIEW_NODE, &config_help_cmd);
 
3289
      install_element (VIEW_NODE, &config_enable_cmd);
 
3290
      install_element (VIEW_NODE, &config_terminal_length_cmd);
 
3291
      install_element (VIEW_NODE, &config_terminal_no_length_cmd);
 
3292
    }
 
3293
 
 
3294
  if (terminal)
 
3295
    {
 
3296
      install_default (ENABLE_NODE);
 
3297
      install_element (ENABLE_NODE, &config_disable_cmd);
 
3298
      install_element (ENABLE_NODE, &config_terminal_cmd);
 
3299
      install_element (ENABLE_NODE, &copy_runningconfig_startupconfig_cmd);
 
3300
    }
 
3301
  install_element (ENABLE_NODE, &show_startup_config_cmd);
 
3302
  install_element (ENABLE_NODE, &show_version_cmd);
 
3303
  install_element (ENABLE_NODE, &config_terminal_length_cmd);
 
3304
  install_element (ENABLE_NODE, &config_terminal_no_length_cmd);
 
3305
 
 
3306
  if (terminal)
 
3307
    install_default (CONFIG_NODE);
 
3308
  install_element (CONFIG_NODE, &hostname_cmd);
 
3309
  install_element (CONFIG_NODE, &no_hostname_cmd);
 
3310
  install_element (CONFIG_NODE, &password_cmd);
 
3311
  install_element (CONFIG_NODE, &password_text_cmd);
 
3312
  install_element (CONFIG_NODE, &enable_password_cmd);
 
3313
  install_element (CONFIG_NODE, &enable_password_text_cmd);
 
3314
  install_element (CONFIG_NODE, &no_enable_password_cmd);
 
3315
  if (terminal)
 
3316
    {
 
3317
      install_element (CONFIG_NODE, &config_log_stdout_cmd);
 
3318
      install_element (CONFIG_NODE, &no_config_log_stdout_cmd);
 
3319
      install_element (CONFIG_NODE, &config_log_file_cmd);
 
3320
      install_element (CONFIG_NODE, &no_config_log_file_cmd);
 
3321
      install_element (CONFIG_NODE, &config_log_syslog_cmd);
 
3322
      install_element (CONFIG_NODE, &config_log_syslog_facility_cmd);
 
3323
      install_element (CONFIG_NODE, &no_config_log_syslog_cmd);
 
3324
      install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd);
 
3325
      install_element (CONFIG_NODE, &config_log_trap_cmd);
 
3326
      install_element (CONFIG_NODE, &no_config_log_trap_cmd);
 
3327
      install_element (CONFIG_NODE, &config_log_record_priority_cmd);
 
3328
      install_element (CONFIG_NODE, &no_config_log_record_priority_cmd);
 
3329
      install_element (CONFIG_NODE, &service_password_encrypt_cmd);
 
3330
      install_element (CONFIG_NODE, &no_service_password_encrypt_cmd);
 
3331
      install_element (CONFIG_NODE, &banner_motd_default_cmd);
 
3332
      install_element (CONFIG_NODE, &no_banner_motd_cmd);
 
3333
      install_element (CONFIG_NODE, &service_terminal_length_cmd);
 
3334
      install_element (CONFIG_NODE, &no_service_terminal_length_cmd);
 
3335
    }
 
3336
 
 
3337
  if (terminal)
 
3338
    {
 
3339
      install_element(VIEW_NODE, &show_thread_cpu_cmd);
 
3340
      install_element(ENABLE_NODE, &show_thread_cpu_cmd);
 
3341
    }
 
3342
  srand(time(NULL));
 
3343
}